/*! This function writes an actual snapshot file containing the data from * processors 'writeTask' to 'lastTask'. 'writeTask' is the one that actually * writes. Each snapshot file contains a header first, then particle * positions, velocities and ID's. Particle masses are written only for * those particle types with zero entry in MassTable. After that, first the * internal energies u, and then the density is written for the SPH * particles. If cooling is enabled, mean molecular weight and neutral * hydrogen abundance are written for the gas particles. This is followed by * the SPH smoothing length and further blocks of information, depending on * included physics and compile-time flags. If HDF5 is used, the header is * stored in a group called "/Header", and the particle data is stored * separately for each particle type in groups calles "/PartType0", * "/PartType1", etc. The sequence of the blocks is unimportant in this case. */ void write_file(char *fname, int writeTask, int lastTask) { int type, bytes_per_blockelement, npart, nextblock, typelist[6]; int n_for_this_task, ntask, n, p, pc, offset = 0, task; int blockmaxlen, ntot_type[6], nn[6]; enum iofields blocknr; int blksize; MPI_Status status; FILE *fd = 0; #ifdef HAVE_HDF5 hid_t hdf5_file = 0, hdf5_grp[6], hdf5_headergrp = 0, hdf5_dataspace_memory; hid_t hdf5_datatype = 0, hdf5_dataspace_in_file = 0, hdf5_dataset = 0; herr_t hdf5_status; hsize_t dims[2], count[2], start[2]; int rank, pcsum = 0; char buf[500]; #endif #define SKIP {my_fwrite(&blksize,sizeof(int),1,fd);} /* determine particle numbers of each type in file */ if(ThisTask == writeTask) { for(n = 0; n < 6; n++) ntot_type[n] = n_type[n]; for(task = writeTask + 1; task <= lastTask; task++) { MPI_Recv(&nn[0], 6, MPI_INT, task, TAG_LOCALN, MPI_COMM_WORLD, &status); for(n = 0; n < 6; n++) ntot_type[n] += nn[n]; } for(task = writeTask + 1; task <= lastTask; task++) MPI_Send(&ntot_type[0], 6, MPI_INT, task, TAG_N, MPI_COMM_WORLD); } else { MPI_Send(&n_type[0], 6, MPI_INT, writeTask, TAG_LOCALN, MPI_COMM_WORLD); MPI_Recv(&ntot_type[0], 6, MPI_INT, writeTask, TAG_N, MPI_COMM_WORLD, &status); } /* fill file header */ for(n = 0; n < 6; n++) { header.npart[n] = ntot_type[n]; header.npartTotal[n] = (unsigned int) ntot_type_all[n]; header.npartTotalHighWord[n] = (unsigned int) (ntot_type_all[n] >> 32); } for(n = 0; n < 6; n++) header.mass[n] = All.MassTable[n]; header.time = All.Time; if(All.ComovingIntegrationOn) header.redshift = 1.0 / All.Time - 1; else header.redshift = 0; header.flag_sfr = 0; header.flag_feedback = 0; header.flag_cooling = 0; header.flag_stellarage = 0; header.flag_metals = 0; #ifdef COOLING header.flag_cooling = 1; #endif #ifdef SFR header.flag_sfr = 1; header.flag_feedback = 1; #ifdef STELLARAGE header.flag_stellarage = 1; #endif #ifdef METALS header.flag_metals = 1; #endif #endif header.num_files = All.NumFilesPerSnapshot; header.BoxSize = All.BoxSize; header.Omega0 = All.Omega0; header.OmegaLambda = All.OmegaLambda; header.HubbleParam = All.HubbleParam; /* open file and write header */ if(ThisTask == writeTask) { if(All.SnapFormat == 3) { #ifdef HAVE_HDF5 sprintf(buf, "%s.hdf5", fname); hdf5_file = H5Fcreate(buf, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); hdf5_headergrp = H5Gcreate(hdf5_file, "/Header", 0); for(type = 0; type < 6; type++) { if(header.npart[type] > 0) { sprintf(buf, "/PartType%d", type); hdf5_grp[type] = H5Gcreate(hdf5_file, buf, 0); } } write_header_attributes_in_hdf5(hdf5_headergrp); #endif } else { if(!(fd = fopen(fname, "w"))) { printf("can't open file `%s' for writing snapshot.\n", fname); endrun(123); } if(All.SnapFormat == 2) { blksize = sizeof(int) + 4 * sizeof(char); SKIP; my_fwrite("HEAD", sizeof(char), 4, fd); nextblock = sizeof(header) + 2 * sizeof(int); my_fwrite(&nextblock, sizeof(int), 1, fd); SKIP; } blksize = sizeof(header); SKIP; my_fwrite(&header, sizeof(header), 1, fd); SKIP; } } ntask = lastTask - writeTask + 1; for(blocknr = 0; blocknr < IO_NBLOCKS; blocknr++) { if(blockpresent(blocknr)) { bytes_per_blockelement = get_bytes_per_blockelement(blocknr); blockmaxlen = ((int) (All.BufferSize * 1024 * 1024)) / bytes_per_blockelement; npart = get_particles_in_block(blocknr, &typelist[0]); if(npart > 0) { if(ThisTask == writeTask) { if(All.SnapFormat == 1 || All.SnapFormat == 2) { if(All.SnapFormat == 2) { blksize = sizeof(int) + 4 * sizeof(char); SKIP; my_fwrite(Tab_IO_Labels[blocknr], sizeof(char), 4, fd); nextblock = npart * bytes_per_blockelement + 2 * sizeof(int); my_fwrite(&nextblock, sizeof(int), 1, fd); SKIP; } blksize = npart * bytes_per_blockelement; SKIP; } } for(type = 0; type < 6; type++) { if(typelist[type]) { #ifdef HAVE_HDF5 if(ThisTask == writeTask && All.SnapFormat == 3 && header.npart[type] > 0) { switch (get_datatype_in_block(blocknr)) { case 0: hdf5_datatype = H5Tcopy(H5T_NATIVE_UINT); break; case 1: hdf5_datatype = H5Tcopy(H5T_NATIVE_FLOAT); break; case 2: hdf5_datatype = H5Tcopy(H5T_NATIVE_UINT64); break; } dims[0] = header.npart[type]; dims[1] = get_values_per_blockelement(blocknr); if(dims[1] == 1) rank = 1; else rank = 2; get_dataset_name(blocknr, buf); hdf5_dataspace_in_file = H5Screate_simple(rank, dims, NULL); hdf5_dataset = H5Dcreate(hdf5_grp[type], buf, hdf5_datatype, hdf5_dataspace_in_file, H5P_DEFAULT); pcsum = 0; } #endif for(task = writeTask, offset = 0; task <= lastTask; task++) { if(task == ThisTask) { n_for_this_task = n_type[type]; for(p = writeTask; p <= lastTask; p++) if(p != ThisTask) MPI_Send(&n_for_this_task, 1, MPI_INT, p, TAG_NFORTHISTASK, MPI_COMM_WORLD); } else MPI_Recv(&n_for_this_task, 1, MPI_INT, task, TAG_NFORTHISTASK, MPI_COMM_WORLD, &status); while(n_for_this_task > 0) { pc = n_for_this_task; if(pc > blockmaxlen) pc = blockmaxlen; if(ThisTask == task) fill_write_buffer(blocknr, &offset, pc, type); if(ThisTask == writeTask && task != writeTask) MPI_Recv(CommBuffer, bytes_per_blockelement * pc, MPI_BYTE, task, TAG_PDATA, MPI_COMM_WORLD, &status); if(ThisTask != writeTask && task == ThisTask) MPI_Ssend(CommBuffer, bytes_per_blockelement * pc, MPI_BYTE, writeTask, TAG_PDATA, MPI_COMM_WORLD); if(ThisTask == writeTask) { if(All.SnapFormat == 3) { #ifdef HAVE_HDF5 start[0] = pcsum; start[1] = 0; count[0] = pc; count[1] = get_values_per_blockelement(blocknr); pcsum += pc; H5Sselect_hyperslab(hdf5_dataspace_in_file, H5S_SELECT_SET, start, NULL, count, NULL); dims[0] = pc; dims[1] = get_values_per_blockelement(blocknr); hdf5_dataspace_memory = H5Screate_simple(rank, dims, NULL); hdf5_status = H5Dwrite(hdf5_dataset, hdf5_datatype, hdf5_dataspace_memory, hdf5_dataspace_in_file, H5P_DEFAULT, CommBuffer); H5Sclose(hdf5_dataspace_memory); #endif } else my_fwrite(CommBuffer, bytes_per_blockelement, pc, fd); } n_for_this_task -= pc; } } #ifdef HAVE_HDF5 if(ThisTask == writeTask && All.SnapFormat == 3 && header.npart[type] > 0) { if(All.SnapFormat == 3) { H5Dclose(hdf5_dataset); H5Sclose(hdf5_dataspace_in_file); H5Tclose(hdf5_datatype); } } #endif } } if(ThisTask == writeTask) { if(All.SnapFormat == 1 || All.SnapFormat == 2) SKIP; } } } } if(ThisTask == writeTask) { if(All.SnapFormat == 3) { #ifdef HAVE_HDF5 for(type = 5; type >= 0; type--) if(header.npart[type] > 0) H5Gclose(hdf5_grp[type]); H5Gclose(hdf5_headergrp); H5Fclose(hdf5_file); #endif } else fclose(fd); } }
/*! This function reads a snapshot file and distributes the data it contains * to tasks 'readTask' to 'lastTask'. */ void read_file(char *fname, int readTask, int lastTask) { int blockmaxlen; int i, n_in_file, n_for_this_task, ntask, pc, offset = 0, task; int blksize1, blksize2; MPI_Status status; FILE *fd = 0; int nall; int type; char label[4]; int nstart, bytes_per_blockelement, npart, nextblock, typelist[6]; enum iofields blocknr; #ifdef HAVE_HDF5 char buf[500]; int rank, pcsum; hid_t hdf5_file, hdf5_grp[6], hdf5_dataspace_in_file; hid_t hdf5_datatype, hdf5_dataspace_in_memory, hdf5_dataset; hsize_t dims[2], count[2], start[2]; #endif #define SKIP {my_fread(&blksize1,sizeof(int),1,fd);} #define SKIP2 {my_fread(&blksize2,sizeof(int),1,fd);} if(ThisTask == readTask) { if(All.ICFormat == 1 || All.ICFormat == 2) { if(!(fd = fopen(fname, "r"))) { printf("can't open file `%s' for reading initial conditions.\n", fname); endrun(123); } if(All.ICFormat == 2) { SKIP; my_fread(&label, sizeof(char), 4, fd); my_fread(&nextblock, sizeof(int), 1, fd); printf("Reading header => '%c%c%c%c' (%d byte)\n", label[0], label[1], label[2], label[3], nextblock); SKIP2; } SKIP; my_fread(&header, sizeof(header), 1, fd); SKIP2; if(blksize1 != 256 || blksize2 != 256) { printf("incorrect header format\n"); fflush(stdout); endrun(890); } } #ifdef HAVE_HDF5 if(All.ICFormat == 3) { read_header_attributes_in_hdf5(fname); hdf5_file = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT); for(type = 0; type < 6; type++) { if(header.npart[type] > 0) { sprintf(buf, "/PartType%d", type); hdf5_grp[type] = H5Gopen(hdf5_file, buf); } } } #endif for(task = readTask + 1; task <= lastTask; task++) MPI_Ssend(&header, sizeof(header), MPI_BYTE, task, TAG_HEADER, MPI_COMM_WORLD); } else MPI_Recv(&header, sizeof(header), MPI_BYTE, readTask, TAG_HEADER, MPI_COMM_WORLD, &status); if(All.TotNumPart == 0) { if(header.num_files <= 1) for(i = 0; i < 6; i++) header.npartTotal[i] = header.npart[i]; All.TotN_gas = header.npartTotal[0] + (((long long) header.npartTotalHighWord[0]) << 32); for(i = 0, All.TotNumPart = 0; i < 6; i++) { All.TotNumPart += header.npartTotal[i]; All.TotNumPart += (((long long) header.npartTotalHighWord[i]) << 32); } for(i = 0; i < 6; i++) All.MassTable[i] = header.mass[i]; All.MaxPart = All.PartAllocFactor * (All.TotNumPart / NTask); /* sets the maximum number of particles that may */ All.MaxPartSph = All.PartAllocFactor * (All.TotN_gas / NTask); /* sets the maximum number of particles that may reside on a processor */ allocate_memory(); if(RestartFlag == 2) All.Time = All.TimeBegin = header.time; } if(ThisTask == readTask) { for(i = 0, n_in_file = 0; i < 6; i++) n_in_file += header.npart[i]; printf("\nreading file `%s' on task=%d (contains %d particles.)\n" "distributing this file to tasks %d-%d\n" "Type 0 (gas): %8d (tot=%6d%09d) masstab=%g\n" "Type 1 (halo): %8d (tot=%6d%09d) masstab=%g\n" "Type 2 (disk): %8d (tot=%6d%09d) masstab=%g\n" "Type 3 (bulge): %8d (tot=%6d%09d) masstab=%g\n" "Type 4 (stars): %8d (tot=%6d%09d) masstab=%g\n" "Type 5 (bndry): %8d (tot=%6d%09d) masstab=%g\n\n", fname, ThisTask, n_in_file, readTask, lastTask, header.npart[0], (int) (header.npartTotal[0] / 1000000000), (int) (header.npartTotal[0] % 1000000000), All.MassTable[0], header.npart[1], (int) (header.npartTotal[1] / 1000000000), (int) (header.npartTotal[1] % 1000000000), All.MassTable[1], header.npart[2], (int) (header.npartTotal[2] / 1000000000), (int) (header.npartTotal[2] % 1000000000), All.MassTable[2], header.npart[3], (int) (header.npartTotal[3] / 1000000000), (int) (header.npartTotal[3] % 1000000000), All.MassTable[3], header.npart[4], (int) (header.npartTotal[4] / 1000000000), (int) (header.npartTotal[4] % 1000000000), All.MassTable[4], header.npart[5], (int) (header.npartTotal[5] / 1000000000), (int) (header.npartTotal[5] % 1000000000), All.MassTable[5]); fflush(stdout); } ntask = lastTask - readTask + 1; /* to collect the gas particles all at the beginning (in case several snapshot files are read on the current CPU) we move the collisionless particles such that a gap of the right size is created */ for(type = 0, nall = 0; type < 6; type++) { n_in_file = header.npart[type]; n_for_this_task = n_in_file / ntask; if((ThisTask - readTask) < (n_in_file % ntask)) n_for_this_task++; nall += n_for_this_task; } memmove(&P[N_gas + nall], &P[N_gas], (NumPart - N_gas) * sizeof(struct particle_data)); nstart = N_gas; for(blocknr = 0; blocknr < IO_NBLOCKS; blocknr++) { if(blockpresent(blocknr)) { if(RestartFlag == 0 && blocknr > IO_U) continue; /* ignore all other blocks in initial conditions */ bytes_per_blockelement = get_bytes_per_blockelement(blocknr); blockmaxlen = ((int) (All.BufferSize * 1024 * 1024)) / bytes_per_blockelement; npart = get_particles_in_block(blocknr, &typelist[0]); if(npart > 0) { if(ThisTask == readTask) { if(All.ICFormat == 2) { SKIP; my_fread(&label, sizeof(char), 4, fd); my_fread(&nextblock, sizeof(int), 1, fd); printf("Reading header => '%c%c%c%c' (%d byte)\n", label[0], label[1], label[2], label[3], nextblock); SKIP2; if(strncmp(label, Tab_IO_Labels[blocknr], 4) != 0) { printf("incorrect block-structure!\n"); printf("expected '%c%c%c%c' but found '%c%c%c%c'\n", label[0], label[1], label[2], label[3], Tab_IO_Labels[blocknr][0], Tab_IO_Labels[blocknr][1], Tab_IO_Labels[blocknr][2], Tab_IO_Labels[blocknr][3]); fflush(stdout); endrun(1890); } } if(All.ICFormat == 1 || All.ICFormat == 2) SKIP; } for(type = 0, offset = 0; type < 6; type++) { n_in_file = header.npart[type]; #ifdef HAVE_HDF5 pcsum = 0; #endif if(typelist[type] == 0) { n_for_this_task = n_in_file / ntask; if((ThisTask - readTask) < (n_in_file % ntask)) n_for_this_task++; offset += n_for_this_task; } else { for(task = readTask; task <= lastTask; task++) { n_for_this_task = n_in_file / ntask; if((task - readTask) < (n_in_file % ntask)) n_for_this_task++; if(task == ThisTask) if(NumPart + n_for_this_task > All.MaxPart) { printf("too many particles\n"); endrun(1313); } do { pc = n_for_this_task; if(pc > blockmaxlen) pc = blockmaxlen; if(ThisTask == readTask) { if(All.ICFormat == 1 || All.ICFormat == 2) my_fread(CommBuffer, bytes_per_blockelement, pc, fd); #ifdef HAVE_HDF5 if(All.ICFormat == 3) { get_dataset_name(blocknr, buf); hdf5_dataset = H5Dopen(hdf5_grp[type], buf); dims[0] = header.npart[type]; dims[1] = get_values_per_blockelement(blocknr); if(dims[1] == 1) rank = 1; else rank = 2; hdf5_dataspace_in_file = H5Screate_simple(rank, dims, NULL); dims[0] = pc; hdf5_dataspace_in_memory = H5Screate_simple(rank, dims, NULL); start[0] = pcsum; start[1] = 0; count[0] = pc; count[1] = get_values_per_blockelement(blocknr); pcsum += pc; H5Sselect_hyperslab(hdf5_dataspace_in_file, H5S_SELECT_SET, start, NULL, count, NULL); switch (get_datatype_in_block(blocknr)) { case 0: hdf5_datatype = H5Tcopy(H5T_NATIVE_UINT); break; case 1: hdf5_datatype = H5Tcopy(H5T_NATIVE_FLOAT); break; case 2: hdf5_datatype = H5Tcopy(H5T_NATIVE_UINT64); break; } H5Dread(hdf5_dataset, hdf5_datatype, hdf5_dataspace_in_memory, hdf5_dataspace_in_file, H5P_DEFAULT, CommBuffer); H5Tclose(hdf5_datatype); H5Sclose(hdf5_dataspace_in_memory); H5Sclose(hdf5_dataspace_in_file); H5Dclose(hdf5_dataset); } #endif } if(ThisTask == readTask && task != readTask) MPI_Ssend(CommBuffer, bytes_per_blockelement * pc, MPI_BYTE, task, TAG_PDATA, MPI_COMM_WORLD); if(ThisTask != readTask && task == ThisTask) MPI_Recv(CommBuffer, bytes_per_blockelement * pc, MPI_BYTE, readTask, TAG_PDATA, MPI_COMM_WORLD, &status); if(ThisTask == task) { empty_read_buffer(blocknr, nstart + offset, pc, type); offset += pc; } n_for_this_task -= pc; } while(n_for_this_task > 0); } } } if(ThisTask == readTask) { if(All.ICFormat == 1 || All.ICFormat == 2) { SKIP2; if(blksize1 != blksize2) { printf("incorrect block-sizes detected!\n"); printf("Task=%d blocknr=%d blksize1=%d blksize2=%d\n", ThisTask, blocknr, blksize1, blksize2); fflush(stdout); endrun(1889); } } } } } } for(type = 0; type < 6; type++) { n_in_file = header.npart[type]; n_for_this_task = n_in_file / ntask; if((ThisTask - readTask) < (n_in_file % ntask)) n_for_this_task++; NumPart += n_for_this_task; if(type == 0) N_gas += n_for_this_task; } if(ThisTask == readTask) { if(All.ICFormat == 1 || All.ICFormat == 2) fclose(fd); #ifdef HAVE_HDF5 if(All.ICFormat == 3) { for(type = 5; type >= 0; type--) if(header.npart[type] > 0) H5Gclose(hdf5_grp[type]); H5Fclose(hdf5_file); } #endif } }
/*! This function reads a snapshot file and distributes the data it contains * to tasks 'readTask' to 'lastTask'. */ void read_file(char *fname, int readTask, int lastTask) { int blockmaxlen; int i, n_in_file, n_for_this_task, ntask, pc, offset = 0, task; int blksize1, blksize2; MPI_Status status; FILE *fd = 0; int nall, nread; int type, bnr; char label[4], expected_label[4], buf[500]; int nstart, bytes_per_blockelement, npart, nextblock, typelist[6]; enum iofields blocknr; size_t bytes; #ifdef HAVE_HDF5 int rank, pcsum; hid_t hdf5_file = 0, hdf5_grp[6], hdf5_dataspace_in_file; hid_t hdf5_datatype = 0, hdf5_dataspace_in_memory, hdf5_dataset; hsize_t dims[2], count[2], start[2]; #endif #if defined(COSMIC_RAYS) && (!defined(CR_IC)) int CRpop; #endif #define SKIP {my_fread(&blksize1,sizeof(int),1,fd);} #define SKIP2 {my_fread(&blksize2,sizeof(int),1,fd);} if(ThisTask == readTask) { if(All.ICFormat == 1 || All.ICFormat == 2) { if(!(fd = fopen(fname, "r"))) { printf("can't open file `%s' for reading initial conditions.\n", fname); endrun(123); } if(All.ICFormat == 2) { SKIP; #ifdef AUTO_SWAP_ENDIAN_READIC swap_file = blksize1; #endif my_fread(&label, sizeof(char), 4, fd); my_fread(&nextblock, sizeof(int), 1, fd); #ifdef AUTO_SWAP_ENDIAN_READIC swap_Nbyte((char *) &nextblock, 1, 4); #endif printf("Reading header => '%c%c%c%c' (%d byte)\n", label[0], label[1], label[2], label[3], nextblock); SKIP2; } SKIP; #ifdef AUTO_SWAP_ENDIAN_READIC if(All.ICFormat == 1) { if(blksize1 != 256) swap_file = 1; } #endif my_fread(&header, sizeof(header), 1, fd); SKIP2; #ifdef AUTO_SWAP_ENDIAN_READIC swap_Nbyte((char *) &blksize1, 1, 4); swap_Nbyte((char *) &blksize2, 1, 4); #endif if(blksize1 != 256 || blksize2 != 256) { printf("incorrect header format\n"); fflush(stdout); endrun(890); /* Probable error is wrong size of fill[] in header file. Needs to be 256 bytes in total. */ } #ifdef AUTO_SWAP_ENDIAN_READIC swap_header(); #endif } #ifdef HAVE_HDF5 if(All.ICFormat == 3) { read_header_attributes_in_hdf5(fname); hdf5_file = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT); for(type = 0; type < 6; type++) { if(header.npart[type] > 0) { sprintf(buf, "/PartType%d", type); hdf5_grp[type] = H5Gopen(hdf5_file, buf); } } } #endif for(task = readTask + 1; task <= lastTask; task++) { MPI_Ssend(&header, sizeof(header), MPI_BYTE, task, TAG_HEADER, MPI_COMM_WORLD); #ifdef AUTO_SWAP_ENDIAN_READIC MPI_Ssend(&swap_file, sizeof(int), MPI_INT, task, TAG_SWAP, MPI_COMM_WORLD); #endif } } else { MPI_Recv(&header, sizeof(header), MPI_BYTE, readTask, TAG_HEADER, MPI_COMM_WORLD, &status); #ifdef AUTO_SWAP_ENDIAN_READIC MPI_Recv(&swap_file, sizeof(int), MPI_INT, readTask, TAG_SWAP, MPI_COMM_WORLD, &status); #endif } #ifdef INPUT_IN_DOUBLEPRECISION if(header.flag_doubleprecision == 0) { if(ThisTask == 0) printf ("\nProblem: Code compiled with INPUT_IN_DOUBLEPRECISION, but input files are in single precision!\n"); endrun(11); } #else if(header.flag_doubleprecision) { if(ThisTask == 0) printf ("\nProblem: Code not compiled with INPUT_IN_DOUBLEPRECISION, but input files are in double precision!\n"); endrun(10); } #endif if(All.TotNumPart == 0) { if(header.num_files <= 1) for(i = 0; i < 6; i++) { header.npartTotal[i] = header.npart[i]; #ifdef SFR header.npartTotalHighWord[i] = 0; #endif } All.TotN_gas = header.npartTotal[0] + (((long long) header.npartTotalHighWord[0]) << 32); for(i = 0, All.TotNumPart = 0; i < 6; i++) { All.TotNumPart += header.npartTotal[i]; All.TotNumPart += (((long long) header.npartTotalHighWord[i]) << 32); } #ifdef GENERATE_GAS_IN_ICS if(RestartFlag == 0) { All.TotN_gas += header.npartTotal[1]; All.TotNumPart += header.npartTotal[1]; } #endif for(i = 0; i < 6; i++) All.MassTable[i] = header.mass[i]; All.MaxPart = (int) (All.PartAllocFactor * (All.TotNumPart / NTask)); /* sets the maximum number of particles that may */ #ifdef GASRETURN All.MaxPartSph = (int) (All.PartAllocFactor * (All.TotNumPart / NTask)); /* sets the maximum number of particles that may */ #else All.MaxPartSph = (int) (All.PartAllocFactor * (All.TotN_gas / NTask)); /* sets the maximum number of particles that may */ #endif #ifdef INHOMOG_GASDISTR_HINT All.MaxPartSph = All.MaxPart; #endif allocate_memory(); if(!(CommBuffer = mymalloc(bytes = All.BufferSize * 1024 * 1024))) { printf("failed to allocate memory for `CommBuffer' (%g MB).\n", bytes / (1024.0 * 1024.0)); endrun(2); } if(RestartFlag >= 2) All.Time = All.TimeBegin = header.time; } if(ThisTask == readTask) { for(i = 0, n_in_file = 0; i < 6; i++) n_in_file += header.npart[i]; printf("\nreading file `%s' on task=%d (contains %d particles.)\n" "distributing this file to tasks %d-%d\n" "Type 0 (gas): %8d (tot=%6d%09d) masstab=%g\n" "Type 1 (halo): %8d (tot=%6d%09d) masstab=%g\n" "Type 2 (disk): %8d (tot=%6d%09d) masstab=%g\n" "Type 3 (bulge): %8d (tot=%6d%09d) masstab=%g\n" "Type 4 (stars): %8d (tot=%6d%09d) masstab=%g\n" "Type 5 (bndry): %8d (tot=%6d%09d) masstab=%g\n\n", fname, ThisTask, n_in_file, readTask, lastTask, header.npart[0], (int) (header.npartTotal[0] / 1000000000), (int) (header.npartTotal[0] % 1000000000), All.MassTable[0], header.npart[1], (int) (header.npartTotal[1] / 1000000000), (int) (header.npartTotal[1] % 1000000000), All.MassTable[1], header.npart[2], (int) (header.npartTotal[2] / 1000000000), (int) (header.npartTotal[2] % 1000000000), All.MassTable[2], header.npart[3], (int) (header.npartTotal[3] / 1000000000), (int) (header.npartTotal[3] % 1000000000), All.MassTable[3], header.npart[4], (int) (header.npartTotal[4] / 1000000000), (int) (header.npartTotal[4] % 1000000000), All.MassTable[4], header.npart[5], (int) (header.npartTotal[5] / 1000000000), (int) (header.npartTotal[5] % 1000000000), All.MassTable[5]); fflush(stdout); } ntask = lastTask - readTask + 1; /* to collect the gas particles all at the beginning (in case several snapshot files are read on the current CPU) we move the collisionless particles such that a gap of the right size is created */ for(type = 0, nall = 0; type < 6; type++) { n_in_file = header.npart[type]; n_for_this_task = n_in_file / ntask; if((ThisTask - readTask) < (n_in_file % ntask)) n_for_this_task++; if(type == 0) { if(N_gas + n_for_this_task > All.MaxPartSph) { printf("Not enough space on task=%d for SPH particles (space for %d, need at least %d)\n", ThisTask, All.MaxPartSph, N_gas + n_for_this_task); fflush(stdout); endrun(172); } } nall += n_for_this_task; } if(NumPart + nall > All.MaxPart) { printf("Not enough space on task=%d (space for %d, need at least %d)\n", ThisTask, All.MaxPart, NumPart + nall); fflush(stdout); endrun(173); } memmove(&P[N_gas + nall], &P[N_gas], (NumPart - N_gas) * sizeof(struct particle_data)); nstart = N_gas; for(bnr = 0; bnr < 1000; bnr++) { blocknr = (enum iofields) bnr; if(blocknr == IO_LASTENTRY) break; if(blockpresent(blocknr)) { #ifdef CR_IC if(RestartFlag == 0 && ((blocknr > IO_CR_Q0 && blocknr != IO_BFLD) || (blocknr >= IO_RHO && blocknr <= IO_ACCEL))) #else #ifdef EOS_DEGENERATE if(RestartFlag == 0 && (blocknr > IO_U && blocknr != IO_EOSXNUC)) #else #ifndef CHEMISTRY #ifndef READ_HSML /* normal */ if(RestartFlag == 0 && blocknr > IO_U && blocknr != IO_BFLD && blocknr != IO_Z && blocknr != IO_AGE) #else if(RestartFlag == 0 && blocknr > IO_U && blocknr != IO_BFLD && blocknr != IO_HSML) #endif #else if(RestartFlag == 0 && blocknr > IO_HM) #endif #endif #endif #if defined(DISTORTIONTENSORPS) && !defined(COSMIC_DISTORTION) if(RestartFlag == 0 && (blocknr > IO_U && blocknr != IO_SHEET_ORIENTATION)) if(RestartFlag == 0 && (blocknr > IO_U && blocknr != IO_INIT_DENSITY)) if(RestartFlag == 0 && (blocknr > IO_U && blocknr != IO_CAUSTIC_COUNTER)) #ifdef DISTORTION_READALL if(RestartFlag == 0 && (blocknr > IO_U && blocknr != IO_DISTORTIONTENSORPS)) #endif #endif continue; /* ignore all other blocks in initial conditions */ #ifdef BINISET if(RestartFlag == 0 && blocknr == IO_BFLD) continue; #endif if(ThisTask == readTask) { get_dataset_name(blocknr, buf); printf("reading block %d (%s)...\n", blocknr, buf); fflush(stdout); } bytes_per_blockelement = get_bytes_per_blockelement(blocknr, 1); blockmaxlen = ((int) (All.BufferSize * 1024 * 1024)) / bytes_per_blockelement; npart = get_particles_in_block(blocknr, &typelist[0]); if(npart > 0) { if(blocknr != IO_DMHSML && blocknr != IO_DMDENSITY && blocknr != IO_DMVELDISP && blocknr != IO_DMHSML_V && blocknr != IO_DMDENSITY_V) if(ThisTask == readTask) { if(All.ICFormat == 2) { SKIP; my_fread(&label, sizeof(char), 4, fd); my_fread(&nextblock, sizeof(int), 1, fd); #ifdef AUTO_SWAP_ENDIAN_READIC swap_Nbyte((char *) &nextblock, 1, 4); #endif printf("Reading header => '%c%c%c%c' (%d byte)\n", label[0], label[1], label[2], label[3], nextblock); SKIP2; get_Tab_IO_Label(blocknr, expected_label); if(strncmp(label, expected_label, 4) != 0) { printf("incorrect block-structure!\n"); printf("expected '%c%c%c%c' but found '%c%c%c%c'\n", label[0], label[1], label[2], label[3], expected_label[0], expected_label[1], expected_label[2], expected_label[3]); fflush(stdout); endrun(1890); } } if(All.ICFormat == 1 || All.ICFormat == 2) SKIP; } for(type = 0, offset = 0, nread = 0; type < 6; type++) { n_in_file = header.npart[type]; #ifdef HAVE_HDF5 pcsum = 0; #endif if(typelist[type] == 0) { n_for_this_task = n_in_file / ntask; if((ThisTask - readTask) < (n_in_file % ntask)) n_for_this_task++; offset += n_for_this_task; } else { for(task = readTask; task <= lastTask; task++) { n_for_this_task = n_in_file / ntask; if((task - readTask) < (n_in_file % ntask)) n_for_this_task++; if(task == ThisTask) if(NumPart + n_for_this_task > All.MaxPart) { printf("too many particles. %d %d %d\n", NumPart, n_for_this_task, All.MaxPart); endrun(1313); } do { pc = n_for_this_task; if(pc > blockmaxlen) pc = blockmaxlen; if(ThisTask == readTask) { if(All.ICFormat == 1 || All.ICFormat == 2) { if(blocknr != IO_DMHSML && blocknr != IO_DMDENSITY && blocknr != IO_DMVELDISP && blocknr != IO_DMHSML_V && blocknr != IO_DMDENSITY_V) { my_fread(CommBuffer, bytes_per_blockelement, pc, fd); nread += pc; } else { #ifdef SUBFIND_RESHUFFLE_CATALOGUE read_hsml_files(CommBuffer, pc, blocknr, NumPartPerFile[FileNr] + nread); #endif nread += pc; } } #ifdef HAVE_HDF5 if(All.ICFormat == 3 && pc > 0) { get_dataset_name(blocknr, buf); hdf5_dataset = H5Dopen(hdf5_grp[type], buf); dims[0] = header.npart[type]; dims[1] = get_values_per_blockelement(blocknr); if(dims[1] == 1) rank = 1; else rank = 2; hdf5_dataspace_in_file = H5Screate_simple(rank, dims, NULL); dims[0] = pc; hdf5_dataspace_in_memory = H5Screate_simple(rank, dims, NULL); start[0] = pcsum; start[1] = 0; count[0] = pc; count[1] = get_values_per_blockelement(blocknr); pcsum += pc; H5Sselect_hyperslab(hdf5_dataspace_in_file, H5S_SELECT_SET, start, NULL, count, NULL); switch (get_datatype_in_block(blocknr)) { case 0: hdf5_datatype = H5Tcopy(H5T_NATIVE_UINT); break; case 1: #ifdef INPUT_IN_DOUBLEPRECISION hdf5_datatype = H5Tcopy(H5T_NATIVE_DOUBLE); #else hdf5_datatype = H5Tcopy(H5T_NATIVE_FLOAT); #endif break; case 2: hdf5_datatype = H5Tcopy(H5T_NATIVE_UINT64); break; } H5Dread(hdf5_dataset, hdf5_datatype, hdf5_dataspace_in_memory, hdf5_dataspace_in_file, H5P_DEFAULT, CommBuffer); H5Tclose(hdf5_datatype); H5Sclose(hdf5_dataspace_in_memory); H5Sclose(hdf5_dataspace_in_file); H5Dclose(hdf5_dataset); } #endif } if(ThisTask == readTask && task != readTask && pc > 0) MPI_Ssend(CommBuffer, bytes_per_blockelement * pc, MPI_BYTE, task, TAG_PDATA, MPI_COMM_WORLD); if(ThisTask != readTask && task == ThisTask && pc > 0) MPI_Recv(CommBuffer, bytes_per_blockelement * pc, MPI_BYTE, readTask, TAG_PDATA, MPI_COMM_WORLD, &status); if(ThisTask == task) { empty_read_buffer(blocknr, nstart + offset, pc, type); offset += pc; } n_for_this_task -= pc; } while(n_for_this_task > 0); } } } if(ThisTask == readTask) { if(blocknr != IO_DMHSML && blocknr != IO_DMDENSITY && blocknr != IO_DMVELDISP && blocknr != IO_DMHSML_V && blocknr != IO_DMDENSITY_V) if(All.ICFormat == 1 || All.ICFormat == 2) { SKIP2; #ifdef AUTO_SWAP_ENDIAN_READIC swap_Nbyte((char *) &blksize1, 1, 4); swap_Nbyte((char *) &blksize2, 1, 4); #endif if(blksize1 != blksize2) { printf("incorrect block-sizes detected!\n"); printf("Task=%d blocknr=%d blksize1=%d blksize2=%d\n", ThisTask, blocknr, blksize1, blksize2); if(blocknr == IO_ID) { printf ("Possible mismatch of 32bit and 64bit ID's in IC file and GADGET compilation !\n"); } fflush(stdout); endrun(1889); } } } } } } #ifdef SAVE_HSML_IN_IC_ORDER MyIDType IdCount = 0; for(type = 0, offset = 0; type < 6; type++) { n_in_file = header.npart[type]; for(task = readTask; task <= lastTask; task++) { n_for_this_task = n_in_file / ntask; if((task - readTask) < (n_in_file % ntask)) n_for_this_task++; if(ThisTask == task) { int i; for(i = 0; i < n_for_this_task; i++) P[nstart + offset + i].ID_ic_order = NumPartPerFile[FileNr] + IdCount + i; offset += n_for_this_task; } IdCount += n_for_this_task; } } #endif for(type = 0; type < 6; type++) { n_in_file = header.npart[type]; n_for_this_task = n_in_file / ntask; if((ThisTask - readTask) < (n_in_file % ntask)) n_for_this_task++; NumPart += n_for_this_task; if(type == 0) N_gas += n_for_this_task; } if(ThisTask == readTask) { if(All.ICFormat == 1 || All.ICFormat == 2) fclose(fd); #ifdef HAVE_HDF5 if(All.ICFormat == 3) { for(type = 5; type >= 0; type--) if(header.npart[type] > 0) H5Gclose(hdf5_grp[type]); H5Fclose(hdf5_file); } #endif } #if defined(COSMIC_RAYS) && (!defined(CR_IC)) for(i = 0; i < n_for_this_task; i++) { if(P[i].Type != 0) { break; } for(CRpop = 0; CRpop < NUMCRPOP; CRpop++) { SphP[i].CR_C0[CRpop] = 0.0; SphP[i].CR_q0[CRpop] = 1.0e10; } } #endif }