MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
Classes | Functions | Variables
gravpm.c File Reference
#include <mpi.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <omp.h>
#include "utils.h"
#include "partmanager.h"
#include "forcetree.h"
#include "petapm.h"
#include "domain.h"
#include "walltime.h"
#include "gravity.h"
#include "cosmology.h"
#include "neutrinos_lra.h"
Include dependency graph for gravpm.c:

Go to the source code of this file.

Classes

struct  gravpm_params
 

Functions

static int pm_mark_region_for_node (int startno, int rid, int *RegionInd, const ForceTree *tt)
 
static void convert_node_to_region (PetaPM *pm, PetaPMRegion *r, struct NODE *Nodes)
 
static int hybrid_nu_gravpm_is_active (int i)
 
static void potential_transfer (PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
 
static void compute_neutrino_power (PetaPM *pm)
 
static void force_x_transfer (PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
 
static void force_y_transfer (PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
 
static void force_z_transfer (PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
 
static void readout_potential (PetaPM *pm, int i, double *mesh, double weight)
 
static void readout_force_x (PetaPM *pm, int i, double *mesh, double weight)
 
static void readout_force_y (PetaPM *pm, int i, double *mesh, double weight)
 
static void readout_force_z (PetaPM *pm, int i, double *mesh, double weight)
 
static PetaPMRegion_prepare (PetaPM *pm, PetaPMParticleStruct *pstruct, void *userdata, int *Nregions)
 
void gravpm_init_periodic (PetaPM *pm, double BoxSize, double Asmth, int Nmesh, double G)
 
void gravpm_force (PetaPM *pm, ForceTree *tree, Cosmology *CP, double Time, double UnitLength_in_cm, const char *PowerOutputDir, double TimeIC, int FastParticleType)
 
static double sinc_unnormed (double x)
 
void powerspectrum_add_mode (Power *PowerSpectrum, const int64_t k2, const int kpos[3], pfft_complex *const value, const double invwindow, double Nmesh)
 
void measure_power_spectrum (PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
 
static double diff_kernel (double w)
 
static void force_transfer (PetaPM *pm, int k, pfft_complex *value)
 

Variables

static PetaPMFunctions functions []
 
static struct gravpm_params GravPM
 

Function Documentation

◆ _prepare()

static PetaPMRegion * _prepare ( PetaPM pm,
PetaPMParticleStruct pstruct,
void *  userdata,
int *  Nregions 
)
static

Definition at line 117 of file gravpm.c.

117  {
118  /*
119  *
120  * walks down the tree, identify nodes that contains local mass and
121  * are sufficiently large in volume.
122  *
123  * for each nodes, a mesh region is created.
124  * the particles in a node are linked to their hosting region
125  * (each particle belongs
126  * to exactly one region even though it may be covered by two)
127  *
128  * */
129  ForceTree * tree = (ForceTree *) userdata;
130  /* In worst case, each topleave becomes a region: thus
131  * NTopLeaves is sufficient */
132  PetaPMRegion * regions = (PetaPMRegion *) mymalloc2("Regions", sizeof(PetaPMRegion) * tree->NTopLeaves);
133  pstruct->RegionInd = (int *) mymalloc2("RegionInd", PartManager->NumPart * sizeof(int));
134  int r = 0;
135 
136  int no = tree->firstnode; /* start with the root */
137  while(no >= 0) {
138 
139  if(!(tree->Nodes[no].f.DependsOnLocalMass)) {
140  /* node doesn't contain particles on this process, do not open */
141  no = tree->Nodes[no].sibling;
142  continue;
143  }
144  if(
145  /* node is large */
146  (tree->Nodes[no].len <= pm->BoxSize / pm->Nmesh * 24)
147  ||
148  /* node is a top leaf */
149  ( !tree->Nodes[no].f.InternalTopLevel && (tree->Nodes[no].f.TopLevel) )
150  ) {
151  regions[r].no = no;
152  r ++;
153  /* do not open */
154  no = tree->Nodes[no].sibling;
155  continue;
156  }
157  /* open */
158  no = tree->Nodes[no].s.suns[0];
159  }
160 
161  *Nregions = r;
162  int maxNregions;
163  MPI_Reduce(&r, &maxNregions, 1, MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD);
164  message(0, "max number of regions is %d\n", maxNregions);
165 
166  int64_t i;
167  int numswallowed = 0;
168  #pragma omp parallel for reduction(+: numswallowed)
169  for(i =0; i < PartManager->NumPart; i ++) {
170  /* Swallowed black hole particles stick around but should not gravitate.
171  * Short-range is handled by not adding them to the tree. */
172  if(P[i].Swallowed){
173  pstruct->RegionInd[i] = -2;
174  numswallowed++;
175  }
176  else
177  pstruct->RegionInd[i] = -1;
178  }
179 
180  /* now lets mark particles to their hosting region */
181  int64_t numpart = 0;
182 #pragma omp parallel for reduction(+: numpart)
183  for(r = 0; r < *Nregions; r++) {
184  regions[r].numpart = pm_mark_region_for_node(regions[r].no, r, pstruct->RegionInd, tree);
185  numpart += regions[r].numpart;
186  }
187  for(i = 0; i < PartManager->NumPart; i ++) {
188  if(pstruct->RegionInd[i] == -1) {
189  message(1, "i = %d father %d not assigned to a region\n", i, force_get_father(i, tree));
190  }
191  }
192  /* All particles shall have been processed just once. Otherwise we die */
193  if((numpart+numswallowed) != PartManager->NumPart) {
194  endrun(1, "Processed only %ld particles out of %ld\n", numpart, PartManager->NumPart);
195  }
196  for(r =0; r < *Nregions; r++) {
197  convert_node_to_region(pm, &regions[r], tree->Nodes);
198  }
199  /*This is done to conserve memory during the PM step*/
200  if(force_tree_allocated(tree)) force_tree_free(tree);
201 
202  /*Allocate memory for a power spectrum*/
203  powerspectrum_alloc(pm->ps, pm->Nmesh, omp_get_max_threads(), GravPM.CP->MassiveNuLinRespOn, pm->BoxSize*GravPM.UnitLength_in_cm);
204 
205  walltime_measure("/PMgrav/Regions");
206  return regions;
207 }
void message(int where, const char *fmt,...)
Definition: endrun.c:175
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
int force_tree_allocated(const ForceTree *tree)
Definition: forcetree.c:134
void force_tree_free(ForceTree *tree)
Definition: forcetree.c:1409
int force_get_father(int no, const ForceTree *tree)
Definition: forcetree.c:905
static int pm_mark_region_for_node(int startno, int rid, int *RegionInd, const ForceTree *tt)
Definition: gravpm.c:209
static struct gravpm_params GravPM
static void convert_node_to_region(PetaPM *pm, PetaPMRegion *r, struct NODE *Nodes)
Definition: gravpm.c:255
#define mymalloc2(name, size)
Definition: mymalloc.h:16
struct part_manager_type PartManager[1]
Definition: partmanager.c:11
#define P
Definition: partmanager.h:88
void powerspectrum_alloc(Power *ps, const int nbins, const int nthreads, const int MassiveNuLinResp, const double BoxSize_in_cm)
Definition: powerspectrum.c:16
int MassiveNuLinRespOn
Definition: cosmology.h:26
int NTopLeaves
Definition: forcetree.h:94
struct NODE * Nodes
Definition: forcetree.h:97
int firstnode
Definition: forcetree.h:84
int sibling
Definition: forcetree.h:40
unsigned int DependsOnLocalMass
Definition: forcetree.h:48
unsigned int TopLevel
Definition: forcetree.h:47
struct NodeChild s
Definition: forcetree.h:66
unsigned int InternalTopLevel
Definition: forcetree.h:46
struct NODE::@8 f
MyFloat len
Definition: forcetree.h:42
int suns[NMAXCHILD]
Definition: forcetree.h:32
int Nmesh
Definition: petapm.h:68
double BoxSize
Definition: petapm.h:70
Power ps[1]
Definition: petapm.h:76
Definition: petapm.h:7
int numpart
Definition: petapm.h:17
int no
Definition: petapm.h:18
double UnitLength_in_cm
Definition: gravpm.c:49
Cosmology * CP
Definition: gravpm.c:47
#define walltime_measure(name)
Definition: walltime.h:8

References PetaPM::BoxSize, convert_node_to_region(), gravpm_params::CP, NODE::DependsOnLocalMass, endrun(), NODE::f, ForceTree::firstnode, force_get_father(), force_tree_allocated(), force_tree_free(), GravPM, NODE::InternalTopLevel, NODE::len, Cosmology::MassiveNuLinRespOn, message(), mymalloc2, PetaPM::Nmesh, Region::no, ForceTree::Nodes, ForceTree::NTopLeaves, part_manager_type::NumPart, Region::numpart, P, PartManager, pm_mark_region_for_node(), powerspectrum_alloc(), PetaPM::ps, PetaPMParticleStruct::RegionInd, NODE::s, NODE::sibling, NodeChild::suns, NODE::TopLevel, gravpm_params::UnitLength_in_cm, and walltime_measure.

Referenced by gravpm_force().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ compute_neutrino_power()

static void compute_neutrino_power ( PetaPM pm)
static

Definition at line 304 of file gravpm.c.

304  {
305  Power * ps = pm->ps;
306  /*Note the power spectrum is now in Mpc units*/
307  powerspectrum_sum(ps);
308  int i;
309  /*Get delta_cdm_curr , which is P(k)^1/2.*/
310  for(i=0; i<ps->nonzero; i++) {
311  ps->Power[i] = sqrt(ps->Power[i]);
312  }
313  /*Get the neutrino power.*/
315 
316  /*Initialize the interpolation for the neutrinos*/
317  ps->nu_spline = gsl_interp_alloc(gsl_interp_linear,ps->nonzero);
318  ps->nu_acc = gsl_interp_accel_alloc();
319  gsl_interp_init(ps->nu_spline,ps->logknu,ps->delta_nu_ratio,ps->nonzero);
320  /*Zero power spectrum, which is stored with the neutrinos*/
321  powerspectrum_zero(ps);
322 }
void delta_nu_from_power(struct _powerspectrum *PowerSpectrum, Cosmology *CP, const double Time, const double TimeIC)
void powerspectrum_sum(Power *ps)
Definition: powerspectrum.c:54
void powerspectrum_zero(Power *ps)
Definition: powerspectrum.c:35
gsl_interp_accel * nu_acc
Definition: powerspectrum.h:24
double * logknu
Definition: powerspectrum.h:20
double * delta_nu_ratio
Definition: powerspectrum.h:21
double * Power
Definition: powerspectrum.h:10
gsl_interp * nu_spline
Definition: powerspectrum.h:23
double TimeIC
Definition: gravpm.c:46
double Time
Definition: gravpm.c:45

References gravpm_params::CP, delta_nu_from_power(), _powerspectrum::delta_nu_ratio, GravPM, _powerspectrum::logknu, _powerspectrum::nonzero, _powerspectrum::nu_acc, _powerspectrum::nu_spline, _powerspectrum::Power, powerspectrum_sum(), powerspectrum_zero(), PetaPM::ps, gravpm_params::Time, and gravpm_params::TimeIC.

Referenced by gravpm_force().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ convert_node_to_region()

static void convert_node_to_region ( PetaPM pm,
PetaPMRegion r,
struct NODE Nodes 
)
static

Definition at line 255 of file gravpm.c.

255  {
256  int k;
257  double cellsize = pm->BoxSize / pm->Nmesh;
258  int no = r->no;
259 #if 0
260  printf("task = %d no = %d len = %g hmax = %g center = %g %g %g\n",
261  ThisTask, no, Nodes[no].len, Nodes[no].hmax,
262  Nodes[no].center[0],
263  Nodes[no].center[1],
264  Nodes[no].center[2]);
265 #endif
266  for(k = 0; k < 3; k ++) {
267  r->offset[k] = floor((Nodes[no].center[k] - Nodes[no].len * 0.5) / cellsize);
268  int end = (int) ceil((Nodes[no].center[k] + Nodes[no].len * 0.5) / cellsize) + 1;
269  r->size[k] = end - r->offset[k] + 1;
270  r->center[k] = Nodes[no].center[k];
271  }
272 
273  /* setup the internal data structure of the region */
275 
276  r->len = Nodes[no].len;
277 }
void petapm_region_init_strides(PetaPMRegion *region)
Definition: petapm.c:813
MyFloat center[3]
Definition: forcetree.h:43
double center[3]
Definition: petapm.h:15
ptrdiff_t size[3]
Definition: petapm.h:10
ptrdiff_t offset[3]
Definition: petapm.h:9
double len
Definition: petapm.h:16
int ThisTask
Definition: test_exchange.c:23

References PetaPM::BoxSize, NODE::center, Region::center, NODE::hmax, NODE::len, Region::len, PetaPM::Nmesh, Region::no, Region::offset, petapm_region_init_strides(), Region::size, and ThisTask.

Referenced by _prepare().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ diff_kernel()

static double diff_kernel ( double  w)
static

Definition at line 454 of file gravpm.c.

454  {
455 /* order N = 1 */
456 /*
457  * This is the same as GADGET-2 but in fourier space:
458  * see gadget-2 paper and Hamming's book.
459  * c1 = 2 / 3, c2 = 1 / 12
460  * */
461  return 1 / 6.0 * (8 * sin (w) - sin (2 * w));
462 }

Referenced by force_transfer().

Here is the caller graph for this function:

◆ force_transfer()

static void force_transfer ( PetaPM pm,
int  k,
pfft_complex *  value 
)
static

Definition at line 472 of file gravpm.c.

472  {
473  double tmp0;
474  double tmp1;
475  /*
476  * negative sign is from force_x = - Del_x pot
477  *
478  * filter is i K(w)
479  * */
480  double fac = -1 * diff_kernel (k * (2 * M_PI / pm->Nmesh)) * (pm->Nmesh / pm->BoxSize);
481  tmp0 = - value[0][1] * fac;
482  tmp1 = value[0][0] * fac;
483  value[0][0] = tmp0;
484  value[0][1] = tmp1;
485 }
static double diff_kernel(double w)
Definition: gravpm.c:454

References PetaPM::BoxSize, diff_kernel(), and PetaPM::Nmesh.

Referenced by force_x_transfer(), force_y_transfer(), and force_z_transfer().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ force_x_transfer()

static void force_x_transfer ( PetaPM pm,
int64_t  k2,
int  kpos[3],
pfft_complex *  value 
)
static

Definition at line 486 of file gravpm.c.

486  {
487  force_transfer(pm, kpos[0], value);
488 }
static void force_transfer(PetaPM *pm, int k, pfft_complex *value)
Definition: gravpm.c:472

References force_transfer().

Here is the call graph for this function:

◆ force_y_transfer()

static void force_y_transfer ( PetaPM pm,
int64_t  k2,
int  kpos[3],
pfft_complex *  value 
)
static

Definition at line 489 of file gravpm.c.

489  {
490  force_transfer(pm, kpos[1], value);
491 }

References force_transfer().

Here is the call graph for this function:

◆ force_z_transfer()

static void force_z_transfer ( PetaPM pm,
int64_t  k2,
int  kpos[3],
pfft_complex *  value 
)
static

Definition at line 492 of file gravpm.c.

492  {
493  force_transfer(pm, kpos[2], value);
494 }

References force_transfer().

Here is the call graph for this function:

◆ gravpm_force()

void gravpm_force ( PetaPM pm,
ForceTree tree,
Cosmology CP,
double  Time,
double  UnitLength_in_cm,
const char *  PowerOutputDir,
double  TimeIC,
int  FastParticleType 
)

Definition at line 62 of file gravpm.c.

62  {
63  PetaPMParticleStruct pstruct = {
64  P,
65  sizeof(P[0]),
66  (char*) &P[0].Pos[0] - (char*) P,
67  (char*) &P[0].Mass - (char*) P,
68  /* Regions allocated inside _prepare*/
69  NULL,
70  /* By default all particles are active. For hybrid neutrinos set below.*/
71  NULL,
73  };
74 
76 
77  /*Initialise the kspace neutrino code if it is enabled.
78  * Mpc units are used to match power spectrum code.*/
79  if(CP->MassiveNuLinRespOn) {
82  }
83 
84  if(CP->HybridNeutrinosOn && particle_nu_fraction(&(CP->ONu.hybnu), Time, 0) == 0.)
86 
87  int i;
88  #pragma omp parallel for
89  for(i = 0; i < PartManager->NumPart; i++)
90  {
91  P[i].GravPM[0] = P[i].GravPM[1] = P[i].GravPM[2] = 0;
92  }
93 
94  /* Set up parameters*/
95  GravPM.Time = Time;
96  GravPM.TimeIC = TimeIC;
97  GravPM.CP = CP;
98  GravPM.FastParticleType = FastParticleType;
100  /*
101  * we apply potential transfer immediately after the R2C transform,
102  * Therefore the force transfer functions are based on the potential,
103  * not the density.
104  * */
105  petapm_force(pm, _prepare, &global_functions, functions, &pstruct, tree);
106  powerspectrum_sum(pm->ps);
107  /*Now save the power spectrum*/
108  powerspectrum_save(pm->ps, PowerOutputDir, "powerspectrum", Time, GrowthFactor(CP, Time, 1.0));
109  /* Save the neutrino power if it is allocated*/
110  if(pm->ps->logknu)
111  powerspectrum_nu_save(pm->ps, PowerOutputDir, "powerspectrum-nu", Time);
112  /*We are done with the power spectrum, free it*/
113  powerspectrum_free(pm->ps);
114  walltime_measure("/LongRange");
115 }
double GrowthFactor(Cosmology *CP, double astart, double aend)
Definition: cosmology.c:82
static PetaPMGlobalFunctions global_functions
Definition: glass.c:33
static void compute_neutrino_power(PetaPM *pm)
Definition: gravpm.c:304
static int hybrid_nu_gravpm_is_active(int i)
Definition: gravpm.c:465
static PetaPMRegion * _prepare(PetaPM *pm, PetaPMParticleStruct *pstruct, void *userdata, int *Nregions)
Definition: gravpm.c:117
static void potential_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: gravpm.c:380
void measure_power_spectrum(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: gravpm.c:361
static PetaPMFunctions functions[]
Definition: gravpm.c:32
void powerspectrum_nu_save(struct _powerspectrum *PowerSpectrum, const char *OutputDir, const char *filename, const double Time)
double particle_nu_fraction(const _hybrid_nu *const hybnu, const double a, const int i)
void petapm_force(PetaPM *pm, petapm_prepare_func prepare, PetaPMGlobalFunctions *global_functions, PetaPMFunctions *functions, PetaPMParticleStruct *pstruct, void *userdata)
Definition: petapm.c:353
static Cosmology * CP
Definition: power.c:27
static double UnitLength_in_cm
Definition: power.c:26
void powerspectrum_save(Power *ps, const char *OutputDir, const char *filename, const double Time, const double D1)
Definition: powerspectrum.c:92
void powerspectrum_free(Power *ps)
Definition: powerspectrum.c:44
int HybridNeutrinosOn
Definition: cosmology.h:28
_omega_nu ONu
Definition: cosmology.h:24
void(* global_analysis)(PetaPM *pm)
Definition: petapm.h:103
petapm_transfer_func global_readout
Definition: petapm.h:102
int(* active)(int i)
Definition: petapm.h:85
_hybrid_nu hybnu
int FastParticleType
Definition: gravpm.c:48

References _prepare(), PetaPMParticleStruct::active, compute_neutrino_power(), gravpm_params::CP, CP, gravpm_params::FastParticleType, functions, PetaPMGlobalFunctions::global_analysis, global_functions, PetaPMGlobalFunctions::global_readout, GravPM, GrowthFactor(), _omega_nu::hybnu, hybrid_nu_gravpm_is_active(), Cosmology::HybridNeutrinosOn, _powerspectrum::logknu, Cosmology::MassiveNuLinRespOn, measure_power_spectrum(), part_manager_type::NumPart, Cosmology::ONu, P, particle_nu_fraction(), PartManager, petapm_force(), potential_transfer(), powerspectrum_free(), powerspectrum_nu_save(), powerspectrum_save(), powerspectrum_sum(), PetaPM::ps, gravpm_params::Time, gravpm_params::TimeIC, gravpm_params::UnitLength_in_cm, UnitLength_in_cm, and walltime_measure.

Referenced by do_force_test(), run(), run_gravity_test(), and runpower().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ gravpm_init_periodic()

void gravpm_init_periodic ( PetaPM pm,
double  BoxSize,
double  Asmth,
int  Nmesh,
double  G 
)

Definition at line 53 of file gravpm.c.

53  {
54  petapm_init(pm, BoxSize, Asmth, Nmesh, G, MPI_COMM_WORLD);
55 }
void petapm_init(PetaPM *pm, double BoxSize, double Asmth, int Nmesh, double G, MPI_Comm comm)
Definition: petapm.c:94
static const double G
Definition: test_gravity.c:35

References G, and petapm_init().

Referenced by do_force_test(), run(), run_gravity_test(), runfof(), and runpower().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ hybrid_nu_gravpm_is_active()

static int hybrid_nu_gravpm_is_active ( int  i)
static

Definition at line 465 of file gravpm.c.

465  {
466  if (P[i].Type == GravPM.FastParticleType)
467  return 0;
468  else
469  return 1;
470 }

References gravpm_params::FastParticleType, GravPM, and P.

Referenced by gravpm_force().

Here is the caller graph for this function:

◆ measure_power_spectrum()

void measure_power_spectrum ( PetaPM pm,
int64_t  k2,
int  kpos[3],
pfft_complex *  value 
)

Definition at line 361 of file gravpm.c.

361  {
362  double f = 1.0;
363  /* the CIC deconvolution kernel is
364  *
365  * sinc_unnormed(k_x L / 2 Nmesh) ** 2
366  *
367  * k_x = kpos * 2pi / L
368  *
369  * */
370  int k;
371  for(k = 0; k < 3; k ++) {
372  double tmp = (kpos[k] * M_PI) / pm->Nmesh;
373  tmp = sinc_unnormed(tmp);
374  f *= 1. / (tmp * tmp);
375  }
376  powerspectrum_add_mode(pm->ps, k2, kpos, value, f, pm->Nmesh);
377 }
void powerspectrum_add_mode(Power *PowerSpectrum, const int64_t k2, const int kpos[3], pfft_complex *const value, const double invwindow, double Nmesh)
Definition: gravpm.c:327
static double sinc_unnormed(double x)
Definition: gravpm.c:291

References NODE::f, PetaPM::Nmesh, powerspectrum_add_mode(), PetaPM::ps, and sinc_unnormed().

Referenced by gravpm_force().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pm_mark_region_for_node()

static int pm_mark_region_for_node ( int  startno,
int  rid,
int *  RegionInd,
const ForceTree tt 
)
static

Definition at line 209 of file gravpm.c.

209  {
210  int numpart = 0;
211  int no = startno;
212  int endno = tree->Nodes[startno].sibling;
213  while(no >= 0 && no != endno)
214  {
215  struct NODE * nop = &tree->Nodes[no];
216  if(nop->f.ChildType == PARTICLE_NODE_TYPE) {
217  int i;
218  for(i = 0; i < nop->s.noccupied; i++) {
219  int p = nop->s.suns[i];
220  RegionInd[p] = rid;
221 #ifdef DEBUG
222  /* Check for particles outside of the node. This should never happen,
223  * unless there is a bug in tree build, or the particles are being moved.*/
224  int k;
225  for(k = 0; k < 3; k ++) {
226  double l = P[p].Pos[k] - tree->Nodes[startno].center[k];
227  l = fabs(l * 2);
228  if (l > tree->Nodes[startno].len) {
229  if(l > tree->Nodes[startno].len * (1+ 1e-7))
230  endrun(1, "enlarging node size from %g to %g, due to particle of type %d at %g %g %g id=%ld\n",
231  tree->Nodes[startno].len, l, P[p].Type, P[p].Pos[0], P[p].Pos[1], P[p].Pos[2], P[p].ID);
232  tree->Nodes[startno].len = l;
233  }
234  }
235 #endif
236  }
237  numpart += nop->s.noccupied;
238  /* Move to sibling*/
239  no = nop->sibling;
240  }
241  /* Generally this function should be handed top leaves which do not contain pseudo particles.
242  * However, sometimes it will receive an internal top node which can, if that top node is small enough.
243  * In this case, just move to the sibling: no particles to mark here.*/
244  else if(nop->f.ChildType == PSEUDO_NODE_TYPE)
245  no = nop->sibling;
246  else if(nop->f.ChildType == NODE_NODE_TYPE)
247  no = nop->s.suns[0];
248  else
249  endrun(122, "Unrecognised Node type %d, memory corruption!\n", nop->f.ChildType);
250  }
251  return numpart;
252 }
#define NODE_NODE_TYPE
Definition: forcetree.h:16
#define PARTICLE_NODE_TYPE
Definition: forcetree.h:15
#define PSEUDO_NODE_TYPE
Definition: forcetree.h:17
Definition: forcetree.h:39
unsigned int ChildType
Definition: forcetree.h:49
int noccupied
Definition: forcetree.h:35

References NODE::center, NODE::ChildType, endrun(), NODE::f, NODE::len, NodeChild::noccupied, NODE_NODE_TYPE, ForceTree::Nodes, P, PARTICLE_NODE_TYPE, PSEUDO_NODE_TYPE, NODE::s, NODE::sibling, and NodeChild::suns.

Referenced by _prepare().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ potential_transfer()

static void potential_transfer ( PetaPM pm,
int64_t  k2,
int  kpos[3],
pfft_complex *  value 
)
static

Definition at line 380 of file gravpm.c.

381 {
382  const double asmth2 = pow((2 * M_PI) * pm->Asmth / pm->Nmesh,2);
383  double f = 1.0;
384  const double smth = exp(-k2 * asmth2) / k2;
385  /* fac is - 4pi G (L / 2pi) **2 / L ** 3
386  * Gravity k2 DFT (dk **3, but )
387  * */
388  const double pot_factor = - pm->G / (M_PI * pm->BoxSize); /* to get potential */
389 
390 
391  /* the CIC deconvolution kernel is
392  *
393  * sinc_unnormed(k_x L / 2 Nmesh) ** 2
394  *
395  * k_x = kpos * 2pi / L
396  *
397  * */
398  int k;
399  for(k = 0; k < 3; k ++) {
400  double tmp = (kpos[k] * M_PI) / pm->Nmesh;
401  tmp = sinc_unnormed(tmp);
402  f *= 1. / (tmp * tmp);
403  }
404  /*
405  * first decovolution is CIC in par->mesh
406  * second decovolution is correcting readout
407  * I don't understand the second yet!
408  * */
409  const double fac = pot_factor * smth * f * f;
410  Power * ps = pm->ps;
411 
412  /*Add neutrino power if desired*/
413  if(GravPM.CP->MassiveNuLinRespOn && k2 > 0) {
414  /* Change the units of k to match those of logkk*/
415  double logk2 = log(sqrt(k2) * 2 * M_PI / ps->BoxSize_in_MPC);
416  /* Floating point roundoff and the binning means there may be a mode just beyond the box size.*/
417  if(logk2 < ps->logknu[0] && logk2 > ps->logknu[0]-log(2) )
418  logk2 = ps->logknu[0];
419  else if( logk2 > ps->logknu[ps->nonzero-1])
420  logk2 = ps->logknu[ps->nonzero-1];
421  /* Note get_neutrino_powerspec returns Omega_nu / (Omega0 -OmegaNu) * delta_nu / P_cdm^1/2, which is dimensionless.
422  * So below is: M_cdm * delta_cdm (1 + Omega_nu/(Omega0-OmegaNu) (delta_nu / delta_cdm))
423  * = M_cdm * (delta_cdm (Omega0 - OmegaNu)/Omega0 + Omega_nu/Omega0 delta_nu) * Omega0 / (Omega0-OmegaNu)
424  * = M_cdm * Omega0 / (Omega0-OmegaNu) * (delta_cdm (1 - f_nu) + f_nu delta_nu) )
425  * = M_cdm * Omega0 / (Omega0-OmegaNu) * delta_t
426  * = (M_cdm + M_nu) * delta_t
427  * This is correct for the forces, and gives the right power spectrum,
428  * once we multiply PowerSpectrum.Norm by (Omega0 / (Omega0 - OmegaNu))**2 */
429  const double nufac = 1 + ps->nu_prefac * gsl_interp_eval(ps->nu_spline,ps->logknu,
430  ps->delta_nu_ratio,logk2,ps->nu_acc);
431  value[0][0] *= nufac;
432  value[0][1] *= nufac;
433  }
434 
435  /*Compute the power spectrum*/
436  powerspectrum_add_mode(ps, k2, kpos, value, f, pm->Nmesh);
437  if(k2 == 0) {
439  const double MtotbyMcdm = GravPM.CP->Omega0/(GravPM.CP->Omega0 - pow(GravPM.Time,3)*get_omega_nu_nopart(&(GravPM.CP->ONu), GravPM.Time));
440  ps->Norm *= MtotbyMcdm*MtotbyMcdm;
441  }
442  /* Remove zero mode corresponding to the mean.*/
443  value[0][0] = 0.0;
444  value[0][1] = 0.0;
445  return;
446  }
447 
448  value[0][0] *= fac;
449  value[0][1] *= fac;
450 }
static double pot_factor
Definition: glass.c:215
double get_omega_nu_nopart(const _omega_nu *const omnu, const double a)
double Omega0
Definition: cosmology.h:10
double G
Definition: petapm.h:71
double Asmth
Definition: petapm.h:69
double BoxSize_in_MPC
Definition: powerspectrum.h:17

References PetaPM::Asmth, PetaPM::BoxSize, _powerspectrum::BoxSize_in_MPC, gravpm_params::CP, _powerspectrum::delta_nu_ratio, NODE::f, PetaPM::G, get_omega_nu_nopart(), GravPM, _powerspectrum::logknu, Cosmology::MassiveNuLinRespOn, PetaPM::Nmesh, _powerspectrum::nonzero, _powerspectrum::Norm, _powerspectrum::nu_acc, _powerspectrum::nu_prefac, _powerspectrum::nu_spline, Cosmology::Omega0, Cosmology::ONu, pot_factor, powerspectrum_add_mode(), PetaPM::ps, sinc_unnormed(), and gravpm_params::Time.

Referenced by gravpm_force().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ powerspectrum_add_mode()

void powerspectrum_add_mode ( Power PowerSpectrum,
const int64_t  k2,
const int  kpos[3],
pfft_complex *const  value,
const double  invwindow,
double  Nmesh 
)

Definition at line 327 of file gravpm.c.

328 {
329  if(k2 == 0) {
330  /* Save zero mode corresponding to the mean as the normalisation factor.*/
331  PowerSpectrum->Norm = (value[0][0] * value[0][0] + value[0][1] * value[0][1]);
332  return;
333  }
334  /* Measure power spectrum: we don't want the zero mode.
335  * Some modes with k_z = 0 or N/2 have weight 1, the rest have weight 2.
336  * This is because of the symmetry of the real fft. */
337  if(k2 > 0) {
338  /*How many bins per unit (log) interval in k?*/
339  const double binsperunit=(PowerSpectrum->size-1)/log(sqrt(3) * Nmesh/2.0);
340  int kint=floor(binsperunit*log(k2)/2.);
341  int w;
342  const double keff = sqrt(kpos[0]*kpos[0]+kpos[1]*kpos[1]+kpos[2]*kpos[2]);
343  const double m = (value[0][0] * value[0][0] + value[0][1] * value[0][1]);
344  /*Make sure we do not overflow (although this should never happen)*/
345  if(kint >= PowerSpectrum->size)
346  return;
347  if(kpos[2] == 0 || kpos[2] == Nmesh/2) w = 1;
348  else w = 2;
349  /*Make sure we use thread-local memory to avoid racing.*/
350  const int index = kint + omp_get_thread_num() * PowerSpectrum->size;
351  /*Multiply P(k) by inverse window function*/
352  PowerSpectrum->Power[index] += w * m * invwindow * invwindow;
353  PowerSpectrum->Nmodes[index] += w;
354  PowerSpectrum->kk[index] += w * keff;
355  }
356 
357 }
int64_t * Nmodes
Definition: powerspectrum.h:11

References _powerspectrum::kk, _powerspectrum::Nmodes, _powerspectrum::Norm, _powerspectrum::Power, and _powerspectrum::size.

Referenced by measure_power_spectrum(), and potential_transfer().

Here is the caller graph for this function:

◆ readout_force_x()

static void readout_force_x ( PetaPM pm,
int  i,
double *  mesh,
double  weight 
)
static

Definition at line 498 of file gravpm.c.

498  {
499  P[i].GravPM[0] += weight * mesh[0];
500 }

References P.

◆ readout_force_y()

static void readout_force_y ( PetaPM pm,
int  i,
double *  mesh,
double  weight 
)
static

Definition at line 501 of file gravpm.c.

501  {
502  P[i].GravPM[1] += weight * mesh[0];
503 }

References P.

◆ readout_force_z()

static void readout_force_z ( PetaPM pm,
int  i,
double *  mesh,
double  weight 
)
static

Definition at line 504 of file gravpm.c.

504  {
505  P[i].GravPM[2] += weight * mesh[0];
506 }

References P.

◆ readout_potential()

static void readout_potential ( PetaPM pm,
int  i,
double *  mesh,
double  weight 
)
static

Definition at line 495 of file gravpm.c.

495  {
496  P[i].Potential += weight * mesh[0];
497 }

References P.

◆ sinc_unnormed()

static double sinc_unnormed ( double  x)
static

Definition at line 291 of file gravpm.c.

291  {
292  if(x < 1e-5 && x > -1e-5) {
293  double x2 = x * x;
294  return 1.0 - x2 / 6. + x2 * x2 / 120.;
295  } else {
296  return sin(x) / x;
297  }
298 }

Referenced by measure_power_spectrum(), and potential_transfer().

Here is the caller graph for this function:

Variable Documentation

◆ functions

PetaPMFunctions functions[]
static
Initial value:
=
{
{"Potential", NULL, readout_potential},
{NULL, NULL, NULL},
}
static void readout_potential(PetaPM *pm, int i, double *mesh, double weight)
Definition: gravpm.c:495
static void force_x_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: gravpm.c:486
static void readout_force_z(PetaPM *pm, int i, double *mesh, double weight)
Definition: gravpm.c:504
static void readout_force_x(PetaPM *pm, int i, double *mesh, double weight)
Definition: gravpm.c:498
static void force_z_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: gravpm.c:492
static void force_y_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: gravpm.c:489
static void readout_force_y(PetaPM *pm, int i, double *mesh, double weight)
Definition: gravpm.c:501

Definition at line 32 of file gravpm.c.

Referenced by displacement_fields(), gravpm_force(), petapm_force(), and petapm_force_c2r().

◆ GravPM

struct gravpm_params GravPM
static