#include #include #include #include #include #include #include #include #include #include #include #include #include "generateMock_conf.h" #include "gslIntegrate.hpp" #include #include "simulation_loader.hpp" using namespace std; using namespace CosmoTool; #define LIGHT_SPEED 299792.458 static double gadgetUnit=1e-3; SimuData *doLoadMultidark(const char *multidarkname) { SimuData *outd; FILE *fp; int actualNumPart; outd = new SimuData; cout << "opening multidark file " << multidarkname << endl; fp = fopen(multidarkname, "r"); if (fp == NULL) { cout << "could not open file!" << endl; return 0; } fscanf(fp, "%f\n", &outd->BoxSize); fscanf(fp, "%f\n", &outd->Omega_M); fscanf(fp, "%f\n", &outd->Hubble); fscanf(fp, "%f\n", &outd->time); fscanf(fp, "%ld\n", &outd->NumPart); outd->time = 1./(1.+outd->time); // convert to scale factor outd->TotalNumPart = outd->NumPart; outd->Omega_Lambda = 1.0 - outd->Omega_M; for (int k = 0; k < 3; k++) outd->Pos[k] = new float[outd->NumPart]; outd->Vel[2] = new float[outd->NumPart]; outd->Id = new int[outd->NumPart]; long *uniqueID = new long[outd->NumPart]; outd->new_attribute("uniqueID", uniqueID, delete_adaptor); cout << "loading multidark particles" << endl; actualNumPart = 0; for (int i = 0; i < outd->NumPart; i++) { fscanf(fp, "%d %f %f %f %f\n", &outd->Id[i], &outd->Pos[0][i], &outd->Pos[1][i], &outd->Pos[2][i], &outd->Vel[2][i]); uniqueID[i] = 1; //uniqueID[i] = 1 * outd->Id[i]; if (outd->Id[i] == -99 && outd->Pos[0][i] == -99 && outd->Pos[1][i] == -99 && outd->Pos[2][i] == -99 && outd->Vel[2][i] == -99) { break; } else { actualNumPart++; } } fclose(fp); outd->NumPart = actualNumPart; outd->TotalNumPart = actualNumPart; return outd; } static double cubic(double a) { return a*a*a; } struct TotalExpansion { double Omega_M, Omega_L; double operator()(double z) { return 1/sqrt(Omega_M*cubic(1+z) + Omega_L); } }; Interpolate make_cosmological_redshift(double OM, double OL, double z0, double z1, int N = 5000) { TotalExpansion e_computer; double D_tilde, Q, Qprime; InterpolatePairs pairs; e_computer.Omega_M = OM; e_computer.Omega_L = OL; pairs.resize(N); ofstream f("comoving_distance.txt"); for (int i = 0; i < N; i++) { double z = z0 + (z1-z0)/N*i; pairs[i].second = z; pairs[i].first = gslIntegrate(e_computer, 0, z, 1e-3); f << z << " " << pairs[i].first << endl; } return buildFromVector(pairs); } void metricTransform(SimuData *data, int axis, bool reshift, bool pecvel, double*& expfact, bool cosmo_flag) { int x0, x1, x2; switch (axis) { case 0: x0 = 1; x1 = 2; x2 = 0; break; case 1: x0 = 0; x1 = 2; x2 = 1; break; case 2: x0 = 0; x1 = 1; x2 = 2; break; default: abort(); } double z0 = 1/data->time - 1; Interpolate z_vs_D = make_cosmological_redshift(data->Omega_M, data->Omega_Lambda, 0., z0+8*data->BoxSize*100/LIGHT_SPEED); // Redshift 2*z0 should be sufficient ? This is fragile. //A proper solver is needed here. double z_base = reshift ? z0 : 0; TotalExpansion e_computer; double baseComovingDistance; expfact = new double[data->NumPart]; cout << "Using base redshift z=" << z0 << " " << z0+8*data->BoxSize*100/LIGHT_SPEED << endl; e_computer.Omega_M = data->Omega_M; e_computer.Omega_L = data->Omega_Lambda; baseComovingDistance = LIGHT_SPEED/100.* gslIntegrate(e_computer, 0, z0, 1e-3); cout << "Comoving distance = " << baseComovingDistance << " Mpc/h" << endl; for (uint32_t i = 0; i < data->NumPart; i++) { float& x = data->Pos[x0][i]; float& y = data->Pos[x1][i]; float& z = data->Pos[x2][i]; float& v = data->Vel[2][i]; float z_old = z; double reduced_red = (z + baseComovingDistance)*100./LIGHT_SPEED; try { // Distorted redshift if (reduced_red == 0) z = 0; else if (cosmo_flag) z = (z_vs_D.compute(reduced_red)-z_base)*LIGHT_SPEED/100.; else z = reduced_red*LIGHT_SPEED/100.0; expfact[i] = z / z_old; // Add peculiar velocity if (pecvel) z += v/100; } catch(const InvalidRangeException& e) { cout << "Trying to interpolate out of the tabulated range." << endl; cout << "The offending value is z=" << reduced_red << endl; abort(); } } } void generateOutput(SimuData *data, int axis, const std::string& fname) { UnformattedWrite f(fname); cout << "Generating output particles to " << fname << endl; int x0, x1, x2; switch (axis) { case 0: x0 = 1; x1 = 2; x2 = 0; break; case 1: x0 = 0; x1 = 2; x2 = 1; break; case 2: x0 = 0; x1 = 1; x2 = 2; break; default: abort(); } f.beginCheckpoint(); f.writeInt32(data->NumPart); f.endCheckpoint(); cout << "Writing X components..." << endl; f.beginCheckpoint(); for (uint32_t i = 0; i < data->NumPart; i++) { f.writeReal32(data->Pos[x0][i]); } f.endCheckpoint(); cout << "Writing Y components..." << endl; f.beginCheckpoint(); for (uint32_t i = 0; i < data->NumPart; i++) { f.writeReal32(data->Pos[x1][i]); } f.endCheckpoint(); cout << "Writing Z components..." << endl; f.beginCheckpoint(); for (uint32_t i = 0; i < data->NumPart; i++) { f.writeReal32(data->Pos[x2][i]); } f.endCheckpoint(); cout << "Writing RA..." << endl; f.beginCheckpoint(); for (uint32_t i = 0; i < data->NumPart; i++) { f.writeReal32(data->Pos[x0][i]); } f.endCheckpoint(); cout << "Writing Dec..." << endl; f.beginCheckpoint(); for (uint32_t i = 0; i < data->NumPart; i++) { f.writeReal32(data->Pos[x1][i]); } f.endCheckpoint(); cout << "Writing redshift..." << endl; f.beginCheckpoint(); for (uint32_t i = 0; i < data->NumPart; i++) { f.writeReal32(data->Pos[x2][i]); } f.endCheckpoint(); long *uniqueID = data->as("uniqueID"); if (uniqueID != 0) { cout << "Writing unique ID..." << endl; f.beginCheckpoint(); for (uint32_t i = 0; i < data->NumPart; i++) { //printf("HELLO %d %d\n", i, data->Id[i]); //f.writeReal32(data->Id[i]); f.writeInt64(uniqueID[i]); } f.endCheckpoint(); } } // This function prepares the list of targets for the specified snapshot. The target list is not // cleared. That way new particles can be appended if this is a multi-file snapshot. void selectBox(SimuData *simu, std::vector& targets, generateMock_info& args_info) { float subsample = args_info.subsample_given ? args_info.subsample_arg : 1.0; double ranges[3][2] = { { args_info.rangeX_min_arg, args_info.rangeX_max_arg }, { args_info.rangeY_min_arg, args_info.rangeY_max_arg }, { args_info.rangeZ_min_arg, args_info.rangeZ_max_arg } }; for (uint32_t i = 0; i < simu->NumPart; i++) { bool acceptance = true; for (int j = 0; j < 3; j++) { acceptance = acceptance && (simu->Pos[j][i] > ranges[j][0]) && (simu->Pos[j][i] < ranges[j][1]); } if (acceptance && (drand48() <= subsample)) targets.push_back(i); } cout << "Subsample fraction: " << subsample << endl; } void createBox(SimuData *simu, long num_targets, std::vector snapshot_split, SimuData *& boxed, generateMock_info& args_info) { double *ranges = new double[6]; double *mul = new double[3]; long *simu_uniqueID = simu->as("uniqueID"); ranges[0] = args_info.rangeX_min_arg; ranges[1] = args_info.rangeX_max_arg; ranges[2] = args_info.rangeY_min_arg; ranges[3] = args_info.rangeY_max_arg; ranges[4] = args_info.rangeZ_min_arg; ranges[5] = args_info.rangeZ_max_arg; boxed = new SimuData; boxed->Hubble = simu->Hubble; boxed->Omega_M = simu->Omega_M; boxed->Omega_Lambda = simu->Omega_Lambda; boxed->time = simu->time; boxed->BoxSize = simu->BoxSize; for (int j = 0; j < 3; j++) { boxed->Pos[j] = new float[num_targets]; boxed->Vel[j] = 0; mul[j] = 1.0/(ranges[2*j+1] - ranges[2*j+0]); } cout << "Min range = " << ranges[0] << " " << ranges[2] << " " << ranges[4] << endl; cout << "Max range = " << ranges[1] << " " << ranges[3] << " " << ranges[5] << endl; cout << "Number of accepted particles: " << num_targets << endl; cout << "Rescaling factors = " << mul[0] << " " << mul[1] << " " << mul[2] << endl; long *uniqueID = new long[num_targets]; long *particle_id = new long[num_targets]; double *expansion_fac = new double[num_targets]; long *snap_split = new long[snapshot_split.size()]; int *numsnap_info = new int[1]; copy(snapshot_split.begin(), snapshot_split.end(), snap_split); *numsnap_info = snapshot_split.size(); boxed->NumPart = num_targets; boxed->new_attribute("particle_id", particle_id, delete_adaptor); boxed->new_attribute("expansion_fac", expansion_fac, delete_adaptor); boxed->new_attribute("uniqueID", uniqueID, delete_adaptor); boxed->new_attribute("mul", mul, delete_adaptor); boxed->new_attribute("ranges", ranges, delete_adaptor); boxed->new_attribute("snapshot_split", snap_split, delete_adaptor); boxed->new_attribute("num_snapshots", numsnap_info, delete_adaptor); } void buildBox(SimuData *simu, const std::vector& targets, long& loaded, SimuData *boxed, double *efac) { uint32_t k = 0; long *uniqueID = boxed->as("uniqueID"); long *simu_uniqueID = simu->as("uniqueID"); double *expansion_fac = boxed->as("expansion_fac"); double *mul = boxed->as("mul"); double *ranges = boxed->as("ranges"); long *particle_id = boxed->as("particle_id"); for (uint32_t i = 0; i < targets.size(); i++) { long pid = targets[i]; assert(loaded < targets.size()); for (int j = 0; j < 3; j++) { boxed->Pos[j][loaded] = (simu->Pos[j][pid]-ranges[j*2])*mul[j]; assert(boxed->Pos[j][loaded] > 0); assert(boxed->Pos[j][loaded] < 1); } particle_id[loaded] = pid; uniqueID[loaded] = (simu_uniqueID != 0) ? simu_uniqueID[pid] : 0; expansion_fac[loaded] = efac[pid]; loaded++; k++; } } void saveBox(SimuData *&boxed, const std::string& outbox) { double *ranges = boxed->as("ranges"); NcFile f(outbox.c_str(), NcFile::Replace); long *particle_id = boxed->as("particle_id"); double *expansion_fac = boxed->as("expansion_fac"); long *snapshot_split = boxed->as("snapshot_split"); int num_snapshots = *boxed->as("num_snapshots"); long *uniqueID = boxed->as("uniqueID"); f.add_att("range_x_min", ranges[0]); f.add_att("range_x_max", ranges[1]); f.add_att("range_y_min", ranges[2]); f.add_att("range_y_max", ranges[3]); f.add_att("range_z_min", ranges[4]); f.add_att("range_z_max", ranges[5]); f.add_att("mask_index", -1); NcDim *NumPart_dim = f.add_dim("numpart_dim", boxed->NumPart); NcDim *NumSnap_dim = f.add_dim("numsnap_dim", num_snapshots); NcVar *v = f.add_var("particle_ids", ncLong, NumPart_dim); NcVar *v2 = f.add_var("expansion", ncDouble, NumPart_dim); NcVar *v3 = f.add_var("snapshot_split", ncLong, NumSnap_dim); v->put(particle_id, boxed->NumPart); v2->put(expansion_fac, boxed->NumPart); v3->put(snapshot_split, num_snapshots); if (uniqueID != 0) { NcVar *v4 = f.add_var("unique_ids", ncLong, NumPart_dim); v4->put(uniqueID, boxed->NumPart); } } void makeBoxFromParameter(SimuData *simu, SimuData* &boxed, generateMock_info& args_info) { NcFile f(args_info.inputParameter_arg); NcVar *v; long *particle_id; double *expansion_fac; long *uniqueID; long *snapshot_split; int *num_snapshots = new int[1]; boxed = new SimuData; boxed->Hubble = simu->Hubble; boxed->Omega_M = simu->Omega_M; boxed->Omega_Lambda = simu->Omega_Lambda; boxed->time = simu->time; boxed->BoxSize = simu->BoxSize; NcVar *v_id = f.get_var("particle_ids"); NcVar *v_snap = f.get_var("snapshot_split"); long *edges1; long *dim_snap; double *ranges; double *mul; edges1 = v_id->edges(); dim_snap = v_snap->edges(); assert(v_id->num_dims()==1); assert(v_snap->num_dims()==1); boxed->NumPart = edges1[0]; *num_snapshots = dim_snap[0]; delete[] dim_snap; delete[] edges1; particle_id = new long[boxed->NumPart]; uniqueID = new long[boxed->NumPart]; mul = new double[3]; ranges = new double[6]; snapshot_split = new long[*num_snapshots]; boxed->new_attribute("uniqueID", uniqueID, delete_adaptor); boxed->new_attribute("mul", mul, delete_adaptor); boxed->new_attribute("ranges", ranges, delete_adaptor); boxed->new_attribute("particle_id", particle_id, delete_adaptor); boxed->new_attribute("num_snapshots", num_snapshots, delete_adaptor); boxed->new_attribute("snapshot_split", snapshot_split, delete_adaptor); v_id->get(particle_id, boxed->NumPart); v_snap->get(snapshot_split, *num_snapshots); ranges[0] = f.get_att("range_x_min")->as_double(0); ranges[1] = f.get_att("range_x_max")->as_double(0); ranges[2] = f.get_att("range_y_min")->as_double(0); ranges[3] = f.get_att("range_y_max")->as_double(0); ranges[4] = f.get_att("range_z_min")->as_double(0); ranges[5] = f.get_att("range_z_max")->as_double(0); for (int j = 0; j < 3; j++) { boxed->Pos[j] = new float[boxed->NumPart]; boxed->Vel[j] = 0; mul[j] = 1.0/(ranges[2*j+1] - ranges[2*j+0]); } uint32_t k = 0; NcVar *v_uniq = f.get_var("unique_ids"); v_uniq->get(uniqueID, boxed->NumPart); } string format_outfile(const std::string& base, int id) { ostringstream oss; oss << base << id; return oss.str(); } int main(int argc, char **argv) { generateMock_info args_info; generateMock_conf_params args_params; SimuData *simu, *simuOut; SimulationLoader *loader; generateMock_conf_init(&args_info); generateMock_conf_params_init(&args_params); args_params.check_required = 0; if (generateMock_conf_ext (argc, argv, &args_info, &args_params)) return 1; if (!args_info.configFile_given) { if (generateMock_conf_required (&args_info, GENERATEMOCK_CONF_PACKAGE)) return 1; } else { args_params.check_required = 1; args_params.initialize = 0; if (generateMock_conf_config_file (args_info.configFile_arg, &args_info, &args_params)) return 1; } generateMock_conf_print_version(); gadgetUnit=args_info.gadgetUnit_arg; if (args_info.ramsesBase_given || args_info.ramsesId_given) { if (args_info.ramsesBase_given && args_info.ramsesId_given) { /* simu = doLoadRamses(args_info.ramsesBase_arg, args_info.ramsesId_arg, args_info.axis_arg, false);*/ } else { cerr << "Both ramsesBase and ramsesId are required to be able to load snapshots" << endl; return 1; } if (simu == 0) { cerr << "Error while loading" << endl; return 1; } } else if (args_info.gadget_given || args_info.flash_given || args_info.multidark_given) { if (args_info.gadget_given && args_info.flash_given) { cerr << "Do not know which file to use: Gadget or Flash ?" << endl; return 1; } /* if (args_info.multidark_given) { simu = doLoadMultidark(args_info.multidark_arg); } if (args_info.gadget_given) { simu = doLoadSimulation(args_info.gadget_arg, args_info.axis_arg, false, myLoadGadget); } if (args_info.flash_given) { simu = doLoadSimulation(args_info.flash_arg, args_info.axis_arg, false, loadFlashMulti); } */ loader = gadgetLoader(args_info.gadget_arg, 1/args_info.gadgetUnit_arg, NEED_POSITION|NEED_VELOCITY|NEED_GADGET_ID); if (loader == 0) { cerr << "Error while loading " << endl; return 1; } simu = loader->getHeader(); } else { cerr << "Either a ramses snapshot or a gadget snapshot is required." << endl; return 1; } { SimuData *header = loader->getHeader(); cout << "Hubble = " << header->Hubble << endl; cout << "Boxsize = " << header->BoxSize << endl; cout << "Omega_M = " << header->Omega_M << endl; cout << "Omega_Lambda = " << header->Omega_Lambda << endl; } double *expfact; for (int nf = 0; nf < loader->num_files(); nf++) { vector targets, split; long loaded = 0; SimuData *simu; cout << "Loading file number " << nf+1 << " / " << loader->num_files() << endl; simu = loader->loadFile(nf); metricTransform(simu, args_info.axis_arg, args_info.preReShift_flag, args_info.peculiarVelocities_flag, expfact, args_info.cosmo_flag); if (args_info.inputParameter_given) makeBoxFromParameter(simu, simuOut, args_info); else { selectBox(simu, targets, args_info); split.push_back(targets.size()); createBox(simu, targets.size(), split, simuOut, args_info); } buildBox(simu, targets, loaded, simuOut, expfact); saveBox(simuOut, format_outfile(args_info.outputParameter_arg, nf)); generateOutput(simuOut, args_info.axis_arg, format_outfile(args_info.output_arg, nf)); delete simu; delete simuOut; } printf("Done!\n"); return 0; }