00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <math.h>
00005 #include <mpi.h>
00006 #include <errno.h>
00007
00008 #ifdef HAVE_HDF5
00009 #include <hdf5.h>
00010 #endif
00011
00012 #include "allvars.h"
00013 #include "proto.h"
00014
00015
00016
00021 static int n_type[6];
00022 static long long ntot_type_all[6];
00023
00024
00025
00026
00033 void savepositions(int num)
00034 {
00035 double t0, t1;
00036 char buf[500];
00037 int i, j, *temp, n, filenr, gr, ngroups, masterTask, lastTask;
00038
00039 t0 = second();
00040
00041 if(ThisTask == 0)
00042 printf("\nwriting snapshot file... \n");
00043
00044 #if defined(SFR) || defined(BLACK_HOLES)
00045 rearrange_particle_sequence();
00046
00047 All.NumForcesSinceLastDomainDecomp = 1 + All.TreeDomainUpdateFrequency * All.TotNumPart;
00048 #endif
00049
00050 if(NTask < All.NumFilesPerSnapshot)
00051 {
00052 if(ThisTask == 0)
00053 printf("Fatal error.\nNumber of processors must be larger or equal than All.NumFilesPerSnapshot.\n");
00054 endrun(0);
00055 }
00056 if(All.SnapFormat < 1 || All.SnapFormat > 3)
00057 {
00058 if(ThisTask == 0)
00059 printf("Unsupported File-Format\n");
00060 endrun(0);
00061 }
00062 #ifndef HAVE_HDF5
00063 if(All.SnapFormat == 3)
00064 {
00065 if(ThisTask == 0)
00066 printf("Code wasn't compiled with HDF5 support enabled!\n");
00067 endrun(0);
00068 }
00069 #endif
00070
00071
00072
00073 for(n = 0; n < 6; n++)
00074 n_type[n] = 0;
00075
00076 for(n = 0; n < NumPart; n++)
00077 n_type[P[n].Type]++;
00078
00079
00080
00081
00082 temp = malloc(NTask * 6 * sizeof(int));
00083 MPI_Allgather(n_type, 6, MPI_INT, temp, 6, MPI_INT, MPI_COMM_WORLD);
00084 for(i = 0; i < 6; i++)
00085 {
00086 ntot_type_all[i] = 0;
00087 for(j = 0; j < NTask; j++)
00088 ntot_type_all[i] += temp[j * 6 + i];
00089 }
00090 free(temp);
00091
00092
00093
00094 distribute_file(All.NumFilesPerSnapshot, 0, 0, NTask - 1, &filenr, &masterTask, &lastTask);
00095
00096 fill_Tab_IO_Labels();
00097
00098 if(All.NumFilesPerSnapshot > 1)
00099 sprintf(buf, "%s%s_%03d.%d", All.OutputDir, All.SnapshotFileBase, num, filenr);
00100 else
00101 sprintf(buf, "%s%s_%03d", All.OutputDir, All.SnapshotFileBase, num);
00102
00103 ngroups = All.NumFilesPerSnapshot / All.NumFilesWrittenInParallel;
00104 if((All.NumFilesPerSnapshot % All.NumFilesWrittenInParallel))
00105 ngroups++;
00106
00107 for(gr = 0; gr < ngroups; gr++)
00108 {
00109 if((filenr / All.NumFilesWrittenInParallel) == gr)
00110 write_file(buf, masterTask, lastTask);
00111 MPI_Barrier(MPI_COMM_WORLD);
00112 }
00113
00114
00115 if(ThisTask == 0)
00116 printf("done with snapshot.\n");
00117
00118 t1 = second();
00119
00120 All.CPU_Snapshot += timediff(t0, t1);
00121
00122 }
00123
00124
00125
00129 void fill_write_buffer(enum iofields blocknr, int *startindex, int pc, int type)
00130 {
00131 int n, k, pindex;
00132 float *fp;
00133
00134 #ifdef LONGIDS
00135 long long *ip;
00136 #else
00137 int *ip;
00138 #endif
00139
00140 #ifdef PERIODIC
00141 FLOAT boxSize;
00142 #endif
00143 #ifdef PMGRID
00144 double dt_gravkick_pm = 0;
00145 #endif
00146 double dt_gravkick, dt_hydrokick, a3inv = 1, fac1, fac2;
00147
00148
00149 if(All.ComovingIntegrationOn)
00150 {
00151 a3inv = 1 / (All.Time * All.Time * All.Time);
00152 fac1 = 1 / (All.Time * All.Time);
00153 fac2 = 1 / pow(All.Time, 3 * GAMMA - 2);
00154 }
00155 else
00156 a3inv = fac1 = fac2 = 1;
00157
00158 #ifdef PMGRID
00159 if(All.ComovingIntegrationOn)
00160 dt_gravkick_pm =
00161 get_gravkick_factor(All.PM_Ti_begstep,
00162 All.Ti_Current) -
00163 get_gravkick_factor(All.PM_Ti_begstep, (All.PM_Ti_begstep + All.PM_Ti_endstep) / 2);
00164 else
00165 dt_gravkick_pm = (All.Ti_Current - (All.PM_Ti_begstep + All.PM_Ti_endstep) / 2) * All.Timebase_interval;
00166 #endif
00167
00168
00169
00170 fp = CommBuffer;
00171 ip = CommBuffer;
00172
00173 pindex = *startindex;
00174
00175 switch (blocknr)
00176 {
00177 case IO_POS:
00178 for(n = 0; n < pc; pindex++)
00179 if(P[pindex].Type == type)
00180 {
00181 for(k = 0; k < 3; k++)
00182 {
00183 fp[k] = P[pindex].Pos[k];
00184 #ifdef PERIODIC
00185 boxSize = All.BoxSize;
00186 #ifdef LONG_X
00187 if(k == 0)
00188 boxSize = All.BoxSize * LONG_X;
00189 #endif
00190 #ifdef LONG_Y
00191 if(k == 1)
00192 boxSize = All.BoxSize * LONG_Y;
00193 #endif
00194 #ifdef LONG_Z
00195 if(k == 2)
00196 boxSize = All.BoxSize * LONG_Z;
00197 #endif
00198 while(fp[k] < 0)
00199 fp[k] += boxSize;
00200 while(fp[k] >= boxSize)
00201 fp[k] -= boxSize;
00202 #endif
00203 }
00204 n++;
00205 fp += 3;
00206 }
00207 break;
00208
00209 case IO_VEL:
00210 for(n = 0; n < pc; pindex++)
00211 if(P[pindex].Type == type)
00212 {
00213 if(All.ComovingIntegrationOn)
00214 {
00215 dt_gravkick =
00216 get_gravkick_factor(P[pindex].Ti_begstep,
00217 All.Ti_Current) -
00218 get_gravkick_factor(P[pindex].Ti_begstep,
00219 (P[pindex].Ti_begstep + P[pindex].Ti_endstep) / 2);
00220 dt_hydrokick =
00221 get_hydrokick_factor(P[pindex].Ti_begstep,
00222 All.Ti_Current) -
00223 get_hydrokick_factor(P[pindex].Ti_begstep,
00224 (P[pindex].Ti_begstep + P[pindex].Ti_endstep) / 2);
00225 }
00226 else
00227 dt_gravkick = dt_hydrokick =
00228 (All.Ti_Current - (P[pindex].Ti_begstep + P[pindex].Ti_endstep) / 2) * All.Timebase_interval;
00229
00230 for(k = 0; k < 3; k++)
00231 {
00232 fp[k] = P[pindex].Vel[k] + P[pindex].GravAccel[k] * dt_gravkick;
00233 if(P[pindex].Type == 0)
00234 fp[k] += SphP[pindex].HydroAccel[k] * dt_hydrokick;
00235 }
00236 #ifdef PMGRID
00237 for(k = 0; k < 3; k++)
00238 fp[k] += P[pindex].GravPM[k] * dt_gravkick_pm;
00239 #endif
00240 for(k = 0; k < 3; k++)
00241 fp[k] *= sqrt(a3inv);
00242
00243 n++;
00244 fp += 3;
00245 }
00246 break;
00247
00248 case IO_ID:
00249 for(n = 0; n < pc; pindex++)
00250 if(P[pindex].Type == type)
00251 {
00252 *ip++ = P[pindex].ID;
00253 n++;
00254 }
00255 break;
00256
00257 case IO_MASS:
00258 for(n = 0; n < pc; pindex++)
00259 if(P[pindex].Type == type)
00260 {
00261 *fp++ = P[pindex].Mass;
00262 n++;
00263 }
00264 break;
00265
00266 case IO_U:
00267 for(n = 0; n < pc; pindex++)
00268 if(P[pindex].Type == type)
00269 {
00270 #ifdef ISOTHERM_EQS
00271 *fp++ = SphP[pindex].Entropy;
00272 #else
00273 *fp++ =
00274 dmax(All.MinEgySpec,
00275 SphP[pindex].Entropy / GAMMA_MINUS1 * pow(SphP[pindex].Density * a3inv, GAMMA_MINUS1));
00276 #endif
00277 n++;
00278 }
00279 break;
00280
00281 case IO_RHO:
00282 for(n = 0; n < pc; pindex++)
00283 if(P[pindex].Type == type)
00284 {
00285 *fp++ = SphP[pindex].Density;
00286 n++;
00287 }
00288 break;
00289
00290 case IO_HSML:
00291 for(n = 0; n < pc; pindex++)
00292 if(P[pindex].Type == type)
00293 {
00294 *fp++ = SphP[pindex].Hsml;
00295 n++;
00296 }
00297 break;
00298
00299
00300 case IO_POT:
00301 #ifdef OUTPUTPOTENTIAL
00302 for(n = 0; n < pc; pindex++)
00303 if(P[pindex].Type == type)
00304 {
00305 *fp++ = P[pindex].Potential;
00306 n++;
00307 }
00308 #endif
00309 break;
00310
00311 case IO_ACCEL:
00312 #ifdef OUTPUTACCELERATION
00313 for(n = 0; n < pc; pindex++)
00314 if(P[pindex].Type == type)
00315 {
00316 for(k = 0; k < 3; k++)
00317 fp[k] = fac1 * P[pindex].GravAccel[k];
00318 #ifdef PMGRID
00319 for(k = 0; k < 3; k++)
00320 fp[k] += fac1 * P[pindex].GravPM[k];
00321 #endif
00322 if(P[pindex].Type == 0)
00323 for(k = 0; k < 3; k++)
00324 fp[k] += fac2 * SphP[pindex].HydroAccel[k];
00325 fp += 3;
00326 n++;
00327 }
00328 #endif
00329 break;
00330
00331 case IO_DTENTR:
00332 #ifdef OUTPUTCHANGEOFENTROPY
00333 for(n = 0; n < pc; pindex++)
00334 if(P[pindex].Type == type)
00335 {
00336 *fp++ = SphP[pindex].DtEntropy;
00337 n++;
00338 }
00339 #endif
00340 break;
00341
00342 case IO_TSTP:
00343 #ifdef OUTPUTTIMESTEP
00344
00345 for(n = 0; n < pc; pindex++)
00346 if(P[pindex].Type == type)
00347 {
00348 *fp++ = (P[pindex].Ti_endstep - P[pindex].Ti_begstep) * All.Timebase_interval;
00349 n++;
00350 }
00351 #endif
00352 break;
00353
00354 }
00355
00356 *startindex = pindex;
00357 }
00358
00359
00360
00361
00366 int get_bytes_per_blockelement(enum iofields blocknr)
00367 {
00368 int bytes_per_blockelement = 0;
00369
00370 switch (blocknr)
00371 {
00372 case IO_POS:
00373 case IO_VEL:
00374 case IO_ACCEL:
00375 bytes_per_blockelement = 3 * sizeof(float);
00376 break;
00377
00378 case IO_ID:
00379 #ifdef LONGIDS
00380 bytes_per_blockelement = sizeof(long long);
00381 #else
00382 bytes_per_blockelement = sizeof(int);
00383 #endif
00384 break;
00385
00386 case IO_MASS:
00387 case IO_U:
00388 case IO_RHO:
00389 case IO_HSML:
00390 case IO_POT:
00391 case IO_DTENTR:
00392 case IO_TSTP:
00393 bytes_per_blockelement = sizeof(float);
00394 break;
00395 }
00396
00397 return bytes_per_blockelement;
00398 }
00399
00400
00405 int get_datatype_in_block(enum iofields blocknr)
00406 {
00407 int typekey;
00408
00409 switch (blocknr)
00410 {
00411 case IO_ID:
00412 #ifdef LONGIDS
00413 typekey = 2;
00414 #else
00415 typekey = 0;
00416 #endif
00417 break;
00418
00419 default:
00420 typekey = 1;
00421 break;
00422 }
00423
00424 return typekey;
00425 }
00426
00427
00432 int get_values_per_blockelement(enum iofields blocknr)
00433 {
00434 int values = 0;
00435
00436 switch (blocknr)
00437 {
00438 case IO_POS:
00439 case IO_VEL:
00440 case IO_ACCEL:
00441 values = 3;
00442 break;
00443
00444 case IO_ID:
00445 case IO_MASS:
00446 case IO_U:
00447 case IO_RHO:
00448 case IO_HSML:
00449 case IO_POT:
00450 case IO_DTENTR:
00451 case IO_TSTP:
00452 values = 1;
00453 break;
00454 }
00455
00456 return values;
00457 }
00458
00459
00465 int get_particles_in_block(enum iofields blocknr, int *typelist)
00466 {
00467 int i, nall, ntot_withmasses, ngas, nstars;
00468
00469 nall = 0;
00470 ntot_withmasses = 0;
00471
00472 for(i = 0; i < 6; i++)
00473 {
00474 typelist[i] = 0;
00475
00476 if(header.npart[i] > 0)
00477 {
00478 nall += header.npart[i];
00479 typelist[i] = 1;
00480 }
00481
00482 if(All.MassTable[i] == 0)
00483 ntot_withmasses += header.npart[i];
00484 }
00485
00486 ngas = header.npart[0];
00487 nstars = header.npart[4];
00488
00489
00490 switch (blocknr)
00491 {
00492 case IO_POS:
00493 case IO_VEL:
00494 case IO_ACCEL:
00495 case IO_TSTP:
00496 case IO_ID:
00497 case IO_POT:
00498 return nall;
00499 break;
00500
00501 case IO_MASS:
00502 for(i = 0; i < 6; i++)
00503 {
00504 typelist[i] = 0;
00505 if(All.MassTable[i] == 0 && header.npart[i] > 0)
00506 typelist[i] = 1;
00507 }
00508 return ntot_withmasses;
00509 break;
00510
00511 case IO_U:
00512 case IO_RHO:
00513 case IO_HSML:
00514 case IO_DTENTR:
00515 for(i = 1; i < 6; i++)
00516 typelist[i] = 0;
00517 return ngas;
00518 break;
00519 }
00520
00521 endrun(212);
00522 return 0;
00523 }
00524
00525
00526
00532 int blockpresent(enum iofields blocknr)
00533 {
00534
00535 #ifndef OUTPUTPOTENTIAL
00536 if(blocknr == IO_POT)
00537 return 0;
00538 #endif
00539
00540 #ifndef OUTPUTACCELERATION
00541 if(blocknr == IO_ACCEL)
00542 return 0;
00543 #endif
00544
00545 #ifndef OUTPUTCHANGEOFENTROPY
00546 if(blocknr == IO_DTENTR)
00547 return 0;
00548 #endif
00549
00550 #ifndef OUTPUTTIMESTEP
00551 if(blocknr == IO_TSTP)
00552 return 0;
00553 #endif
00554
00555 return 1;
00556 }
00557
00558
00559
00560
00566 void fill_Tab_IO_Labels(void)
00567 {
00568 enum iofields i;
00569
00570 for(i = 0; i < IO_NBLOCKS; i++)
00571 switch (i)
00572 {
00573 case IO_POS:
00574 strncpy(Tab_IO_Labels[IO_POS], "POS ", 4);
00575 break;
00576 case IO_VEL:
00577 strncpy(Tab_IO_Labels[IO_VEL], "VEL ", 4);
00578 break;
00579 case IO_ID:
00580 strncpy(Tab_IO_Labels[IO_ID], "ID ", 4);
00581 break;
00582 case IO_MASS:
00583 strncpy(Tab_IO_Labels[IO_MASS], "MASS", 4);
00584 break;
00585 case IO_U:
00586 strncpy(Tab_IO_Labels[IO_U], "U ", 4);
00587 break;
00588 case IO_RHO:
00589 strncpy(Tab_IO_Labels[IO_RHO], "RHO ", 4);
00590 break;
00591 case IO_HSML:
00592 strncpy(Tab_IO_Labels[IO_HSML], "HSML", 4);
00593 break;
00594 case IO_POT:
00595 strncpy(Tab_IO_Labels[IO_POT], "POT ", 4);
00596 break;
00597 case IO_ACCEL:
00598 strncpy(Tab_IO_Labels[IO_ACCEL], "ACCE", 4);
00599 break;
00600 case IO_DTENTR:
00601 strncpy(Tab_IO_Labels[IO_DTENTR], "ENDT", 4);
00602 break;
00603 case IO_TSTP:
00604 strncpy(Tab_IO_Labels[IO_TSTP], "TSTP", 4);
00605 break;
00606 }
00607 }
00608
00613 void get_dataset_name(enum iofields blocknr, char *buf)
00614 {
00615
00616 strcpy(buf, "default");
00617
00618 switch (blocknr)
00619 {
00620 case IO_POS:
00621 strcpy(buf, "Coordinates");
00622 break;
00623 case IO_VEL:
00624 strcpy(buf, "Velocities");
00625 break;
00626 case IO_ID:
00627 strcpy(buf, "ParticleIDs");
00628 break;
00629 case IO_MASS:
00630 strcpy(buf, "Masses");
00631 break;
00632 case IO_U:
00633 strcpy(buf, "InternalEnergy");
00634 break;
00635 case IO_RHO:
00636 strcpy(buf, "Density");
00637 break;
00638 case IO_HSML:
00639 strcpy(buf, "SmoothingLength");
00640 break;
00641 case IO_POT:
00642 strcpy(buf, "Potential");
00643 break;
00644 case IO_ACCEL:
00645 strcpy(buf, "Acceleration");
00646 break;
00647 case IO_DTENTR:
00648 strcpy(buf, "RateOfChangeOfEntropy");
00649 break;
00650 case IO_TSTP:
00651 strcpy(buf, "TimeStep");
00652 break;
00653 }
00654 }
00655
00656
00657
00672 void write_file(char *fname, int writeTask, int lastTask)
00673 {
00674 int type, bytes_per_blockelement, npart, nextblock, typelist[6];
00675 int n_for_this_task, ntask, n, p, pc, offset = 0, task;
00676 int blockmaxlen, ntot_type[6], nn[6];
00677 enum iofields blocknr;
00678 int blksize;
00679 MPI_Status status;
00680 FILE *fd = 0;
00681
00682 #ifdef HAVE_HDF5
00683 hid_t hdf5_file = 0, hdf5_grp[6], hdf5_headergrp = 0, hdf5_dataspace_memory;
00684 hid_t hdf5_datatype = 0, hdf5_dataspace_in_file = 0, hdf5_dataset = 0;
00685 herr_t hdf5_status;
00686 hsize_t dims[2], count[2], start[2];
00687 int rank, pcsum = 0;
00688 char buf[500];
00689 #endif
00690
00691 #define SKIP {my_fwrite(&blksize,sizeof(int),1,fd);}
00692
00693
00694
00695 if(ThisTask == writeTask)
00696 {
00697 for(n = 0; n < 6; n++)
00698 ntot_type[n] = n_type[n];
00699
00700 for(task = writeTask + 1; task <= lastTask; task++)
00701 {
00702 MPI_Recv(&nn[0], 6, MPI_INT, task, TAG_LOCALN, MPI_COMM_WORLD, &status);
00703 for(n = 0; n < 6; n++)
00704 ntot_type[n] += nn[n];
00705 }
00706
00707 for(task = writeTask + 1; task <= lastTask; task++)
00708 MPI_Send(&ntot_type[0], 6, MPI_INT, task, TAG_N, MPI_COMM_WORLD);
00709 }
00710 else
00711 {
00712 MPI_Send(&n_type[0], 6, MPI_INT, writeTask, TAG_LOCALN, MPI_COMM_WORLD);
00713 MPI_Recv(&ntot_type[0], 6, MPI_INT, writeTask, TAG_N, MPI_COMM_WORLD, &status);
00714 }
00715
00716
00717
00718
00719
00720 for(n = 0; n < 6; n++)
00721 {
00722 header.npart[n] = ntot_type[n];
00723 header.npartTotal[n] = (unsigned int) ntot_type_all[n];
00724 header.npartTotalHighWord[n] = (unsigned int) (ntot_type_all[n] >> 32);
00725 }
00726
00727 for(n = 0; n < 6; n++)
00728 header.mass[n] = All.MassTable[n];
00729
00730 header.time = All.Time;
00731
00732 if(All.ComovingIntegrationOn)
00733 header.redshift = 1.0 / All.Time - 1;
00734 else
00735 header.redshift = 0;
00736
00737 header.flag_sfr = 0;
00738 header.flag_feedback = 0;
00739 header.flag_cooling = 0;
00740 header.flag_stellarage = 0;
00741 header.flag_metals = 0;
00742
00743 #ifdef COOLING
00744 header.flag_cooling = 1;
00745 #endif
00746 #ifdef SFR
00747 header.flag_sfr = 1;
00748 header.flag_feedback = 1;
00749 #ifdef STELLARAGE
00750 header.flag_stellarage = 1;
00751 #endif
00752 #ifdef METALS
00753 header.flag_metals = 1;
00754 #endif
00755 #endif
00756
00757 header.num_files = All.NumFilesPerSnapshot;
00758 header.BoxSize = All.BoxSize;
00759 header.Omega0 = All.Omega0;
00760 header.OmegaLambda = All.OmegaLambda;
00761 header.HubbleParam = All.HubbleParam;
00762
00763
00764
00765
00766 if(ThisTask == writeTask)
00767 {
00768 if(All.SnapFormat == 3)
00769 {
00770 #ifdef HAVE_HDF5
00771 sprintf(buf, "%s.hdf5", fname);
00772 hdf5_file = H5Fcreate(buf, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
00773
00774 hdf5_headergrp = H5Gcreate(hdf5_file, "/Header", 0);
00775
00776 for(type = 0; type < 6; type++)
00777 {
00778 if(header.npart[type] > 0)
00779 {
00780 sprintf(buf, "/PartType%d", type);
00781 hdf5_grp[type] = H5Gcreate(hdf5_file, buf, 0);
00782 }
00783 }
00784
00785 write_header_attributes_in_hdf5(hdf5_headergrp);
00786 #endif
00787 }
00788 else
00789 {
00790 if(!(fd = fopen(fname, "w")))
00791 {
00792 printf("can't open file `%s' for writing snapshot.\n", fname);
00793 endrun(123);
00794 }
00795
00796 if(All.SnapFormat == 2)
00797 {
00798 blksize = sizeof(int) + 4 * sizeof(char);
00799 SKIP;
00800 my_fwrite("HEAD", sizeof(char), 4, fd);
00801 nextblock = sizeof(header) + 2 * sizeof(int);
00802 my_fwrite(&nextblock, sizeof(int), 1, fd);
00803 SKIP;
00804 }
00805
00806 blksize = sizeof(header);
00807 SKIP;
00808 my_fwrite(&header, sizeof(header), 1, fd);
00809 SKIP;
00810 }
00811 }
00812
00813 ntask = lastTask - writeTask + 1;
00814
00815 for(blocknr = 0; blocknr < IO_NBLOCKS; blocknr++)
00816 {
00817 if(blockpresent(blocknr))
00818 {
00819 bytes_per_blockelement = get_bytes_per_blockelement(blocknr);
00820
00821 blockmaxlen = ((int) (All.BufferSize * 1024 * 1024)) / bytes_per_blockelement;
00822
00823 npart = get_particles_in_block(blocknr, &typelist[0]);
00824
00825 if(npart > 0)
00826 {
00827 if(ThisTask == writeTask)
00828 {
00829
00830 if(All.SnapFormat == 1 || All.SnapFormat == 2)
00831 {
00832 if(All.SnapFormat == 2)
00833 {
00834 blksize = sizeof(int) + 4 * sizeof(char);
00835 SKIP;
00836 my_fwrite(Tab_IO_Labels[blocknr], sizeof(char), 4, fd);
00837 nextblock = npart * bytes_per_blockelement + 2 * sizeof(int);
00838 my_fwrite(&nextblock, sizeof(int), 1, fd);
00839 SKIP;
00840 }
00841
00842 blksize = npart * bytes_per_blockelement;
00843 SKIP;
00844
00845 }
00846 }
00847
00848 for(type = 0; type < 6; type++)
00849 {
00850 if(typelist[type])
00851 {
00852 #ifdef HAVE_HDF5
00853 if(ThisTask == writeTask && All.SnapFormat == 3 && header.npart[type] > 0)
00854 {
00855 switch (get_datatype_in_block(blocknr))
00856 {
00857 case 0:
00858 hdf5_datatype = H5Tcopy(H5T_NATIVE_UINT);
00859 break;
00860 case 1:
00861 hdf5_datatype = H5Tcopy(H5T_NATIVE_FLOAT);
00862 break;
00863 case 2:
00864 hdf5_datatype = H5Tcopy(H5T_NATIVE_UINT64);
00865 break;
00866 }
00867
00868 dims[0] = header.npart[type];
00869 dims[1] = get_values_per_blockelement(blocknr);
00870 if(dims[1] == 1)
00871 rank = 1;
00872 else
00873 rank = 2;
00874
00875 get_dataset_name(blocknr, buf);
00876
00877 hdf5_dataspace_in_file = H5Screate_simple(rank, dims, NULL);
00878 hdf5_dataset =
00879 H5Dcreate(hdf5_grp[type], buf, hdf5_datatype, hdf5_dataspace_in_file,
00880 H5P_DEFAULT);
00881 pcsum = 0;
00882 }
00883 #endif
00884
00885 for(task = writeTask, offset = 0; task <= lastTask; task++)
00886 {
00887 if(task == ThisTask)
00888 {
00889 n_for_this_task = n_type[type];
00890
00891 for(p = writeTask; p <= lastTask; p++)
00892 if(p != ThisTask)
00893 MPI_Send(&n_for_this_task, 1, MPI_INT, p, TAG_NFORTHISTASK, MPI_COMM_WORLD);
00894 }
00895 else
00896 MPI_Recv(&n_for_this_task, 1, MPI_INT, task, TAG_NFORTHISTASK, MPI_COMM_WORLD,
00897 &status);
00898
00899 while(n_for_this_task > 0)
00900 {
00901 pc = n_for_this_task;
00902
00903 if(pc > blockmaxlen)
00904 pc = blockmaxlen;
00905
00906 if(ThisTask == task)
00907 fill_write_buffer(blocknr, &offset, pc, type);
00908
00909 if(ThisTask == writeTask && task != writeTask)
00910 MPI_Recv(CommBuffer, bytes_per_blockelement * pc, MPI_BYTE, task,
00911 TAG_PDATA, MPI_COMM_WORLD, &status);
00912
00913 if(ThisTask != writeTask && task == ThisTask)
00914 MPI_Ssend(CommBuffer, bytes_per_blockelement * pc, MPI_BYTE, writeTask,
00915 TAG_PDATA, MPI_COMM_WORLD);
00916
00917 if(ThisTask == writeTask)
00918 {
00919 if(All.SnapFormat == 3)
00920 {
00921 #ifdef HAVE_HDF5
00922 start[0] = pcsum;
00923 start[1] = 0;
00924
00925 count[0] = pc;
00926 count[1] = get_values_per_blockelement(blocknr);
00927 pcsum += pc;
00928
00929 H5Sselect_hyperslab(hdf5_dataspace_in_file, H5S_SELECT_SET,
00930 start, NULL, count, NULL);
00931
00932 dims[0] = pc;
00933 dims[1] = get_values_per_blockelement(blocknr);
00934 hdf5_dataspace_memory = H5Screate_simple(rank, dims, NULL);
00935
00936 hdf5_status =
00937 H5Dwrite(hdf5_dataset, hdf5_datatype, hdf5_dataspace_memory,
00938 hdf5_dataspace_in_file, H5P_DEFAULT, CommBuffer);
00939
00940 H5Sclose(hdf5_dataspace_memory);
00941 #endif
00942 }
00943 else
00944 my_fwrite(CommBuffer, bytes_per_blockelement, pc, fd);
00945 }
00946
00947 n_for_this_task -= pc;
00948 }
00949 }
00950
00951 #ifdef HAVE_HDF5
00952 if(ThisTask == writeTask && All.SnapFormat == 3 && header.npart[type] > 0)
00953 {
00954 if(All.SnapFormat == 3)
00955 {
00956 H5Dclose(hdf5_dataset);
00957 H5Sclose(hdf5_dataspace_in_file);
00958 H5Tclose(hdf5_datatype);
00959 }
00960 }
00961 #endif
00962 }
00963 }
00964
00965 if(ThisTask == writeTask)
00966 {
00967 if(All.SnapFormat == 1 || All.SnapFormat == 2)
00968 SKIP;
00969 }
00970 }
00971 }
00972 }
00973
00974 if(ThisTask == writeTask)
00975 {
00976 if(All.SnapFormat == 3)
00977 {
00978 #ifdef HAVE_HDF5
00979 for(type = 5; type >= 0; type--)
00980 if(header.npart[type] > 0)
00981 H5Gclose(hdf5_grp[type]);
00982 H5Gclose(hdf5_headergrp);
00983 H5Fclose(hdf5_file);
00984 #endif
00985 }
00986 else
00987 fclose(fd);
00988 }
00989 }
00990
00991
00992
00993
00997 #ifdef HAVE_HDF5
00998 void write_header_attributes_in_hdf5(hid_t handle)
00999 {
01000 hsize_t adim[1] = { 6 };
01001 hid_t hdf5_dataspace, hdf5_attribute;
01002
01003 hdf5_dataspace = H5Screate(H5S_SIMPLE);
01004 H5Sset_extent_simple(hdf5_dataspace, 1, adim, NULL);
01005 hdf5_attribute = H5Acreate(handle, "NumPart_ThisFile", H5T_NATIVE_INT, hdf5_dataspace, H5P_DEFAULT);
01006 H5Awrite(hdf5_attribute, H5T_NATIVE_UINT, header.npart);
01007 H5Aclose(hdf5_attribute);
01008 H5Sclose(hdf5_dataspace);
01009
01010 hdf5_dataspace = H5Screate(H5S_SIMPLE);
01011 H5Sset_extent_simple(hdf5_dataspace, 1, adim, NULL);
01012 hdf5_attribute = H5Acreate(handle, "NumPart_Total", H5T_NATIVE_UINT, hdf5_dataspace, H5P_DEFAULT);
01013 H5Awrite(hdf5_attribute, H5T_NATIVE_UINT, header.npartTotal);
01014 H5Aclose(hdf5_attribute);
01015 H5Sclose(hdf5_dataspace);
01016
01017 hdf5_dataspace = H5Screate(H5S_SIMPLE);
01018 H5Sset_extent_simple(hdf5_dataspace, 1, adim, NULL);
01019 hdf5_attribute = H5Acreate(handle, "NumPart_Total_HW", H5T_NATIVE_UINT, hdf5_dataspace, H5P_DEFAULT);
01020 H5Awrite(hdf5_attribute, H5T_NATIVE_UINT, header.npartTotalHighWord);
01021 H5Aclose(hdf5_attribute);
01022 H5Sclose(hdf5_dataspace);
01023
01024
01025 hdf5_dataspace = H5Screate(H5S_SIMPLE);
01026 H5Sset_extent_simple(hdf5_dataspace, 1, adim, NULL);
01027 hdf5_attribute = H5Acreate(handle, "MassTable", H5T_NATIVE_DOUBLE, hdf5_dataspace, H5P_DEFAULT);
01028 H5Awrite(hdf5_attribute, H5T_NATIVE_DOUBLE, header.mass);
01029 H5Aclose(hdf5_attribute);
01030 H5Sclose(hdf5_dataspace);
01031
01032 hdf5_dataspace = H5Screate(H5S_SCALAR);
01033 hdf5_attribute = H5Acreate(handle, "Time", H5T_NATIVE_DOUBLE, hdf5_dataspace, H5P_DEFAULT);
01034 H5Awrite(hdf5_attribute, H5T_NATIVE_DOUBLE, &header.time);
01035 H5Aclose(hdf5_attribute);
01036 H5Sclose(hdf5_dataspace);
01037
01038 hdf5_dataspace = H5Screate(H5S_SCALAR);
01039 hdf5_attribute = H5Acreate(handle, "Redshift", H5T_NATIVE_DOUBLE, hdf5_dataspace, H5P_DEFAULT);
01040 H5Awrite(hdf5_attribute, H5T_NATIVE_DOUBLE, &header.redshift);
01041 H5Aclose(hdf5_attribute);
01042 H5Sclose(hdf5_dataspace);
01043
01044 hdf5_dataspace = H5Screate(H5S_SCALAR);
01045 hdf5_attribute = H5Acreate(handle, "BoxSize", H5T_NATIVE_DOUBLE, hdf5_dataspace, H5P_DEFAULT);
01046 H5Awrite(hdf5_attribute, H5T_NATIVE_DOUBLE, &header.BoxSize);
01047 H5Aclose(hdf5_attribute);
01048 H5Sclose(hdf5_dataspace);
01049
01050 hdf5_dataspace = H5Screate(H5S_SCALAR);
01051 hdf5_attribute = H5Acreate(handle, "NumFilesPerSnapshot", H5T_NATIVE_INT, hdf5_dataspace, H5P_DEFAULT);
01052 H5Awrite(hdf5_attribute, H5T_NATIVE_INT, &header.num_files);
01053 H5Aclose(hdf5_attribute);
01054 H5Sclose(hdf5_dataspace);
01055
01056 hdf5_dataspace = H5Screate(H5S_SCALAR);
01057 hdf5_attribute = H5Acreate(handle, "Omega0", H5T_NATIVE_DOUBLE, hdf5_dataspace, H5P_DEFAULT);
01058 H5Awrite(hdf5_attribute, H5T_NATIVE_DOUBLE, &header.Omega0);
01059 H5Aclose(hdf5_attribute);
01060 H5Sclose(hdf5_dataspace);
01061
01062 hdf5_dataspace = H5Screate(H5S_SCALAR);
01063 hdf5_attribute = H5Acreate(handle, "OmegaLambda", H5T_NATIVE_DOUBLE, hdf5_dataspace, H5P_DEFAULT);
01064 H5Awrite(hdf5_attribute, H5T_NATIVE_DOUBLE, &header.OmegaLambda);
01065 H5Aclose(hdf5_attribute);
01066 H5Sclose(hdf5_dataspace);
01067
01068 hdf5_dataspace = H5Screate(H5S_SCALAR);
01069 hdf5_attribute = H5Acreate(handle, "HubbleParam", H5T_NATIVE_DOUBLE, hdf5_dataspace, H5P_DEFAULT);
01070 H5Awrite(hdf5_attribute, H5T_NATIVE_DOUBLE, &header.HubbleParam);
01071 H5Aclose(hdf5_attribute);
01072 H5Sclose(hdf5_dataspace);
01073
01074 hdf5_dataspace = H5Screate(H5S_SCALAR);
01075 hdf5_attribute = H5Acreate(handle, "Flag_Sfr", H5T_NATIVE_INT, hdf5_dataspace, H5P_DEFAULT);
01076 H5Awrite(hdf5_attribute, H5T_NATIVE_INT, &header.flag_sfr);
01077 H5Aclose(hdf5_attribute);
01078 H5Sclose(hdf5_dataspace);
01079
01080 hdf5_dataspace = H5Screate(H5S_SCALAR);
01081 hdf5_attribute = H5Acreate(handle, "Flag_Cooling", H5T_NATIVE_INT, hdf5_dataspace, H5P_DEFAULT);
01082 H5Awrite(hdf5_attribute, H5T_NATIVE_INT, &header.flag_cooling);
01083 H5Aclose(hdf5_attribute);
01084 H5Sclose(hdf5_dataspace);
01085
01086 hdf5_dataspace = H5Screate(H5S_SCALAR);
01087 hdf5_attribute = H5Acreate(handle, "Flag_StellarAge", H5T_NATIVE_INT, hdf5_dataspace, H5P_DEFAULT);
01088 H5Awrite(hdf5_attribute, H5T_NATIVE_INT, &header.flag_stellarage);
01089 H5Aclose(hdf5_attribute);
01090 H5Sclose(hdf5_dataspace);
01091
01092 hdf5_dataspace = H5Screate(H5S_SCALAR);
01093 hdf5_attribute = H5Acreate(handle, "Flag_Metals", H5T_NATIVE_INT, hdf5_dataspace, H5P_DEFAULT);
01094 H5Awrite(hdf5_attribute, H5T_NATIVE_INT, &header.flag_metals);
01095 H5Aclose(hdf5_attribute);
01096 H5Sclose(hdf5_dataspace);
01097
01098 hdf5_dataspace = H5Screate(H5S_SCALAR);
01099 hdf5_attribute = H5Acreate(handle, "Flag_Feedback", H5T_NATIVE_INT, hdf5_dataspace, H5P_DEFAULT);
01100 H5Awrite(hdf5_attribute, H5T_NATIVE_INT, &header.flag_feedback);
01101 H5Aclose(hdf5_attribute);
01102 H5Sclose(hdf5_dataspace);
01103
01104 header.flag_entropy_instead_u = 0;
01105
01106 hdf5_dataspace = H5Screate(H5S_SIMPLE);
01107 H5Sset_extent_simple(hdf5_dataspace, 1, adim, NULL);
01108 hdf5_attribute = H5Acreate(handle, "Flag_Entropy_ICs", H5T_NATIVE_UINT, hdf5_dataspace, H5P_DEFAULT);
01109 H5Awrite(hdf5_attribute, H5T_NATIVE_UINT, &header.flag_entropy_instead_u);
01110 H5Aclose(hdf5_attribute);
01111 H5Sclose(hdf5_dataspace);
01112 }
01113 #endif
01114
01115
01116
01117
01118
01122 size_t my_fwrite(void *ptr, size_t size, size_t nmemb, FILE * stream)
01123 {
01124 size_t nwritten;
01125
01126 if((nwritten = fwrite(ptr, size, nmemb, stream)) != nmemb)
01127 {
01128 printf("I/O error (fwrite) on task=%d has occured: %s\n", ThisTask, strerror(errno));
01129 fflush(stdout);
01130 endrun(777);
01131 }
01132 return nwritten;
01133 }
01134
01135
01139 size_t my_fread(void *ptr, size_t size, size_t nmemb, FILE * stream)
01140 {
01141 size_t nread;
01142
01143 if((nread = fread(ptr, size, nmemb, stream)) != nmemb)
01144 {
01145 printf("I/O error (fread) on task=%d has occured: %s\n", ThisTask, strerror(errno));
01146 fflush(stdout);
01147 endrun(778);
01148 }
01149 return nread;
01150 }