/* output_gadget2.cc - This file is part of MUSIC - a code to generate multi-scale initial conditions for cosmological simulations Copyright (C) 2010 Oliver Hahn */ #include #include "log.hh" #include "output.hh" #include "mg_interp.hh" #include "mesh.hh" template< typename T_store=float > class gadget2_2comp_output_plugin : public output_plugin { protected: std::ofstream ofs_; bool bmultimass_; typedef struct io_header { unsigned int npart[6]; double mass[6]; double time; double redshift; int flag_sfr; int flag_feedback; unsigned int npartTotal[6]; int flag_cooling; int num_files; double BoxSize; double Omega0; double OmegaLambda; double HubbleParam; int flag_stellarage; int flag_metals; unsigned int npartTotalHighWord[6]; int flag_entropy_instead_u; int flag_doubleprecision; int flag_ic_info; char fill[52]; }header; header header_; std::string fname; bool do_glass_; std::string fname_glass_baryon_, fname_glass_cdm_; enum iofields { id_dm_mass, id_dm_vel, id_dm_pos, id_gas_vel, id_gas_rho, id_gas_temp, id_gas_pos }; size_t np_fine_gas_, np_fine_dm_, np_coarse_dm_; size_t block_buf_size_; unsigned long long npartmax_; unsigned nfiles_; //bool bbndparticles_; bool bmorethan2bnd_; bool kpcunits_; double YHe_; void distribute_particles( unsigned nfiles, size_t nfine_dm, size_t nfine_gas, size_t ncoarse, std::vector& nfdm_pf, std::vector& nfgas_pf, std::vector& nc_pf ) { nfdm_pf.assign( nfiles, 0 ); nfgas_pf.assign( nfiles, 0 ); nc_pf.assign( nfiles, 0 ); size_t ntotal = nfine_dm + nfine_gas + ncoarse; size_t nnominal = (size_t)((double)ntotal/(double)nfiles); size_t nf_dm_assigned = 0, nf_gas_assigned = 0, nc_assigned = 0; for( unsigned i=0; i 0 ) { nfdm_pf[i] = std::min( nnominal/2ul, nfine_dm-nf_dm_assigned ); nf_dm_assigned += nfdm_pf[i]; nfgas_pf[i] = std::min( nnominal/2ul, nfine_gas-nf_gas_assigned ); nf_gas_assigned += nfgas_pf[i]; }else{ nfdm_pf[i] = std::min( nnominal, nfine_dm-nf_dm_assigned ); nf_dm_assigned += nfdm_pf[i]; } // once all fine particles are assigned, start with the coarse if( nf_dm_assigned+nf_gas_assigned == nfine_dm+nfine_gas ) { nc_pf[i] = std::min( nnominal-(size_t)(nfdm_pf[i]+nfgas_pf[i]), ncoarse-nc_assigned ); nc_assigned += nc_pf[i]; } } // make sure all particles are assigned nfdm_pf[ nfiles-1 ] += nfine_dm-nf_dm_assigned; nfgas_pf[ nfiles-1 ] += nfine_gas-nf_gas_assigned; nc_pf[ nfiles-1 ] += ncoarse-nc_assigned; } std::ifstream& open_and_check( std::string ffname, size_t npart ) { std::ifstream ifs( ffname.c_str(), std::ios::binary ); unsigned long long blk, expected; ifs.read( (char*)&blk, sizeof(unsigned long long) ); expected = ((unsigned long long) npart*(unsigned long long)sizeof(T_store)); if( blk != expected ) { LOGERR("Internal consistency error in gadget2 output plug-in, open_and_check"); LOGERR("Expected %d particles (%lld bytes) in temp file %s but found %lld",npart, expected ,ffname.c_str(), blk); //throw std::runtime_error("Internal consistency error in gadget2 output plug-in"); } return ifs; } class pistream : public std::ifstream { public: pistream (std::string fname, size_t npart, size_t offset=0 ) : std::ifstream( fname.c_str(), std::ios::binary ) { size_t blk; if( !this->good() ) { LOGERR("Could not open buffer file in gadget2 output plug-in"); throw std::runtime_error("Could not open buffer file in gadget2 output plug-in"); } this->read( (char*)&blk, sizeof(size_t) ); if( blk != npart*sizeof(T_store) ) { LOGERR("Internal consistency error in gadget2 output plug-in"); LOGERR("Expected %ld bytes in temp file but found %ld",npart*sizeof(T_store),blk); throw std::runtime_error("Internal consistency error in gadget2 output plug-in"); } this->seekg( offset+sizeof(size_t), std::ios::beg ); } pistream () { } void open(std::string fname, size_t npart, size_t offset=0 ) { std::ifstream::open( fname.c_str(), std::ios::binary ); size_t blk; if( !this->good() ) { LOGERR("Could not open buffer file \'%s\' in gadget2 output plug-in",fname.c_str()); throw std::runtime_error("Could not open buffer file in gadget2 output plug-in"); } this->read( (char*)&blk, sizeof(size_t) ); if( blk != npart*sizeof(T_store) ) { LOGERR("Internal consistency error in gadget2 output plug-in"); LOGERR("Expected %ld bytes in temp file but found %ld",npart*sizeof(T_store),blk); throw std::runtime_error("Internal consistency error in gadget2 output plug-in"); } this->seekg( offset+sizeof(size_t), std::ios::beg ); } }; class postream : public std::fstream { public: postream (std::string fname, size_t npart, size_t offset=0 ) : std::fstream( fname.c_str(), std::ios::binary|std::ios::in|std::ios::out ) { size_t blk; if( !this->good() ) { LOGERR("Could not open buffer file in gadget2 output plug-in"); throw std::runtime_error("Could not open buffer file in gadget2 output plug-in"); } this->read( (char*)&blk, sizeof(size_t) ); if( blk != npart*sizeof(T_store) ) { LOGERR("Internal consistency error in gadget2 output plug-in"); LOGERR("Expected %ld bytes in temp file but found %ld",npart*sizeof(T_store),blk); throw std::runtime_error("Internal consistency error in gadget2 output plug-in"); } this->seekg( offset, std::ios::cur ); this->seekp( offset+sizeof(size_t), std::ios::beg ); } postream () { } void open(std::string fname, size_t npart, size_t offset=0 ) { if( is_open() ) this->close(); std::fstream::open( fname.c_str(), std::ios::binary|std::ios::in|std::ios::out ); size_t blk; if( !this->good() ) { LOGERR("Could not open buffer file \'%s\' in gadget2 output plug-in",fname.c_str()); throw std::runtime_error("Could not open buffer file in gadget2 output plug-in"); } this->read( (char*)&blk, sizeof(size_t) ); if( blk != npart*sizeof(T_store) ) { LOGERR("Internal consistency error in gadget2 output plug-in"); LOGERR("Expected %ld bytes in temp file but found %ld",npart*sizeof(T_store),blk); throw std::runtime_error("Internal consistency error in gadget2 output plug-in"); } this->seekg( offset, std::ios::cur ); this->seekp( offset+sizeof(size_t), std::ios::beg ); } }; void assemble_gadget_file( void ) { //............................................................................ //... copy from the temporary files, interleave the data and save ............ char fnx[256],fny[256],fnz[256],fnvx[256],fnvy[256],fnvz[256],fnm[256]; char fnbx[256], fnby[256], fnbz[256], fnbvx[256], fnbvy[256], fnbvz[256]; sprintf( fnx, "___ic_temp_%05d.bin", 100*id_dm_pos+0 ); sprintf( fny, "___ic_temp_%05d.bin", 100*id_dm_pos+1 ); sprintf( fnz, "___ic_temp_%05d.bin", 100*id_dm_pos+2 ); sprintf( fnvx, "___ic_temp_%05d.bin", 100*id_dm_vel+0 ); sprintf( fnvy, "___ic_temp_%05d.bin", 100*id_dm_vel+1 ); sprintf( fnvz, "___ic_temp_%05d.bin", 100*id_dm_vel+2 ); sprintf( fnm, "___ic_temp_%05d.bin", 100*id_dm_mass ); sprintf( fnbx, "___ic_temp_%05d.bin", 100*id_gas_pos+0 ); sprintf( fnby, "___ic_temp_%05d.bin", 100*id_gas_pos+1 ); sprintf( fnbz, "___ic_temp_%05d.bin", 100*id_gas_pos+2 ); sprintf( fnbvx, "___ic_temp_%05d.bin", 100*id_gas_vel+0 ); sprintf( fnbvy, "___ic_temp_%05d.bin", 100*id_gas_vel+1 ); sprintf( fnbvz, "___ic_temp_%05d.bin", 100*id_gas_vel+2 ); pistream iffs1, iffs2, iffs3; /*const size_t nptot = header_.npart[1]+header_.npart[2]+header_.npart[5], npgas = header_.npart[2], npcdm = nptot-npgas;*/ const size_t nptot = np_fine_gas_+np_fine_dm_+np_coarse_dm_, //npgas = np_fine_gas_, npcdm = np_fine_dm_+np_coarse_dm_; size_t wrote_coarse = 0, wrote_gas = 0, wrote_dm = 0; size_t npleft = nptot, n2read = std::min(block_buf_size_,npleft); if( header_.npart[5] > 0 ) LOGERR("Multi-resolution setup not supported for 2comp hack"); std::cout << " - Writing " << nptot << " particles to Gadget file...\n" << " type 1 : " << header_.npart[1] << "\n" << " type 2 : " << header_.npart[2] << "\n" << " type 5 : " << header_.npart[5] << "\n"; bool bbaryons = np_fine_gas_ > 0; std::vector adata3; adata3.reserve( 3*block_buf_size_ ); T_store *tmp1, *tmp2, *tmp3; tmp1 = new T_store[block_buf_size_]; tmp2 = new T_store[block_buf_size_]; tmp3 = new T_store[block_buf_size_]; std::vector nfdm_per_file, nfgas_per_file, nc_per_file; distribute_particles( nfiles_, np_fine_dm_, np_fine_gas_, np_coarse_dm_, nfdm_per_file, nfgas_per_file, nc_per_file ); if( nfiles_ > 1 ) { std::cout << " - Gadget2 : distributing particles to " << nfiles_ << " files\n" << " " << std::setw(12) << "type 1" << "," << std::setw(12) << "type 2" << "," << std::setw(12) << "type 5" << std::endl; for( unsigned i=0; i= 1ul<<32 ) { bneed_long_ids = true; LOGWARN("Need long particle IDs, make sure to enable in Gadget!"); } for( unsigned ifile=0; ifile 1 ) { char ffname[256]; sprintf(ffname,"%s.%d",fname_.c_str(), ifile); ofs_.open(ffname, std::ios::binary|std::ios::trunc ); }else{ ofs_.open(fname_.c_str(), std::ios::binary|std::ios::trunc ); } size_t np_this_file = nfgas_per_file[ifile] + nfdm_per_file[ifile] + nc_per_file[ifile]; int blksize = sizeof(header); //... write the header ....................................................... header this_header( header_ ); this_header.npart[1] = nfdm_per_file[ifile]; this_header.npart[2] = nfgas_per_file[ifile]; this_header.npart[5] = nc_per_file[ifile]; ofs_.write( (char *)&blksize, sizeof(int) ); ofs_.write( (char *)&this_header, sizeof(header) ); ofs_.write( (char *)&blksize, sizeof(int) ); //... particle positions .................................................. blksize = 3ul*np_this_file*sizeof(T_store); ofs_.write( (char *)&blksize, sizeof(int) ); npleft = nfdm_per_file[ifile];//+nc_per_file[ifile]; n2read = std::min(curr_block_buf_size,npleft); iffs1.open( fnx, npcdm, wrote_dm*sizeof(T_store) ); iffs2.open( fny, npcdm, wrote_dm*sizeof(T_store) ); iffs3.open( fnz, npcdm, wrote_dm*sizeof(T_store) ); while( n2read > 0ul ) { iffs1.read( reinterpret_cast(&tmp1[0]), n2read*sizeof(T_store) ); iffs2.read( reinterpret_cast(&tmp2[0]), n2read*sizeof(T_store) ); iffs3.read( reinterpret_cast(&tmp3[0]), n2read*sizeof(T_store) ); for( size_t i=0; i(&adata3[0]), 3*n2read*sizeof(T_store) ); adata3.clear(); npleft -= n2read; n2read = std::min( curr_block_buf_size,npleft ); } iffs1.close(); iffs2.close(); iffs3.close(); if( bbaryons && nfgas_per_file[ifile] > 0ul ) { iffs1.open( fnbx, npcdm, wrote_gas*sizeof(T_store) ); iffs2.open( fnby, npcdm, wrote_gas*sizeof(T_store) ); iffs3.open( fnbz, npcdm, wrote_gas*sizeof(T_store) ); npleft = nfgas_per_file[ifile]; n2read = std::min(curr_block_buf_size,npleft); while( n2read > 0ul ) { iffs1.read( reinterpret_cast(&tmp1[0]), n2read*sizeof(T_store) ); iffs2.read( reinterpret_cast(&tmp2[0]), n2read*sizeof(T_store) ); iffs3.read( reinterpret_cast(&tmp3[0]), n2read*sizeof(T_store) ); for( size_t i=0; i(&adata3[0]), 3*n2read*sizeof(T_store) ); adata3.clear(); npleft -= n2read; n2read = std::min( curr_block_buf_size,npleft ); } iffs1.close(); iffs2.close(); iffs3.close(); } ofs_.write( reinterpret_cast(&blksize), sizeof(int) ); //... particle velocities .................................................. blksize = 3ul*np_this_file*sizeof(T_store); ofs_.write( reinterpret_cast(&blksize), sizeof(int) ); iffs1.open( fnvx, npcdm, wrote_dm*sizeof(T_store) ); iffs2.open( fnvy, npcdm, wrote_dm*sizeof(T_store) ); iffs3.open( fnvz, npcdm, wrote_dm*sizeof(T_store) ); npleft = nfdm_per_file[ifile];//+nc_per_file[ifile]; n2read = std::min(curr_block_buf_size,npleft); while( n2read > 0ul ) { iffs1.read( reinterpret_cast(&tmp1[0]), n2read*sizeof(T_store) ); iffs2.read( reinterpret_cast(&tmp2[0]), n2read*sizeof(T_store) ); iffs3.read( reinterpret_cast(&tmp3[0]), n2read*sizeof(T_store) ); for( size_t i=0; i(&adata3[0]), 3*n2read*sizeof(T_store) ); adata3.clear(); npleft -= n2read; n2read = std::min( curr_block_buf_size,npleft ); } iffs1.close(); iffs2.close(); iffs3.close(); if( bbaryons && nfgas_per_file[ifile] > 0ul ) { iffs1.open( fnbvx, npcdm, wrote_gas*sizeof(T_store) ); iffs2.open( fnbvy, npcdm, wrote_gas*sizeof(T_store) ); iffs3.open( fnbvz, npcdm, wrote_gas*sizeof(T_store) ); npleft = nfgas_per_file[ifile]; n2read = std::min(curr_block_buf_size,npleft); while( n2read > 0ul ) { iffs1.read( reinterpret_cast(&tmp1[0]), n2read*sizeof(T_store) ); iffs2.read( reinterpret_cast(&tmp2[0]), n2read*sizeof(T_store) ); iffs3.read( reinterpret_cast(&tmp3[0]), n2read*sizeof(T_store) ); for( size_t i=0; i(&adata3[0]), 3*n2read*sizeof(T_store) ); adata3.clear(); npleft -= n2read; n2read = std::min( curr_block_buf_size,npleft ); } iffs1.close(); iffs2.close(); iffs3.close(); } ofs_.write( reinterpret_cast(&blksize), sizeof(int) ); //... particle IDs .......................................................... std::vector short_ids; std::vector long_ids; if( bneed_long_ids ) long_ids.assign(curr_block_buf_size,0); else short_ids.assign(curr_block_buf_size,0); npleft = np_this_file; n2read = std::min(curr_block_buf_size,npleft); blksize = sizeof(unsigned)*np_this_file; if( bneed_long_ids ) blksize = sizeof(size_t)*np_this_file; //... generate contiguous IDs and store in file .. ofs_.write( reinterpret_cast(&blksize), sizeof(int) ); while( n2read > 0ul ) { if( bneed_long_ids ) { for( size_t i=0; i(&long_ids[0]), n2read*sizeof(size_t) ); }else{ for( size_t i=0; i(&short_ids[0]), n2read*sizeof(unsigned) ); } npleft -= n2read; n2read = std::min( curr_block_buf_size,npleft ); } ofs_.write( reinterpret_cast(&blksize), sizeof(int) ); std::vector().swap( short_ids ); std::vector().swap( long_ids ); //... particle masses ....................................................... // multi-mass not supported here ofs_.flush(); ofs_.close(); wrote_gas += nfgas_per_file[ifile]; wrote_dm += nfdm_per_file[ifile] + nc_per_file[ifile]; wrote_coarse += nc_per_file[ifile]; } delete[] tmp1; delete[] tmp2; delete[] tmp3; remove( fnbx ); remove( fnby ); remove( fnbz ); remove( fnx ); remove( fny ); remove( fnz ); remove( fnbvx ); remove( fnbvy ); remove( fnbvz ); remove( fnvx ); remove( fnvy ); remove( fnvz ); remove( fnm ); } void get_cic_displacement( size_t icoord, const float* ppos, size_t np, float l, const grid_hierarchy& gh, T_store* valp ) { size_t N = gh.size(gh.levelmax(), 0); float facconv = 1.f / l * (float)N/(float)(1ul<("output","gadget_blksize",2*1048576); //... ensure that everyone knows we want to do SPH cf.insertValue("setup","do_SPH","yes"); //bbndparticles_ = !cf_.getValueSafe("output","gadget_nobndpart",false); npartmax_ = 1<<30; nfiles_ = cf.getValueSafe("output","gadget_num_files",1); /****************************************/ if (nfiles_ > 1 ) { for( unsigned ifile=0; ifile levelmin_ +1) bmorethan2bnd_ = true; bmultimass_ = true; if( levelmax_ == levelmin_ ) bmultimass_ = false; for( int i=0; i<6; ++i ) { header_.npart[i] = 0; header_.npartTotal[i] = 0; header_.npartTotalHighWord[i] = 0; header_.mass[i] = 0.0; } YHe_ = cf.getValueSafe("cosmology","YHe",0.248); gamma_ = cf.getValueSafe("cosmology","gamma",5.0/3.0); do_baryons_ = cf.getValueSafe("setup","baryons",false); omegab_ = cf.getValueSafe("cosmology","Omega_b",0.045); //... write displacements in kpc/h rather than Mpc/h? kpcunits_ = cf.getValueSafe("output","gadget_usekpc",false); do_glass_ = cf.getValueSafe("output","glass", false); if( do_glass_ ) { LOGINFO("Will use provided glass rather than Cartesian mesh for particle placement."); fname_glass_cdm_ = cf.getValue("output","glass_file_cdm"); if( do_baryons_ ) fname_glass_baryon_ = fname_glass_cdm_;//cf.getValue("output","glass_file_baryon"); } //... set time ...................................................... header_.redshift = cf.getValue("setup","zstart"); header_.time = 1.0/(1.0+header_.redshift); //... SF flags header_.flag_sfr = 0; header_.flag_feedback = 0; header_.flag_cooling = 0; //... header_.num_files = nfiles_; header_.BoxSize = cf.getValue("setup","boxlength"); header_.Omega0 = cf.getValue("cosmology","Omega_m"); omegam_ = header_.Omega0; omegac_ = omegam_ - omegab_; header_.OmegaLambda = cf.getValue("cosmology","Omega_L"); header_.HubbleParam = cf.getValue("cosmology","H0"); header_.flag_stellarage = 0; header_.flag_metals = 0; header_.flag_entropy_instead_u = 0; #ifdef SINGLE_PRECISION header_.flag_doubleprecision = 0; #else header_.flag_doubleprecision = 1; #endif std::cout << "header_.flag_doubleprecision " << header_.flag_doubleprecision << "\n"; header_.flag_ic_info = 0; if( kpcunits_ ) header_.BoxSize *= 1000.0; } void write_dm_mass( const grid_hierarchy& gh ) { double rhoc = 27.7519737; // in h^2 1e10 M_sol / Mpc^3 if( kpcunits_ ) rhoc *= 10.0; // in h^2 M_sol / kpc^3 if(! do_glass_ ) { if( !do_baryons_ ) header_.mass[1] = header_.Omega0 * rhoc * pow(header_.BoxSize,3.)/pow(2,3*levelmax_); else header_.mass[1] = (header_.Omega0-omegab_) * rhoc * pow(header_.BoxSize,3.)/pow(2,3*levelmax_); } if( bmorethan2bnd_ ) { unsigned long long npcoarse = gh.count_leaf_cells(gh.levelmin(), gh.levelmax()-1); unsigned long long nwritten = 0; std::vector temp_dat; temp_dat.reserve(block_buf_size_); char temp_fname[256]; sprintf( temp_fname, "___ic_temp_%05d.bin", 100*id_dm_mass ); std::ofstream ofs_temp( temp_fname, std::ios::binary|std::ios::trunc ); unsigned long long blksize = sizeof(T_store)*npcoarse; ofs_temp.write( (char *)&blksize, sizeof(unsigned long long) ); for( int ilevel=gh.levelmax()-1; ilevel>=(int)gh.levelmin(); --ilevel ) { double pmass = 0.0; if( !do_baryons_ ) pmass = header_.Omega0 * rhoc * pow(header_.BoxSize,3.)/pow(2,3*ilevel); else pmass = (header_.Omega0-omegab_) * rhoc * pow(header_.BoxSize,3.)/pow(2,3*ilevel); for( unsigned i=0; isize(0); ++i ) for( unsigned j=0; jsize(1); ++j ) for( unsigned k=0; ksize(2); ++k ) if( ! gh.is_refined(ilevel,i,j,k) ) { if( temp_dat.size() < block_buf_size_ ) temp_dat.push_back( pmass ); else { ofs_temp.write( (char*)&temp_dat[0], sizeof(T_store)*block_buf_size_ ); nwritten += block_buf_size_; temp_dat.clear(); temp_dat.push_back( pmass ); } } } if( temp_dat.size() > 0 ) { ofs_temp.write( (char*)&temp_dat[0], sizeof(T_store)*temp_dat.size() ); nwritten+=temp_dat.size(); } if( nwritten != npcoarse ) throw std::runtime_error("Internal consistency error while writing temporary file for masses"); ofs_temp.write( (char *)&blksize, sizeof(unsigned long long) ); if( ofs_temp.bad() ) throw std::runtime_error("I/O error while writing temporary file for masses"); } else if( gh.levelmax() != gh.levelmin() ) { header_.mass[5] = header_.Omega0 * rhoc * pow(header_.BoxSize,3.)/pow(2,3*levelmin_); } } void write_dm_position( int coord, const grid_hierarchy& gh ) { //... count number of leaf cells ...// unsigned long long npcoarse = 0, npfine = 0; npfine = gh.count_leaf_cells(gh.levelmax(), gh.levelmax()); if( bmultimass_ ) npcoarse = gh.count_leaf_cells(gh.levelmin(), gh.levelmax()-1); np_fine_dm_ = npfine; np_fine_gas_ = do_baryons_? npfine : 0ul; np_coarse_dm_ = npcoarse; //... determine if we need to shift the coordinates back double *shift = NULL; if( cf_.getValueSafe("output","shift_back",false ) ) { if( coord == 0 ) std::cout << " - gadget2 output plug-in will shift particle positions back...\n"; double h = 1.0/(1<( "setup", "shift_x" )*h; shift[1] = -(double)cf_.getValue( "setup", "shift_y" )*h; shift[2] = -(double)cf_.getValue( "setup", "shift_z" )*h; } size_t npart = npfine+npcoarse; size_t nwritten = 0; size_t blksize; //... header_.npart[1] = npfine; header_.npart[5] = npcoarse; header_.npartTotal[1] = (unsigned)npfine; header_.npartTotal[5] = (unsigned)npcoarse; header_.npartTotalHighWord[1] = (unsigned)(npfine>>32); header_.npartTotalHighWord[5] = (unsigned)(npfine>>32); //header_.num_files = (int)ceil((double)npart/(double)npartmax_); //... collect displacements and convert to absolute coordinates with correct //... units std::vector temp_data; temp_data.reserve( block_buf_size_ ); double xfac = header_.BoxSize; char temp_fname[256]; sprintf( temp_fname, "___ic_temp_%05d.bin", 100*id_dm_pos+coord ); std::ofstream ofs_temp( temp_fname, std::ios::binary|std::ios::trunc ); //... if baryons are present, then stagger the two fields if( do_baryons_ && !do_glass_ ) { double h = 1. / (1<=(int)gh.levelmin(); --ilevel ) for( unsigned i=0; isize(0); ++i ) for( unsigned j=0; jsize(1); ++j ) for( unsigned k=0; ksize(2); ++k ) if( ! gh.is_refined(ilevel,i,j,k) ) { double xx[3]; gh.cell_pos(ilevel, i, j, k, xx); if( shift != NULL ) xx[coord] += shift[coord]; xx[coord] = fmod( (xx[coord]+(*gh.get_grid(ilevel))(i,j,k))*xfac + header_.BoxSize, header_.BoxSize ); if( temp_data.size() < block_buf_size_ ) temp_data.push_back( xx[coord] ); else { ofs_temp.write( (char*)&temp_data[0], sizeof(T_store)*block_buf_size_ ); nwritten += block_buf_size_; temp_data.clear(); temp_data.push_back( xx[coord] ); } } } else { std::ifstream ofg( fname_glass_cdm_.c_str(), std::ios::binary ); if( !ofg.good() ) LOGERR("could not open glass input file \'%s\'",fname_glass_cdm_.c_str()); io_header glasshead; unsigned blksz; ofg.read( reinterpret_cast(&blksz), sizeof(unsigned) ); assert( blksz == sizeof(io_header) ); ofg.read( reinterpret_cast(&glasshead), sizeof( io_header ) ); //size_t nreq = gh.size(gh.levelmax(), 0)*gh.size(gh.levelmax(), 1)*gh.size(gh.levelmax(), 2); /*if( nreq != (size_t)glasshead.npart[1] ) { LOGERR("glass file contains %d particles, but should contain %ld",glasshead.npart[1],nreq); throw std::runtime_error("glass file does not contain the right amount of particles"); }*/ ofg.read( reinterpret_cast(&blksz), sizeof(unsigned) ); ofg.read( reinterpret_cast(&blksz), sizeof(unsigned) ); //assert( blksz == glasshead.npart[1]*sizeof(float)*3 ); float lglass = glasshead.BoxSize; blksize = sizeof(T_store)*glasshead.npart[1]; //ofs_temp.write( (char *)&blksize, sizeof(int) ); ofs_temp.write( (char *)&blksize, sizeof(unsigned long long) ); header_.npart[1] = glasshead.npart[1]; header_.npartTotal[1] = glasshead.npartTotal[1]; header_.npartTotalHighWord[1] = 0; double rhoc = 27.7519737; if( kpcunits_ ) rhoc *= 10.0; // in h^2 M_sol / kpc^3 if( do_baryons_ ) header_.mass[1] = omegac_ * rhoc * pow(header_.BoxSize,3.)/(glasshead.npart[1]); else header_.mass[1] = omegam_ * rhoc * pow(header_.BoxSize,3.)/(glasshead.npart[1]); // read glass, do interpolation and write size_t npartdone=0; size_t npinter = glasshead.npart[1]; blksize = sizeof(T_store)*npinter; ofs_temp.write( (char *)&blksize, sizeof(unsigned long long) ); float *pos_tmp = new float[3*block_buf_size_]; temp_data.assign( block_buf_size_, 0.0 ); while( npartdone < npinter ) { size_t npart2read = std::min(npinter-npartdone,block_buf_size_); ofg.read( reinterpret_cast(&pos_tmp[0]), npart2read*sizeof(float)*3 ); get_cic_displacement( coord, pos_tmp, npart2read, lglass, gh, &temp_data[0] ); ofs_temp.write( (char*)&temp_data[0], sizeof(T_store)*npart2read ); // std::cout << "npart2read " << npart2read << "\n"; // std::cout << "pos temp " << temp_data[0] << " " << temp_data[1] << " " << temp_data[2] << "\n"; // std::cout << "pos temp " << temp_data[npart2read-1] << " " << temp_data[npart2read-2] << " " << temp_data[npart2read-3] <<"\n"; npartdone += npart2read; nwritten += npart2read; } delete[] pos_tmp; temp_data.clear(); // do all lower levels with standard cartesian grid for( int ilevel=gh.levelmax()-1; ilevel>=(int)gh.levelmin(); --ilevel ) for( unsigned i=0; isize(0); ++i ) for( unsigned j=0; jsize(1); ++j ) for( unsigned k=0; ksize(2); ++k ) if( ! gh.is_refined(ilevel,i,j,k) ) { double xx[3]; gh.cell_pos(ilevel, i, j, k, xx); if( shift != NULL ) xx[coord] += shift[coord]; xx[coord] = fmod( (xx[coord]+(*gh.get_grid(ilevel))(i,j,k))*xfac + header_.BoxSize, header_.BoxSize ); if( temp_data.size() < block_buf_size_ ) temp_data.push_back( xx[coord] ); else { ofs_temp.write( (char*)&temp_data[0], sizeof(T_store)*block_buf_size_ ); nwritten += block_buf_size_; temp_data.clear(); temp_data.push_back( xx[coord] ); } } } if( temp_data.size() > 0 ) { ofs_temp.write( (char*)&temp_data[0], sizeof(T_store)*temp_data.size() ); nwritten += temp_data.size(); } if( nwritten != npart ) throw std::runtime_error("Internal consistency error while writing temporary file for positions"); //... dump to temporary file ofs_temp.write( (char *)&blksize, sizeof(unsigned long long) ); if( ofs_temp.bad() ) throw std::runtime_error("I/O error while writing temporary file for positions"); ofs_temp.close(); if( shift != NULL ) delete[] shift; } void write_dm_velocity( int coord, const grid_hierarchy& gh ) { //... count number of leaf cells ...// size_t npcoarse = 0, npfine = 0; npfine = gh.count_leaf_cells(gh.levelmax(), gh.levelmax()); if( bmultimass_ ) npcoarse = gh.count_leaf_cells(gh.levelmin(), gh.levelmax()-1); header_.npart[1] = npfine; header_.npart[5] = npcoarse; header_.npartTotal[1] = npfine; header_.npartTotal[5] = npcoarse; header_.npartTotalHighWord[1] = 0; header_.npartTotalHighWord[5] = 0; //... collect displacements and convert to absolute coordinates with correct //... units std::vector temp_data; temp_data.reserve( block_buf_size_ ); float isqrta = 1.0f/sqrt(header_.time); float vfac = isqrta*header_.BoxSize; if( kpcunits_ ) vfac /= 1000.0; unsigned npart = npfine+npcoarse; unsigned nwritten = 0; unsigned long long blksize; char temp_fname[256]; sprintf( temp_fname, "___ic_temp_%05d.bin", 100*id_dm_vel+coord ); std::ofstream ofs_temp( temp_fname, std::ios::binary|std::ios::trunc ); if( !do_glass_ ) { blksize = sizeof(T_store)*npart; ofs_temp.write( (char *)&blksize, sizeof(unsigned long long) ); for( int ilevel=levelmax_; ilevel>=(int)levelmin_; --ilevel ) for( unsigned i=0; isize(0); ++i ) for( unsigned j=0; jsize(1); ++j ) for( unsigned k=0; ksize(2); ++k ) if( ! gh.is_refined(ilevel,i,j,k) ) { if( temp_data.size() < block_buf_size_ ) temp_data.push_back( (*gh.get_grid(ilevel))(i,j,k) * vfac ); else { ofs_temp.write( (char*)&temp_data[0], sizeof(T_store)*block_buf_size_ ); nwritten += block_buf_size_; temp_data.clear(); temp_data.push_back( (*gh.get_grid(ilevel))(i,j,k) * vfac ); } } } else { std::ifstream ofg( fname_glass_cdm_.c_str(), std::ios::binary ); if( !ofg.good() ) LOGERR("could not open glass input file \'%s\'",fname_glass_cdm_.c_str()); io_header glasshead; unsigned blksz; ofg.read( reinterpret_cast(&blksz), sizeof(unsigned) ); assert( blksz == sizeof(io_header) ); ofg.read( reinterpret_cast(&glasshead), sizeof( io_header ) ); ofg.read( reinterpret_cast(&blksz), sizeof(unsigned) ); ofg.read( reinterpret_cast(&blksz), sizeof(unsigned) ); //assert( blksz == glasshead.npart[1]*sizeof(float)*3 ); header_.npart[1] = glasshead.npart[1]; header_.npartTotal[1] = glasshead.npartTotal[1]; header_.npartTotalHighWord[1] = glasshead.npartTotalHighWord[1]; float lglass = glasshead.BoxSize; // read glass, do interpolation and write size_t npartdone=0; size_t npinter = glasshead.npart[1]; blksize = sizeof(T_store)*npinter; ofs_temp.write( (char *)&blksize, sizeof(unsigned long long) ); float *pos_tmp = new float[3*block_buf_size_]; temp_data.assign( block_buf_size_, 0.0 ); while( npartdone < npinter ) { size_t npart2read = std::min(npinter-npartdone,block_buf_size_); ofg.read( reinterpret_cast(&pos_tmp[0]), npart2read*sizeof(float)*3 ); get_cic_velocity( pos_tmp, npart2read, lglass, gh, &temp_data[0] ); ofs_temp.write( (char*)&temp_data[0], sizeof(T_store)*npart2read ); npartdone += npart2read; nwritten += npart2read; } delete[] pos_tmp; temp_data.clear(); for( int ilevel=levelmax_-1; ilevel>=(int)levelmin_; --ilevel ) for( unsigned i=0; isize(0); ++i ) for( unsigned j=0; jsize(1); ++j ) for( unsigned k=0; ksize(2); ++k ) if( ! gh.is_refined(ilevel,i,j,k) ) { if( temp_data.size() < block_buf_size_ ) temp_data.push_back( (*gh.get_grid(ilevel))(i,j,k) * vfac ); else { ofs_temp.write( (char*)&temp_data[0], sizeof(T_store)*block_buf_size_ ); nwritten += block_buf_size_; temp_data.clear(); temp_data.push_back( (*gh.get_grid(ilevel))(i,j,k) * vfac ); } } } if( temp_data.size() > 0 ) { ofs_temp.write( (char*)&temp_data[0], temp_data.size()*sizeof(T_store) ); nwritten += temp_data.size(); } if( nwritten != npart ) throw std::runtime_error("Internal consistency error while writing temporary file for velocities"); ofs_temp.write( (char *)&blksize, sizeof(int) ); if( ofs_temp.bad() ) throw std::runtime_error("I/O error while writing temporary file for velocities"); ofs_temp.close(); } void write_dm_density( const grid_hierarchy& gh ) { //... we don't care about DM density for Gadget } void write_dm_potential( const grid_hierarchy& gh ) { } void write_gas_potential( const grid_hierarchy& gh ) { } //... write data for gas -- don't do this void write_gas_velocity( int coord, const grid_hierarchy& gh ) { //... count number of leaf cells ...// size_t npcoarse = 0, npfine = 0; npfine = gh.count_leaf_cells(gh.levelmax(), gh.levelmax()); header_.npart[2] = npfine; header_.npartTotal[2] = (unsigned)npfine; header_.npartTotalHighWord[2] = (unsigned)(npfine>>32); //... collect displacements and convert to absolute coordinates with correct //... units std::vector temp_data; temp_data.reserve( block_buf_size_ ); float isqrta = 1.0f/sqrt(header_.time); float vfac = isqrta*header_.BoxSize; if( kpcunits_ ) vfac /= 1000.0; unsigned npart = npfine+npcoarse; unsigned nwritten = 0; char temp_fname[256]; sprintf( temp_fname, "___ic_temp_%05d.bin", 100*id_gas_vel+coord ); std::ofstream ofs_temp( temp_fname, std::ios::binary|std::ios::trunc ); unsigned long long blksize; if(!do_glass_) { blksize = sizeof(T_store)*npart; ofs_temp.write( (char *)&blksize, sizeof(unsigned long long) ); const unsigned ilevel = gh.levelmax(); const unsigned nx = gh.get_grid(ilevel)->size(0), ny = gh.get_grid(ilevel)->size(1), nz = gh.get_grid(ilevel)->size(2); for( unsigned i=0; i(&blksz), sizeof(unsigned) ); assert( blksz == sizeof(io_header) ); ofg.read( reinterpret_cast(&glasshead), sizeof( io_header ) ); //size_t nreq = gh.size(gh.levelmax(), 0)*gh.size(gh.levelmax(), 1)*gh.size(gh.levelmax(), 2); /*if( nreq != (size_t)glasshead.npart[1] ) { LOGERR("glass file contains %d particles, but should contain %ld",glasshead.npart[1],nreq); throw std::runtime_error("glass file does not contain the right amount of particles"); }*/ ofg.read( reinterpret_cast(&blksz), sizeof(unsigned) ); ofg.read( reinterpret_cast(&blksz), sizeof(unsigned) ); //assert( blksz == (glasshead.npart[1]+glasshead.npart[2])*sizeof(float)*3 ); //ofg.seekg( sizeof(float)*3*glasshead.npart[1], std::ios_base::cur ); // do the highest level with the glass float lglass = glasshead.BoxSize; header_.npart[2] = glasshead.npart[2]; header_.npartTotal[2] = glasshead.npartTotal[2]; header_.npartTotalHighWord[2] = glasshead.npartTotalHighWord[2]; // read glass, do interpolation and write size_t npartdone=0; size_t npinter = (size_t)glasshead.npart[2]; blksize = sizeof(T_store)*npinter; ofs_temp.write( (char *)&blksize, sizeof(unsigned long long) ); float *pos_tmp = new float[3*block_buf_size_]; temp_data.assign( block_buf_size_, 0.0 ); while( npartdone < npinter ) { size_t npart2read = std::min(npinter-npartdone,block_buf_size_); ofg.read( reinterpret_cast(&pos_tmp[0]), npart2read*sizeof(float)*3 ); get_cic_velocity( pos_tmp, npart2read, lglass, gh, &temp_data[0] ); ofs_temp.write( (char*)&temp_data[0], sizeof(T_store)*npart2read ); npartdone += npart2read; nwritten += npart2read; } delete[] pos_tmp; temp_data.clear(); for( int ilevel=levelmax_-1; ilevel>=(int)levelmin_; --ilevel ) for( unsigned i=0; isize(0); ++i ) for( unsigned j=0; jsize(1); ++j ) for( unsigned k=0; ksize(2); ++k ) if( ! gh.is_refined(ilevel,i,j,k) ) { if( temp_data.size() < block_buf_size_ ) temp_data.push_back( (*gh.get_grid(ilevel))(i,j,k) * vfac ); else { ofs_temp.write( (char*)&temp_data[0], sizeof(T_store)*block_buf_size_ ); nwritten += block_buf_size_; temp_data.clear(); temp_data.push_back( (*gh.get_grid(ilevel))(i,j,k) * vfac ); } } } if( temp_data.size() > 0 ) { ofs_temp.write( (char*)&temp_data[0], temp_data.size()*sizeof(T_store) ); nwritten += temp_data.size(); } if( nwritten != npart ) throw std::runtime_error("Internal consistency error while writing temporary file for gas velocities"); ofs_temp.write( (char *)&blksize, sizeof(int) ); if( ofs_temp.bad() ) throw std::runtime_error("I/O error while writing temporary file for gas velocities"); ofs_temp.close(); } //... write only for fine level void write_gas_position( int coord, const grid_hierarchy& gh ) { //... count number of leaf cells ...// unsigned long long npfine = 0; npfine = gh.count_leaf_cells(gh.levelmax(), gh.levelmax()); //... determine if we need to shift the coordinates back double *shift = NULL; if( cf_.getValueSafe("output","shift_back",false ) ) { if( coord == 0 ) std::cout << " - gadget2 output plug-in will shift particle positions back...\n"; double h = 1.0/(1<( "setup", "shift_x" )*h; shift[1] = -(double)cf_.getValue( "setup", "shift_y" )*h; shift[2] = -(double)cf_.getValue( "setup", "shift_z" )*h; } unsigned long long npart = npfine; unsigned long long nwritten = 0; //... header_.npart[2] = npfine; header_.npartTotal[2] = (unsigned)npfine; header_.npartTotalHighWord[2] = (unsigned)(npfine>>32); //header_.num_files = (int)ceil((double)npart/(double)npartmax_); //... collect displacements and convert to absolute coordinates with correct //... units std::vector temp_data; temp_data.reserve( block_buf_size_ ); char temp_fname[256]; sprintf( temp_fname, "___ic_temp_%05d.bin", 100*id_gas_pos+coord ); std::ofstream ofs_temp( temp_fname, std::ios::binary|std::ios::trunc ); unsigned long long blksize; double xfac = header_.BoxSize; //... shift particle positions (this has to be done as the same shift //... is used when computing the convolution kernel for SPH baryons) if( do_baryons_ ) { double h = 1. / (1<size(0), ny = gh.get_grid(ilevel)->size(1), nz = gh.get_grid(ilevel)->size(2); for( unsigned i=0; i(&blksz), sizeof(unsigned) ); assert( blksz == sizeof(io_header) ); ofg.read( reinterpret_cast(&glasshead), sizeof( io_header ) ); //size_t nreq = gh.size(gh.levelmax(), 0)*gh.size(gh.levelmax(), 1)*gh.size(gh.levelmax(), 2); /*if( nreq != (size_t)glasshead.npart[1] ) { LOGERR("glass file contains %d particles, but should contain %ld",glasshead.npart[1],nreq); throw std::runtime_error("glass file does not contain the right amount of particles"); }*/ ofg.read( reinterpret_cast(&blksz), sizeof(unsigned) ); ofg.read( reinterpret_cast(&blksz), sizeof(unsigned) ); //assert( blksz == (glasshead.npart[1]+glasshead.npart[2])*sizeof(float)*3 ); //ofg.seekg( sizeof(float)*3*glasshead.npart[1], std::ios_base::cur ); float lglass = glasshead.BoxSize; blksize = sizeof(T_store)*glasshead.npart[1]; ofs_temp.write( (char *)&blksize, sizeof(unsigned long long) ); header_.npart[2] = glasshead.npart[2]; header_.npartTotal[2] = glasshead.npartTotal[2]; header_.npartTotalHighWord[2] = glasshead.npartTotalHighWord[2]; double rhoc = 27.7519737; if( kpcunits_ ) rhoc *= 10.0; // in h^2 M_sol / kpc^3 header_.mass[2] = omegab_ * rhoc * pow(header_.BoxSize,3.)/(glasshead.npart[2]); // read glass, do interpolation and write size_t npartdone=0; size_t npinter = glasshead.npart[2]; blksize = sizeof(T_store)*npinter; ofs_temp.write( (char *)&blksize, sizeof(unsigned long long) ); float *pos_tmp = new float[3*block_buf_size_]; temp_data.assign( block_buf_size_, 0.0 ); while( npartdone < npinter ) { size_t npart2read = std::min(npinter-npartdone,block_buf_size_); ofg.read( reinterpret_cast(&pos_tmp[0]), npart2read*sizeof(float)*3 ); get_cic_displacement( coord, pos_tmp, npart2read, lglass, gh, &temp_data[0] ); ofs_temp.write( (char*)&temp_data[0], sizeof(T_store)*npart2read ); npartdone += npart2read; nwritten += npart2read; } delete[] pos_tmp; temp_data.clear(); } if( temp_data.size() > 0 ) { ofs_temp.write( (char*)&temp_data[0], sizeof(T_store)*temp_data.size() ); nwritten += temp_data.size(); } if( nwritten != npart ) throw std::runtime_error("Internal consistency error while writing temporary file for gas positions"); //... dump to temporary file ofs_temp.write( (char *)&blksize, sizeof(unsigned long long) ); if( ofs_temp.bad() ) throw std::runtime_error("I/O error while writing temporary file for gas positions"); ofs_temp.close(); if( shift != NULL ) delete[] shift; } void write_gas_density( const grid_hierarchy& gh ) { double rhoc = 27.7519737; // h^2 1e10 M_sol / Mpc^3 if( kpcunits_ ) rhoc *= 10.0; // in h^2 M_sol / kpc^3 if( do_baryons_ && !do_glass_ ) header_.mass[2] = omegab_ * rhoc * pow(header_.BoxSize,3.)/pow(2,3*levelmax_); } void finalize( void ) { this->assemble_gadget_file(); } }; namespace{ output_plugin_creator_concrete< gadget2_2comp_output_plugin > creator1("gadget2_2c"); #ifndef SINGLE_PRECISION output_plugin_creator_concrete< gadget2_2comp_output_plugin > creator2("gadget2_2c_double"); #endif }