/*! This function reads initial conditions, in one of the three possible file * formats currently supported by Gadget. Note: When a snapshot file is * started from initial conditions (start-option 0), not all the information * in the header is used, in particular, the STARTING TIME needs to be set in * the parameterfile. Also, for gas particles, only the internal energy is * read, the density and mean molecular weight will be recomputed by the * code. When InitGasTemp>0 is given, the gas temperature will be initialzed * to this value assuming a mean colecular weight either corresponding to * complete neutrality, or full ionization. * * However, when the code is started with start-option 2, then all the this * data in the snapshot files is preserved, i.e. this is also the way to * resume a simulation from a snapshot file in case a regular restart file is * not available. */ void read_ic(char *fname) { int i, num_files, rest_files, ngroups, gr, filenr, masterTask, lastTask, groupMaster; #ifndef POLYTROPE double u_init; #endif char buf[500]; #ifndef ISOTHERM_EQS #ifndef POLYTROPE double molecular_weight; #endif #ifdef CHEMCOOL double gamm1; #endif /* CHEMCOOL */ #endif /* ISOTHERM_EQS */ #ifdef SFR double original_gas_mass, mass, masstot; #endif NumPart = 0; N_gas = 0; N_sinks = 0; All.TotNumPart = 0; num_files = find_files(fname); fill_Tab_IO_Labels(); sprintf(buf, "%s.hdf5", fname); read_file(buf, ThisTask, ThisTask); /* this makes sure that masses are initialized in the case that the mass-block is completely empty */ for(i = 0; i < NumPart; i++) { if(All.MassTable[P[i].Type] != 0) P[i].Mass = All.MassTable[P[i].Type]; } #ifndef POLYTROPE for(i = 0; i < N_gas; i++) SphP[i].Entropy = dmax(All.MinEgySpec, SphP[i].Entropy); #endif if(ThisTask == 0) { printf("reading done.\n"); fflush(stdout); } if(ThisTask == 0) { printf("Total number of particles : %d%09d\n\n", (int) (All.TotNumPart / 1000000000), (int) (All.TotNumPart % 1000000000)); fflush(stdout); } }
/*! This function reads initial conditions, in one of the three possible file * formats currently supported by Gadget. Note: When a snapshot file is * started from initial conditions (start-option 0), not all the information * in the header is used, in particular, the STARTING TIME needs to be set in * the parameterfile. Also, for gas particles, only the internal energy is * read, the density and mean molecular weight will be recomputed by the * code. When InitGasTemp>0 is given, the gas temperature will be initialzed * to this value assuming a mean colecular weight either corresponding to * complete neutrality, or full ionization. * * However, when the code is started with start-option 2, then all the this * data in the snapshot files is preserved, i.e. this is also the way to * resume a simulation from a snapshot file in case a regular restart file is * not available. */ void read_ic(char *fname) { int i, num_files, rest_files, ngroups, gr, filenr, masterTask, lastTask, groupMaster; double u_init; char buf[500]; #ifndef ISOTHERM_EQS double molecular_weight; #endif #ifdef SFR double original_gas_mass, mass, masstot; #endif NumPart = 0; N_gas = 0; All.TotNumPart = 0; num_files = find_files(fname); rest_files = num_files; fill_Tab_IO_Labels(); while(rest_files > NTask) { sprintf(buf, "%s.%d", fname, ThisTask + (rest_files - NTask)); if(All.ICFormat == 3) sprintf(buf, "%s.%d.hdf5", fname, ThisTask + (rest_files - NTask)); ngroups = NTask / All.NumFilesWrittenInParallel; if((NTask % All.NumFilesWrittenInParallel)) ngroups++; groupMaster = (ThisTask / ngroups) * ngroups; for(gr = 0; gr < ngroups; gr++) { if(ThisTask == (groupMaster + gr)) /* ok, it's this processor's turn */ read_file(buf, ThisTask, ThisTask); MPI_Barrier(MPI_COMM_WORLD); } rest_files -= NTask; } if(rest_files > 0) { distribute_file(rest_files, 0, 0, NTask - 1, &filenr, &masterTask, &lastTask); if(num_files > 1) { sprintf(buf, "%s.%d", fname, filenr); if(All.ICFormat == 3) sprintf(buf, "%s.%d.hdf5", fname, filenr); } else { sprintf(buf, "%s", fname); if(All.ICFormat == 3) sprintf(buf, "%s.hdf5", fname); } ngroups = rest_files / All.NumFilesWrittenInParallel; if((rest_files % All.NumFilesWrittenInParallel)) ngroups++; for(gr = 0; gr < ngroups; gr++) { if((filenr / All.NumFilesWrittenInParallel) == gr) /* ok, it's this processor's turn */ read_file(buf, masterTask, lastTask); MPI_Barrier(MPI_COMM_WORLD); } } /* this makes sure that masses are initialized in the case that the mass-block is completely empty */ for(i = 0; i < NumPart; i++) { if(All.MassTable[P[i].Type] != 0) P[i].Mass = All.MassTable[P[i].Type]; } if(RestartFlag == 0) { #ifdef NEUTRINO_FLUID /* Initial sound velocity = 3.6e-5 c (94.1 Omega_Nu * h^2)^-2 * (1+z)^2 */ u_init = (BOLTZMANN / PROTONMASS) * 10000.; u_init *= All.UnitMass_in_g / All.UnitEnergy_in_cgs; /* unit conversion */ if (ThisTask == 0) printf("U_init 10000K : %f\n\n",u_init); u_init = 0.2 * 2.02e-7 * (29979245800. / All.UnitVelocity_in_cm_per_s) * (29979245800. / All.UnitVelocity_in_cm_per_s) / (94.1 * All.OmegaNeutrino * All.HubbleParam * All.HubbleParam) / (94.1 * All.OmegaNeutrino * All.HubbleParam * All.HubbleParam) / (All.Time * All.Time); if (ThisTask == 0) printf("U_init Neutrinos : %f\n\n",u_init); All.InitGasTemp = u_init; for(i = 0; i < N_gas; i++) { SphP[i].Entropy = u_init; /* Note: the coversion to entropy will be done in the function init(), after the densities have been computed */ } #else if(All.InitGasTemp > 0) { u_init = (BOLTZMANN / PROTONMASS) * All.InitGasTemp; u_init *= All.UnitMass_in_g / All.UnitEnergy_in_cgs; /* unit conversion */ #ifdef ISOTHERM_EQS u_init *= 1.0; #else u_init *= (1.0 / GAMMA_MINUS1); if(All.InitGasTemp > 1.0e4) /* assuming FULL ionization */ molecular_weight = 4 / (8 - 5 * (1 - HYDROGEN_MASSFRAC)); else /* assuming NEUTRAL GAS */ molecular_weight = 4 / (1 + 3 * HYDROGEN_MASSFRAC); u_init /= molecular_weight; #endif for(i = 0; i < N_gas; i++) { if(SphP[i].Entropy == 0) SphP[i].Entropy = u_init; /* Note: the coversion to entropy will be done in the function init(), after the densities have been computed */ } } #endif } for(i = 0; i < N_gas; i++) SphP[i].Entropy = dmax(All.MinEgySpec, SphP[i].Entropy); MPI_Barrier(MPI_COMM_WORLD); if(ThisTask == 0) { printf("reading done.\n"); fflush(stdout); } if(ThisTask == 0) { printf("Total number of particles : %d%09d\n\n", (int) (All.TotNumPart / 1000000000), (int) (All.TotNumPart % 1000000000)); fflush(stdout); } }
/*! This function writes a snapshot of the particle distribution to one or * several files using the selected file format. If NumFilesPerSnapshot>1, * the snapshot is distributed onto several files, several of them can be * written simultaneously (up to NumFilesWrittenInParallel). Each file * contains data from a group of processors. */ void savepositions(int num) { double t0, t1; char buf[500]; int i, j, *temp, n, filenr, gr, ngroups, masterTask, lastTask; t0 = second(); if(ThisTask == 0) printf("\nwriting snapshot file... \n"); #if defined(SFR) || defined(BLACK_HOLES) rearrange_particle_sequence(); /* ensures that new tree will be constructed */ All.NumForcesSinceLastDomainDecomp = 1 + All.TreeDomainUpdateFrequency * All.TotNumPart; #endif if(NTask < All.NumFilesPerSnapshot) { if(ThisTask == 0) printf("Fatal error.\nNumber of processors must be larger or equal than All.NumFilesPerSnapshot.\n"); endrun(0); } if(All.SnapFormat < 1 || All.SnapFormat > 3) { if(ThisTask == 0) printf("Unsupported File-Format\n"); endrun(0); } #ifndef HAVE_HDF5 if(All.SnapFormat == 3) { if(ThisTask == 0) printf("Code wasn't compiled with HDF5 support enabled!\n"); endrun(0); } #endif /* determine global and local particle numbers */ for(n = 0; n < 6; n++) n_type[n] = 0; for(n = 0; n < NumPart; n++) n_type[P[n].Type]++; /* because ntot_type_all[] is of type `long long', we cannot do a simple * MPI_Allreduce() to sum the total particle numbers */ temp = malloc(NTask * 6 * sizeof(int)); MPI_Allgather(n_type, 6, MPI_INT, temp, 6, MPI_INT, MPI_COMM_WORLD); for(i = 0; i < 6; i++) { ntot_type_all[i] = 0; for(j = 0; j < NTask; j++) ntot_type_all[i] += temp[j * 6 + i]; } free(temp); /* assign processors to output files */ distribute_file(All.NumFilesPerSnapshot, 0, 0, NTask - 1, &filenr, &masterTask, &lastTask); fill_Tab_IO_Labels(); if(All.NumFilesPerSnapshot > 1) sprintf(buf, "%s%s_%03d.%d.g", All.OutputDir, All.SnapshotFileBase, num, filenr); else sprintf(buf, "%s%s_%03d.g", All.OutputDir, All.SnapshotFileBase, num); ngroups = All.NumFilesPerSnapshot / All.NumFilesWrittenInParallel; if((All.NumFilesPerSnapshot % All.NumFilesWrittenInParallel)) ngroups++; for(gr = 0; gr < ngroups; gr++) { if((filenr / All.NumFilesWrittenInParallel) == gr) /* ok, it's this processor's turn */ write_file(buf, masterTask, lastTask); MPI_Barrier(MPI_COMM_WORLD); } if(ThisTask == 0) printf("done with snapshot.\n"); t1 = second(); All.CPU_Snapshot += timediff(t0, t1); }