12#include "gadgetconfig.h"
16#include <gsl/gsl_rng.h>
27#include "../data/allvars.h"
28#include "../data/dtypes.h"
29#include "../data/intposconvert.h"
30#include "../data/mymalloc.h"
31#include "../io/hdf5_util.h"
32#include "../lightcone/lightcone.h"
33#include "../lightcone/lightcone_massmap_io.h"
34#include "../main/main.h"
35#include "../main/simulation.h"
36#include "../sort/cxxsort.h"
37#include "../system/system.h"
39void lightcone::lightcone_init_intposconverter(
double linklength)
43#ifdef LIGHTCONE_PARTICLES
44 if(ConeGlobComDistStart > maxlength)
45 maxlength = ConeGlobComDistStart;
48#ifdef LIGHTCONE_MASSMAPS
49 for(
int i = 0; i < NumMassMapBoundaries; i++)
50 if(MassMapBoundariesComDist[i] > maxlength)
51 maxlength = MassMapBoundariesComDist[i];
54 maxlength += linklength;
56#ifdef LIGHTCONE_PARTICLES
57 Lp->RegionLen = 2.0 * maxlength;
63#ifdef LIGHTCONE_MASSMAPS
64int lightcone::lightcone_add_position_massmaps(
particle_data *P,
double *pos,
double ascale)
66 int buffer_full_flag = 0;
69 vec2pix_ring(
All.LightConeMassMapsNside, pos, &ipnest);
74 if(Mp->NumPart >= Mp->MaxPart)
77 if(Mp->NumPart >= new_maxpart)
80 Mp->reallocate_memory_maxpart(new_maxpart);
85 int p = Mp->NumPart++;
87 Mp->P[p].Ascale = ascale;
90 Mp->P[p].PixIndex = ipnest;
93 if(task < 0 || task >= NTask || ipnest < 0 || ipnest >= Mp->Npix)
94 Terminate(
"strange assignment: task=%d NTask=%d pos=(%g|%g|%g) ipnest=%d\n", task, NTask, pos[0], pos[1], pos[2], (
int)ipnest);
96 return buffer_full_flag;
100#ifdef LIGHTCONE_PARTICLES
101void lightcone::lightcone_add_position_particles(
particle_data *P,
double *pos,
double ascale)
103 if(Lp->NumPart >= Lp->MaxPart)
106 if(Lp->NumPart >= new_maxpart)
107 Terminate(
"Lp->NumPart >= new_maxpart. Lp->NumPart=%d Lp->MaxPart=%d new_maxpart=%d", Lp->NumPart, Lp->MaxPart, new_maxpart);
109 Lp->reallocate_memory_maxpart(new_maxpart);
112 int q = Lp->NumPart++;
118 for(
int i = 0; i < 3; i++)
119 Lp->P[q].IntPos[i] = intpos[i];
121 Lp->P[q].Ascale = ascale;
124 for(
int i = 0; i < 3; i++)
125 Lp->P[q].Vel[i] = P->
Vel[i] / ascale;
127#ifdef LIGHTCONE_OUTPUT_ACCELERATIONS
128 for(
int i = 0; i < 3; i++)
132 Lp->P[q].setType(P->
getType());
133 Lp->P[q].setMass(P->
getMass());
134 Lp->P[q].ID.set(P->
ID.
get());
135#if defined(LIGHTCONE_PARTICLES_GROUPS) && defined(FOF)
140 Lp->P[q].ID.mark_as_formerly_most_bound();
142#if defined(LIGHTCONE_PARTICLES_GROUPS) && defined(FOF)
143 Lp->P[q].setFlagSaveDistance();
150 int buffer_full_flag = 0;
154#ifdef LIGHTCONE_PARTICLES
155 if(time0 < ConeGlobTime_end && time1 > ConeGlobTime_start)
159#ifdef LIGHTCONE_MASSMAPS
160 if(time0 < MassMapBoundariesTime[NumMassMapBoundaries - 1] && time1 > MassMapBoundariesTime[0])
165 return buffer_full_flag;
167 static integertime last_time0 = -1, last_time1 = -1;
168 static double last_R0 = -1, last_R1 = -1;
170 if(time0 != last_time0 || time1 != last_time1)
182 double R0_squared = R0 * R0;
183 double R1_squared = R1 * R1;
185 double R1prime = R1 - (R0 - R1);
188 Sp->intpos_to_pos(P->
IntPos, pos);
190#ifdef LIGHTCONE_PARTICLES
196 for(
int n = 0; n < NumBoxes; n++)
198 if(R0 < BoxList[n].Rmin)
201 if(R1prime > BoxList[n].Rmax)
206 int i = BoxList[n].i;
207 int j = BoxList[n].j;
208 int k = BoxList[n].k;
216 double rA2 = PosA[0] * PosA[0] + PosA[1] * PosA[1] + PosA[2] * PosA[2];
221 double diffBminusA[3];
223 for(
int q = 0; q < 3; q++)
225 diffBminusA[q] = P->
Vel[q] * dt_drift * Sp->FacIntToCoord;
226 PosB[q] = PosA[q] + diffBminusA[q];
229 double rB2 = PosB[0] * PosB[0] + PosB[1] * PosB[1] + PosB[2] * PosB[2];
235 double dr2 = diffBminusA[0] * diffBminusA[0] + diffBminusA[1] * diffBminusA[1] + diffBminusA[2] * diffBminusA[2];
237 double a =
pow(R1 - R0, 2) - dr2;
238 double b = 2 * R0 * (R1 - R0) - 2 * (PosA[0] * diffBminusA[0] + PosA[1] * diffBminusA[1] + PosA[2] * diffBminusA[2]);
239 double c = R0 * R0 - rA2;
241 double det = b * b - 4 * a * c;
245 "det=%g R0=%g R1=%g rA=%g rB=%g dr=%g dt_drift=%g dx=(%g|%g|%g) vel=(%g|%g|%g) "
246 "posA=(%g|%g|%g) posB=(%g|%g|%g)\n",
247 det, R0, R1,
sqrt(rA2),
sqrt(rB2),
sqrt(dr2), dt_drift, P->
Vel[0] * dt_drift * Sp->FacIntToCoord,
248 P->
Vel[1] * dt_drift * Sp->FacIntToCoord, P->
Vel[2] * dt_drift * Sp->FacIntToCoord, P->
Vel[0], P->
Vel[1],
249 P->
Vel[2], PosA[0], PosA[1], PosA[2], PosB[0], PosB[1], PosB[2]);
251 double fac = (-b -
sqrt(det)) / (2 * a);
255 for(
int q = 0; q < 3; q++)
256 Pos[q] = PosA[q] + fac * diffBminusA[q];
262 if(fac < 0 || fac > 1)
265 "ascale=%g fac=%g fac-1%g R0=%g R1=%g rA=%g rB=%g dr=%g dt_drift=%g dx=(%g|%g|%g) vel=(%g|%g|%g) "
266 "posA=(%g|%g|%g) posB=(%g|%g|%g)\n",
267 ascale, fac, fac - 1, R0, R1,
sqrt(rA2),
sqrt(rB2),
sqrt(dr2), dt_drift,
268 P->
Vel[0] * dt_drift * Sp->FacIntToCoord, P->
Vel[1] * dt_drift * Sp->FacIntToCoord,
269 P->
Vel[2] * dt_drift * Sp->FacIntToCoord, P->
Vel[0], P->
Vel[1], P->
Vel[2], PosA[0], PosA[1], PosA[2], PosB[0],
274#ifdef LIGHTCONE_PARTICLES
275 if(ascale >= ConeGlobAstart && ascale < ConeGlobAend)
276 for(
int cone = 0; cone < Nlightcones; cone++)
277 if(lightcone_is_cone_member_basic(ascale, Pos, previously, cone))
280 lightcone_add_position_particles(P, Pos.
da, ascale);
285#ifdef LIGHTCONE_MASSMAPS
286 if(ascale >= MassMapBoundariesAscale[0] && ascale < MassMapBoundariesAscale[NumMassMapBoundaries - 1])
287 buffer_full_flag |= lightcone_add_position_massmaps(P, Pos.
da, ascale);
294 return buffer_full_flag;
297#ifdef LIGHTCONE_PARTICLES
299bool lightcone::lightcone_is_cone_member(
int i,
int cone)
301#if defined(LIGHTCONE_PARTICLES_GROUPS) && defined(FOF)
302 if(!Lp->P[i].getFlagSaveDistance())
309 Terminate(
"i=%d Lp->NumPart=%d\n", i, Lp->NumPart);
313 return lightcone_is_cone_member_basic(Lp->P[i].Ascale, pos, Lp->P[i].ID.is_previously_most_bound(), cone);
316bool lightcone::lightcone_is_cone_member_basic(
double ascale,
vector<double> &pos,
bool previously,
int cone)
318 if(ascale < Cones[cone].Astart || ascale > Cones[cone].Aend)
321 if(Cones[cone].OnlyMostBoundFlag == 1 && previously ==
false)
324 if(Cones[cone].LcType == LC_TYPE_FULLSKY)
328 else if(Cones[cone].LcType == LC_TYPE_OCTANT)
330 double rad = pos.
norm();
331 double phi =
atan2(pos[1], pos[0]);
332 double theta =
acos(pos[2] / rad);
337 int octnr = phi / (0.5 *
M_PI);
345 if(theta > 0.5 *
M_PI)
348 if(octnr == Cones[cone].OctantNr)
353 else if(Cones[cone].LcType == LC_TYPE_PENCIL)
355 double rad = pos.
norm();
359 double angle =
acos((pos * Cones[cone].PencilDir) / rad);
361 if(angle < Cones[cone].PencilAngleRad)
366 else if(Cones[cone].LcType == LC_TYPE_DISK)
368 double dist = pos * Cones[cone].DiskNormal;
370 if(
fabs(dist) < 0.5 * Cones[cone].DiskThickness)
375 else if(Cones[cone].LcType == LC_TYPE_SQUAREMAP)
377 double x = pos * Cones[cone].SquareMapXdir;
378 double y = pos * Cones[cone].SquareMapYdir;
379 double z = pos * Cones[cone].SquareMapZdir;
382 if(z > 0 &&
fabs(x) < Cones[cone].SquareMapAngleRad * z &&
fabs(y) < Cones[cone].SquareMapAngleRad * z)
390void lightcone::lightcone_init_geometry(
char *fname)
393 Terminate(
"LIGHTCONE_PARTICLES: makes only sense for cosmological simulations with ComovingIntegrationOn enabled\n");
397 for(
int iter = 0; iter < 2; iter++)
402 if(!(fd = fopen(fname,
"r")))
403 Terminate(
"LIGHTCONE_PARTICLES: cannot read lightcone geometries in file `%s'\n", fname);
410 if(fscanf(fd,
"%d", &lc_type) != 1)
417 case LC_TYPE_FULLSKY:
418 if(fscanf(fd,
"%lg %lg %lg", &dummy, &dummy, &dummy) != 3)
419 Terminate(
"LIGHTCONE_PARTICLES: incorrect data for lightcone type %d in file '%s'", lc_type, fname);
423 if(fscanf(fd,
"%lg %lg %lg %lg", &dummy, &dummy, &dummy, &dummy) != 4)
424 Terminate(
"LIGHTCONE_PARTICLES: incorrect data for lightcone type %d in file '%s'", lc_type, fname);
428 if(fscanf(fd,
"%lg %lg %lg %lg %lg %lg %lg", &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy) != 7)
429 Terminate(
"LIGHTCONE_PARTICLES: incorrect data for lightcone type %d in file '%s'", lc_type, fname);
433 if(fscanf(fd,
"%lg %lg %lg %lg %lg %lg %lg", &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy) != 7)
434 Terminate(
"LIGHTCONE_PARTICLES: incorrect data for lightcone type %d in file '%s'", lc_type, fname);
437 case LC_TYPE_SQUAREMAP:
438 if(fscanf(fd,
"%lg %lg %lg %lg %lg %lg %lg %lg %lg %lg", &dummy, &dummy, &dummy, &dummy, &dummy, &dummy,
439 &dummy, &dummy, &dummy, &dummy) != 10)
440 Terminate(
"LIGHTCONE_PARTICLES: incorrect data for squaremap type %d in file '%s'", lc_type, fname);
444 Terminate(
"LIGHTCONE_PARTICLES: unknown lightcone type %d in file '%s'", lc_type, fname);
451 Cones = (cone_data *)
Mem.mymalloc(
"Cones", Nlightcones *
sizeof(cone_data));
453 mpi_printf(
"LIGHTCONE_PARTICLES: read definitions with %d entries in file `%s'.\n", Nlightcones, fname);
460 if(fscanf(fd,
"%d", &lc_type) != 1)
463 Cones[Nlightcones].LcType = lc_type;
467 case LC_TYPE_FULLSKY:
468 fscanf(fd,
"%d %lg %lg", &Cones[Nlightcones].OnlyMostBoundFlag, &Cones[Nlightcones].Astart,
469 &Cones[Nlightcones].Aend);
470 sprintf(Cones[Nlightcones].Tag,
"Full-sky");
474 fscanf(fd,
"%d %lg %lg", &Cones[Nlightcones].OnlyMostBoundFlag, &Cones[Nlightcones].Astart,
475 &Cones[Nlightcones].Aend);
476 fscanf(fd,
"%d", &Cones[Nlightcones].OctantNr);
477 sprintf(Cones[Nlightcones].Tag,
"Octant");
481 fscanf(fd,
"%d %lg %lg", &Cones[Nlightcones].OnlyMostBoundFlag, &Cones[Nlightcones].Astart,
482 &Cones[Nlightcones].Aend);
483 fscanf(fd,
"%lg %lg %lg", &Cones[Nlightcones].PencilDir[0], &Cones[Nlightcones].PencilDir[1],
484 &Cones[Nlightcones].PencilDir[2]);
485 fscanf(fd,
"%lg", &Cones[Nlightcones].PencilAngle);
488 Cones[Nlightcones].PencilDir *= 1.0 / Cones[Nlightcones].PencilDir.norm();
491 Cones[Nlightcones].PencilAngleRad = Cones[Nlightcones].PencilAngle *
M_PI / 180.0;
493 sprintf(Cones[Nlightcones].Tag,
"Pencil-Beam");
497 fscanf(fd,
"%d %lg %lg", &Cones[Nlightcones].OnlyMostBoundFlag, &Cones[Nlightcones].Astart,
498 &Cones[Nlightcones].Aend);
499 fscanf(fd,
"%lg %lg %lg", &Cones[Nlightcones].DiskNormal[0], &Cones[Nlightcones].DiskNormal[1],
500 &Cones[Nlightcones].DiskNormal[2]);
501 fscanf(fd,
"%lg", &Cones[Nlightcones].DiskThickness);
504 Cones[Nlightcones].DiskNormal *= 1.0 / Cones[Nlightcones].DiskNormal.norm();
505 sprintf(Cones[Nlightcones].Tag,
"Disk (for image)");
508 case LC_TYPE_SQUAREMAP:
509 fscanf(fd,
"%d %lg %lg", &Cones[Nlightcones].OnlyMostBoundFlag, &Cones[Nlightcones].Astart,
510 &Cones[Nlightcones].Aend);
511 fscanf(fd,
"%lg %lg %lg", &Cones[Nlightcones].SquareMapZdir[0], &Cones[Nlightcones].SquareMapZdir[1],
512 &Cones[Nlightcones].SquareMapZdir[2]);
513 fscanf(fd,
"%lg %lg %lg", &Cones[Nlightcones].SquareMapXdir[0], &Cones[Nlightcones].SquareMapXdir[1],
514 &Cones[Nlightcones].SquareMapXdir[2]);
515 fscanf(fd,
"%lg", &Cones[Nlightcones].SquareMapAngle);
519 Cones[Nlightcones].SquareMapZdir *= 1.0 / Cones[Nlightcones].SquareMapZdir.norm();
522 Cones[Nlightcones].SquareMapYdir = Cones[Nlightcones].SquareMapZdir ^ Cones[Nlightcones].SquareMapXdir;
524 Cones[Nlightcones].SquareMapYdir *= 1.0 / Cones[Nlightcones].SquareMapYdir.norm();
527 Cones[Nlightcones].SquareMapXdir = Cones[Nlightcones].SquareMapYdir ^ Cones[Nlightcones].SquareMapZdir;
529 Cones[Nlightcones].SquareMapAngleRad = Cones[Nlightcones].SquareMapAngle *
M_PI / 180.0;
531 mpi_printf(
"LIGHTCONE_SQUAREMAP: cone=%2d x-axis = %15g %15g %15g\n", Nlightcones,
532 Cones[Nlightcones].SquareMapXdir[0], Cones[Nlightcones].SquareMapXdir[1],
533 Cones[Nlightcones].SquareMapXdir[2]);
534 mpi_printf(
"LIGHTCONE_SQUAREMAP: cone=%2d y-axis = %15g %15g %15g\n", Nlightcones,
535 Cones[Nlightcones].SquareMapYdir[0], Cones[Nlightcones].SquareMapYdir[1],
536 Cones[Nlightcones].SquareMapYdir[2]);
537 mpi_printf(
"LIGHTCONE_SQUAREMAP: cone=%2d z-axis = %15g %15g %15g\n", Nlightcones,
538 Cones[Nlightcones].SquareMapZdir[0], Cones[Nlightcones].SquareMapZdir[1],
539 Cones[Nlightcones].SquareMapZdir[2]);
540 sprintf(Cones[Nlightcones].Tag,
"Square-map");
552 for(
int i = 0; i < Nlightcones; i++)
553 mpi_printf(
"LIGHTCONE_PARTICLES: lightcone #%2d: %18s %20s Astart=%10g Aend=%10g\n", i, Cones[i].Tag,
554 Cones[i].OnlyMostBoundFlag ?
"(only most bound)" :
"(all particles)", Cones[i].Astart, Cones[i].Aend);
561 MPI_Bcast(&Nlightcones, 1, MPI_INT, 0, Communicator);
564 Cones = (cone_data *)
Mem.mymalloc(
"Cones", Nlightcones *
sizeof(cone_data));
566 MPI_Bcast(Cones, Nlightcones *
sizeof(cone_data), MPI_BYTE, 0, Communicator);
569int lightcone::lightcone_init_times(
void)
571 for(
int i = 0; i < Nlightcones; i++)
580 double astart = 1.0e10;
583 for(
int i = 0; i < Nlightcones; i++)
585 if(Cones[i].Astart < astart)
586 astart = Cones[i].Astart;
588 if(Cones[i].Aend > aend)
589 aend = Cones[i].Aend;
592 ConeGlobAstart = astart;
603 for(
int rep = 0; rep < 2; rep++)
611 for(
int i = -n; i <= n; i++)
612 for(
int j = -n; j <= n; j++)
613 for(
int k = -n; k <= n; k++)
623 if(lightcone_box_at_corner_overlaps_at_least_with_one_cone(corner, Rmin, Rmax))
627 BoxList[NumBoxes].i = i;
628 BoxList[NumBoxes].j = j;
629 BoxList[NumBoxes].k = k;
630 BoxList[NumBoxes].Rmin = Rmin;
631 BoxList[NumBoxes].Rmax = Rmax;
639 mycxxsort(BoxList, BoxList + NumBoxes, lightcone_compare_BoxList_Rmax);
641 lightcone_clear_boxlist(
All.
Time);
648 "LIGHTCONE_PARTICLES: scale_factor: %10g to %10g comoving distance: %10g to %10g covered volume in units of box "
650 ConeGlobAstart, ConeGlobAend, ConeGlobComDistStart, ConeGlobComDistEnd, fac);
652 mpi_printf(
"LIGHTCONE_PARTICLES: number of box replicas to check for this lightcone geometry settings = %d\n", NumBoxes);
654 if(NumBoxes > LIGHTCONE_MAX_BOXREPLICAS)
657 "\nLIGHTCONE_PARTICLES: Your lightcone extends to such high redshift that the box needs to be replicated a huge number of "
658 "times to cover it,\n"
659 "more than the prescribed limit of LIGHTCONE_MAX_BOXREPLICAS=%d. We better don't do such an inefficient run, unless you "
660 "override this constant.\n",
661 LIGHTCONE_MAX_BOXREPLICAS);
668void lightcone::lightcone_clear_boxlist(
double ascale)
676 for(
int i = 0; i < NumBoxes; i++)
678 if(dist < BoxList[i].Rmin)
680 BoxList[i] = BoxList[--NumBoxes];
688 mpi_printf(
"LIGHTCONE: Eliminated %d entries from BoxList\n", count);
689 mycxxsort(BoxList, BoxList + NumBoxes, lightcone_compare_BoxList_Rmax);
693bool lightcone::lightcone_box_at_corner_overlaps_at_least_with_one_cone(
double *corner,
double &Rmin,
double &Rmax)
698 for(
int ii = 0; ii <= 1; ii++)
699 for(
int jj = 0; jj <= 1; jj++)
700 for(
int kk = 0; kk <= 1; kk++)
707 double r =
sqrt(crn[0] * crn[0] + crn[1] * crn[1] + crn[2] * crn[2]);
714 for(
int cone = 0; cone < Nlightcones; cone++)
716 if(Rmin < Cones[cone].ComDistStart && Rmax > Cones[cone].ComDistEnd)
718 if(Cones[cone].LcType == LC_TYPE_FULLSKY)
722 else if(Cones[cone].LcType == LC_TYPE_OCTANT)
726 else if(Cones[cone].LcType == LC_TYPE_PENCIL)
730 else if(Cones[cone].LcType == LC_TYPE_DISK)
733 double first_dist = 0;
735 for(
int ii = 0; ii <= 1; ii++)
736 for(
int jj = 0; jj <= 1; jj++)
737 for(
int kk = 0; kk <= 1; kk++)
745 crn[0] * Cones[cone].DiskNormal[0] + crn[1] * Cones[cone].DiskNormal[1] + crn[2] * Cones[cone].DiskNormal[2];
747 if(ii == 0 && jj == 0 && kk == 0)
751 if(first_dist * dist < 0)
755 if(
fabs(dist) < mindist)
756 mindist =
fabs(dist);
758 if(mindist < 0.5 * Cones[cone].DiskThickness)
770#ifdef LIGHTCONE_MASSMAPS
772void lightcone::lightcone_init_massmaps(
void)
775 Terminate(
"LIGHTCONE_MASSMAPS: Makes only sense for cosmological simulations with ComovingIntegrationOn enabled\n");
777 Mp->Npix = nside2npix(
All.LightConeMassMapsNside);
783 for(
int iter = 0; iter < 2; iter++)
785 NumMassMapBoundaries = 0;
790 double com_dist_end = 0;
791 NumMassMapBoundaries++;
793 while(zend <=
All.LightConeMassMapMaxRedshift)
795 com_dist_end +=
All.LightConeMassMapThickness;
801 NumMassMapBoundaries++;
804 MassMapBoundariesAscale = (
double *)
Mem.mymalloc_movable(&MassMapBoundariesAscale,
"MassMapBoundariesAscale",
805 NumMassMapBoundaries *
sizeof(
double));
807 mpi_printf(
"LIGHTCONE_MASSMAPS: %d entries\n", NumMassMapBoundaries);
809 if(NumMassMapBoundaries < 2)
810 Terminate(
"Less than two boundaries detected");
815 double com_dist_end = 0;
816 MassMapBoundariesAscale[NumMassMapBoundaries] = 1.0;
817 NumMassMapBoundaries++;
819 while(zend <=
All.LightConeMassMapMaxRedshift)
821 com_dist_end +=
All.LightConeMassMapThickness;
825 MassMapBoundariesAscale[NumMassMapBoundaries] = aend;
829 NumMassMapBoundaries++;
834 mycxxsort(MassMapBoundariesAscale, MassMapBoundariesAscale + NumMassMapBoundaries, compare_doubles);
839 MPI_Bcast(&NumMassMapBoundaries, 1, MPI_INT, 0, Communicator);
842 MassMapBoundariesAscale =
843 (
double *)
Mem.mymalloc_movable(&MassMapBoundariesAscale,
"MassMapBoundariesAscale", NumMassMapBoundaries *
sizeof(
double));
845 MPI_Bcast(MassMapBoundariesAscale, NumMassMapBoundaries *
sizeof(
double), MPI_BYTE, 0, Communicator);
847 MassMapBoundariesTime =
848 (
integertime *)
Mem.mymalloc_movable(&MassMapBoundariesTime,
"MassMapBoundariesTime", NumMassMapBoundaries *
sizeof(
integertime));
849 MassMapBoundariesComDist =
850 (
double *)
Mem.mymalloc_movable(&MassMapBoundariesComDist,
"MassMapBoundariesComDist", NumMassMapBoundaries *
sizeof(
double));
853int lightcone::lightcone_massmap_report_boundaries(
void)
856 const double allowed_fac_max = LIGHTCONE_MAX_BOXREPLICAS;
858 for(
int i = 0; i < NumMassMapBoundaries; i++)
864 for(
int i = 0; i < NumMassMapBoundaries - 1; i++)
870 double shell = fac - (4 *
M_PI / 3.0) *
pow(MassMapBoundariesComDist[i + 1], 3) /
pow(
All.
BoxSize, 3);
873 "LIGHTCONE_MASSMAPS: entry=%3d scale_factor=%10.6f redshift=%10.6f comoving distance=%12.3f shell-volume in "
876 i, MassMapBoundariesAscale[i], 1 / MassMapBoundariesAscale[i] - 1, MassMapBoundariesComDist[i], shell);
882 if(fac_max > allowed_fac_max)
885 "\nLIGHTCONE_MASSMAPS: Your lightcone mass maps extend to such high redshift that the box needs to be replicated a huge "
886 "number of times to cover it (volume ratio %g). We better don't do such an inefficient run.\n"
887 "Setting LIGHTCONE_MAX_BOXREPLICAS=%g to a higher value (at least %g) can override this, however.\n",
888 fac_max, (
double)LIGHTCONE_MAX_BOXREPLICAS, fac_max);
895void lightcone::lightcone_massmap_flush(
int dump_allowed_flag)
897 lightcone_massmap_binning();
899 if(dump_allowed_flag)
901 while(
All.CurrentMassMapBoundary < NumMassMapBoundaries - 1 &&
904 lightcone_massmap_io Lcone(Mp,
this, Communicator,
All.
SnapFormat);
905 Lcone.lightcone_massmap_save(
All.CurrentMassMapBoundary++);
907 lightcone_massmap_binning();
912void lightcone::lightcone_massmap_binning(
void)
916 int *Send_count = (
int *)
Mem.mymalloc_movable(&Send_count,
"Send_count",
sizeof(
int) * NTask);
917 int *Send_offset = (
int *)
Mem.mymalloc_movable(&Send_offset,
"Send_offset",
sizeof(
int) * NTask);
918 int *Recv_count = (
int *)
Mem.mymalloc_movable(&Recv_count,
"Recv_count",
sizeof(
int) * NTask);
919 int *Recv_offset = (
int *)
Mem.mymalloc_movable(&Recv_offset,
"Recv_offset",
sizeof(
int) * NTask);
922 for(
int i = 0; i < NTask; i++)
925 for(
int i = 0; i < Mp->NumPart; i++)
927 int target = Mp->P[i].Task;
929 if(target < 0 || target >= NTask)
930 Terminate(
"i=%d: target=%d target < 0 || target >= NTask", i, target);
932 if(target != ThisTask)
933 Send_count[target]++;
936 myMPI_Alltoall(Send_count, 1, MPI_INT, Recv_count, 1, MPI_INT, Communicator);
938 Recv_offset[0] = Send_offset[0] = 0;
939 int nexport = 0, nimport = 0;
941 for(
int i = 0; i < NTask; i++)
943 nimport += Recv_count[i];
944 nexport += Send_count[i];
948 Send_offset[i] = Send_offset[i - 1] + Send_count[i - 1];
949 Recv_offset[i] = Recv_offset[i - 1] + Recv_count[i - 1];
953 lightcone_massmap_data *send_P =
954 (lightcone_massmap_data *)
Mem.mymalloc_movable(&send_P,
"send_P", nexport *
sizeof(lightcone_massmap_data));
956 for(
int i = 0; i < NTask; i++)
959 for(
int i = 0; i < Mp->NumPart; i++)
961 int target = Mp->P[i].Task;
963 if(target != ThisTask)
965 send_P[Send_offset[target] + Send_count[target]] = Mp->P[i];
966 Send_count[target]++;
968 Mp->P[i] = Mp->P[Mp->NumPart - 1];
974 if(Mp->NumPart + nimport > Mp->MaxPart)
975 Mp->reallocate_memory_maxpart(Mp->NumPart + nimport);
977 for(
int ngrp = 1; ngrp < (1 << PTask); ngrp++)
979 int recvTask = ThisTask ^ ngrp;
982 if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
983 myMPI_Sendrecv(&send_P[Send_offset[recvTask]], Send_count[recvTask] *
sizeof(lightcone_massmap_data), MPI_BYTE, recvTask,
984 TAG_DENS_A, &Mp->P[Mp->NumPart + Recv_offset[recvTask]],
985 Recv_count[recvTask] *
sizeof(lightcone_massmap_data), MPI_BYTE, recvTask,
TAG_DENS_A, Communicator,
989 Mp->NumPart += nimport;
991 Mem.myfree_movable(send_P);
993 Mem.myfree(Recv_offset);
994 Mem.myfree(Recv_count);
995 Mem.myfree(Send_offset);
996 Mem.myfree(Send_count);
998 mpi_printf(
"LIGHTCONE_MASSMAPS: before binning %9d (maxpart=%9d, memory for buffer %g MB)\n", Mp->NumPart, Mp->MaxPart,
999 (
double)Mp->MaxPart *
sizeof(lightcone_massmap_data) *
TO_MBYTE_FAC);
1004 for(
int i = 0; i < Mp->NumPart; i++)
1006 if(Mp->P[i].Task != ThisTask)
1009 if(Mp->P[i].Ascale >= MassMapBoundariesAscale[
All.CurrentMassMapBoundary] &&
1010 Mp->P[i].Ascale < MassMapBoundariesAscale[
All.CurrentMassMapBoundary + 1])
1012 int pix = Mp->P[i].PixIndex - Mp->FirstPix;
1013 if(pix < 0 || pix >= Mp->NpixLoc)
1016 MassMap[pix] += Mp->P[i].getMass();
1018 Mp->P[i] = Mp->P[Mp->NumPart - 1];
1022 else if(Mp->P[i].Ascale < MassMapBoundariesAscale[
All.CurrentMassMapBoundary])
1024 Mp->P[i] = Mp->P[Mp->NumPart - 1];
1038 mpi_printf(
"LIGHTCONE_MASSMAPS: after binning %9d (maxpart=%9d, memory for buffer %g MB) took=%g sec expunge=%d\n", Mp->NumPart,
global_data_all_processes All
bool is_previously_most_bound(void)
double get_scalefactor_for_comoving_distance(double dist)
double get_comoving_distance(integertime time0)
double timediff(double t0, double t1)
T * alloc_movable(T *&ptr, const char *varname, size_t n, const char *func, const char *file, int linenr)
#define LIGHTCONE_MAX_FILLFACTOR
#define LIGHTCONE_MASSMAP_ALLOC_FAC
#define MAX_DOUBLE_NUMBER
double mycxxsort(T *begin, T *end, Tcomp comp)
int32_t MySignedIntPosType
#define BITS_FOR_POSITIONS
int myMPI_Alltoall(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm)
int myMPI_Sendrecv(void *sendbuf, size_t sendcount, MPI_Datatype sendtype, int dest, int sendtag, void *recvbuf, size_t recvcount, MPI_Datatype recvtype, int source, int recvtag, MPI_Comm comm, MPI_Status *status)
expr atan2(half x, half y)
expr pow(half base, half exp)
int ComovingIntegrationOn
unsigned char getSofteningClass(void)
unsigned char getType(void)
vector< MyFloat > GravAccel
void subdivide_evenly_get_bin(int N, int pieces, int index, int *bin)
void subdivide_evenly(long long N, int pieces, int index_bin, long long *first, int *count)