MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
Classes | Macros | Typedefs | Enumerations | Functions
treewalk.h File Reference
#include <stdint.h>
#include "utils/paramset.h"
#include "forcetree.h"
Include dependency graph for treewalk.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  TreeWalkQueryBase
 
struct  TreeWalkResultBase
 
struct  TreeWalkNgbIterBase
 
struct  LocalTreeWalk
 
struct  TreeWalk
 

Macros

#define NODELISTLENGTH   8
 
#define TREEWALK_REDUCE(A, B)   (A) = (mode==TREEWALK_PRIMARY)?(B):((A) + (B))
 
#define MAXITER   400
 

Typedefs

typedef struct TreeWalk TreeWalk
 
typedef int(* TreeWalkVisitFunction) (TreeWalkQueryBase *input, TreeWalkResultBase *output, LocalTreeWalk *lv)
 
typedef void(* TreeWalkNgbIterFunction) (TreeWalkQueryBase *input, TreeWalkResultBase *output, TreeWalkNgbIterBase *iter, LocalTreeWalk *lv)
 
typedef int(* TreeWalkHasWorkFunction) (const int i, TreeWalk *tw)
 
typedef void(* TreeWalkProcessFunction) (const int i, TreeWalk *tw)
 
typedef void(* TreeWalkFillQueryFunction) (const int j, TreeWalkQueryBase *query, TreeWalk *tw)
 
typedef void(* TreeWalkReduceResultFunction) (const int j, TreeWalkResultBase *result, const enum TreeWalkReduceMode mode, TreeWalk *tw)
 

Enumerations

enum  NgbTreeFindSymmetric { NGB_TREEFIND_SYMMETRIC , NGB_TREEFIND_ASYMMETRIC }
 
enum  TreeWalkReduceMode { TREEWALK_PRIMARY , TREEWALK_GHOSTS }
 
enum  TreeWalkType { TREEWALK_ACTIVE = 0 , TREEWALK_ALL , TREEWALK_SPLIT }
 

Functions

void set_treewalk_params (ParameterSet *ps)
 
void treewalk_run (TreeWalk *tw, int *active_set, size_t size)
 
int treewalk_visit_ngbiter (TreeWalkQueryBase *I, TreeWalkResultBase *O, LocalTreeWalk *lv)
 
int treewalk_export_particle (LocalTreeWalk *lv, int no)
 
int treewalk_visit_nolist_ngbiter (TreeWalkQueryBase *I, TreeWalkResultBase *O, LocalTreeWalk *lv)
 
void treewalk_do_hsml_loop (TreeWalk *tw, int *queue, int64_t queuesize, int update_hsml)
 
double ngb_narrow_down (double *right, double *left, const double *radius, const double *numNgb, int maxcmpt, int desnumngb, int *closeidx, double BoxSize)
 
void treewalk_build_queue (TreeWalk *tw, int *active_set, const size_t size, int may_have_garbage)
 

Macro Definition Documentation

◆ MAXITER

#define MAXITER   400

Definition at line 201 of file treewalk.h.

◆ NODELISTLENGTH

#define NODELISTLENGTH   8

Definition at line 8 of file treewalk.h.

◆ TREEWALK_REDUCE

#define TREEWALK_REDUCE (   A,
 
)    (A) = (mode==TREEWALK_PRIMARY)?(B):((A) + (B))

Definition at line 189 of file treewalk.h.

Typedef Documentation

◆ TreeWalk

typedef struct TreeWalk TreeWalk

Definition at line 1 of file treewalk.h.

◆ TreeWalkFillQueryFunction

typedef void(* TreeWalkFillQueryFunction) (const int j, TreeWalkQueryBase *query, TreeWalk *tw)

Definition at line 75 of file treewalk.h.

◆ TreeWalkHasWorkFunction

typedef int(* TreeWalkHasWorkFunction) (const int i, TreeWalk *tw)

Definition at line 72 of file treewalk.h.

◆ TreeWalkNgbIterFunction

typedef void(* TreeWalkNgbIterFunction) (TreeWalkQueryBase *input, TreeWalkResultBase *output, TreeWalkNgbIterBase *iter, LocalTreeWalk *lv)

Definition at line 70 of file treewalk.h.

◆ TreeWalkProcessFunction

typedef void(* TreeWalkProcessFunction) (const int i, TreeWalk *tw)

Definition at line 73 of file treewalk.h.

◆ TreeWalkReduceResultFunction

typedef void(* TreeWalkReduceResultFunction) (const int j, TreeWalkResultBase *result, const enum TreeWalkReduceMode mode, TreeWalk *tw)

Definition at line 76 of file treewalk.h.

◆ TreeWalkVisitFunction

typedef int(* TreeWalkVisitFunction) (TreeWalkQueryBase *input, TreeWalkResultBase *output, LocalTreeWalk *lv)

Definition at line 68 of file treewalk.h.

Enumeration Type Documentation

◆ NgbTreeFindSymmetric

Enumerator
NGB_TREEFIND_SYMMETRIC 
NGB_TREEFIND_ASYMMETRIC 

Definition at line 10 of file treewalk.h.

10  {
13 };
@ NGB_TREEFIND_ASYMMETRIC
Definition: treewalk.h:12
@ NGB_TREEFIND_SYMMETRIC
Definition: treewalk.h:11

◆ TreeWalkReduceMode

Enumerator
TREEWALK_PRIMARY 
TREEWALK_GHOSTS 

Definition at line 15 of file treewalk.h.

15  {
18 };
@ TREEWALK_PRIMARY
Definition: treewalk.h:16
@ TREEWALK_GHOSTS
Definition: treewalk.h:17

◆ TreeWalkType

Enumerator
TREEWALK_ACTIVE 
TREEWALK_ALL 
TREEWALK_SPLIT 

Definition at line 78 of file treewalk.h.

78  {
79  TREEWALK_ACTIVE = 0,
82 };
@ TREEWALK_ACTIVE
Definition: treewalk.h:79
@ TREEWALK_SPLIT
Definition: treewalk.h:81
@ TREEWALK_ALL
Definition: treewalk.h:80

Function Documentation

◆ ngb_narrow_down()

double ngb_narrow_down ( double *  right,
double *  left,
const double *  radius,
const double *  numNgb,
int  maxcmpt,
int  desnumngb,
int *  closeidx,
double  BoxSize 
)

Definition at line 1366 of file treewalk.c.

1367 {
1368  int j;
1369  int close = 0;
1370  double ngbdist = fabs(numNgb[0] - desnumngb);
1371  for(j = 1; j < maxcmpt; j++){
1372  double newdist = fabs(numNgb[j] - desnumngb);
1373  if(newdist < ngbdist){
1374  ngbdist = newdist;
1375  close = j;
1376  }
1377  }
1378  if(closeidx)
1379  *closeidx = close;
1380 
1381  for(j = 0; j < maxcmpt; j++){
1382  if(numNgb[j] < desnumngb)
1383  *left = radius[j];
1384  if(numNgb[j] > desnumngb){
1385  *right = radius[j];
1386  break;
1387  }
1388  }
1389 
1390  double hsml = radius[close];
1391 
1392  if(*right > 0.99 * BoxSize){
1393  double dngbdv = 0;
1394  if(maxcmpt > 1 && (radius[maxcmpt-1]>radius[maxcmpt-2]))
1395  dngbdv = (numNgb[maxcmpt-1]-numNgb[maxcmpt-2])/(pow(radius[maxcmpt-1],3) - pow(radius[maxcmpt-2],3));
1396  /* Increase hsml by a maximum factor to avoid madness. We can be fairly aggressive about this factor.*/
1397  double newhsml = 4 * hsml;
1398  if(dngbdv > 0) {
1399  double dngb = (desnumngb - numNgb[maxcmpt-1]);
1400  double newvolume = pow(hsml,3) + dngb / dngbdv;
1401  if(pow(newvolume, 1./3) < newhsml)
1402  newhsml = pow(newvolume, 1./3);
1403  }
1404  hsml = newhsml;
1405  }
1406  if(hsml > *right)
1407  hsml = *right;
1408 
1409  if(*left == 0) {
1410  /* Extrapolate using volume, ie locally constant density*/
1411  double dngbdv = 0;
1412  if(radius[1] > radius[0])
1413  dngbdv = (numNgb[1] - numNgb[0]) / (pow(radius[1],3) - pow(radius[0],3));
1414  /* Derivative is not defined for minimum, so use 0.*/
1415  if(maxcmpt == 1 && radius[0] > 0)
1416  dngbdv = numNgb[0] / pow(radius[0],3);
1417 
1418  if(dngbdv > 0) {
1419  double dngb = desnumngb - numNgb[0];
1420  double newvolume = pow(hsml,3) + dngb / dngbdv;
1421  hsml = pow(newvolume, 1./3);
1422  }
1423  }
1424  if(hsml < *left)
1425  hsml = *left;
1426 
1427  return hsml;
1428 }

Referenced by sfr_wind_weight_postprocess(), and stellar_density_check_neighbours().

Here is the caller graph for this function:

◆ set_treewalk_params()

void set_treewalk_params ( ParameterSet ps)

Definition at line 55 of file treewalk.c.

56 {
57  int ThisTask;
58  MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask);
59  if(ThisTask == 0)
60  ImportBufferBoost = param_get_int(ps, "ImportBufferBoost");
61  MPI_Bcast(&ImportBufferBoost, 1, MPI_INT, 0, MPI_COMM_WORLD);
62 }
int param_get_int(ParameterSet *ps, const char *name)
Definition: paramset.c:368
int ThisTask
Definition: test_exchange.c:23
static int ImportBufferBoost
Definition: treewalk.c:36

References ImportBufferBoost, param_get_int(), and ThisTask.

Referenced by read_parameter_file().

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

◆ treewalk_build_queue()

void treewalk_build_queue ( TreeWalk tw,
int *  active_set,
const size_t  size,
int  may_have_garbage 
)

Definition at line 394 of file treewalk.c.

395 {
396  tw->NThread = omp_get_max_threads();
397 
398  if(!tw->haswork && !may_have_garbage)
399  {
400  tw->WorkSetSize = size;
401  tw->WorkSet = active_set;
403  return;
404  }
405 
406  /* Since we use a static schedule below we only need size / tw->NThread elements per thread.
407  * Add NThread so that each thread has a little extra space.*/
408  size_t tsize = size / tw->NThread + tw->NThread;
409  /*Watch out: tw->WorkSet may change a few lines later due to the realloc*/
410  tw->WorkSet = (int *) mymalloc("ActiveQueue", tsize * sizeof(int) * tw->NThread);
412  size_t i;
413  size_t nqueue = 0;
414 
415  /*We want a lockless algorithm which preserves the ordering of the particle list.*/
416  size_t *nqthr = ta_malloc("nqthr", size_t, tw->NThread);
417  int **thrqueue = ta_malloc("thrqueue", int *, tw->NThread);
418 
419  gadget_setup_thread_arrays(tw->WorkSet, thrqueue, nqthr, tsize, tw->NThread);
420 
421  /* We enforce schedule static to ensure that each thread executes on contiguous particles.
422  * Note static enforces the monotonic modifier but on OpenMP 5.0 nonmonotonic is the default.
423  * static also ensures that no single thread gets more than tsize elements.*/
424  size_t schedsz = size/tw->NThread+1;
425  #pragma omp parallel for schedule(static, schedsz)
426  for(i=0; i < size; i++)
427  {
428  const int tid = omp_get_thread_num();
429  /*Use raw particle number if active_set is null, otherwise use active_set*/
430  const int p_i = active_set ? active_set[i] : (int) i;
431 
432  /* Skip the garbage particles */
433  if(P[p_i].IsGarbage)
434  continue;
435 
436  if(tw->haswork && !tw->haswork(p_i, tw))
437  continue;
438 #ifdef DEBUG
439  if(nqthr[tid] >= tsize)
440  endrun(5, "tid = %d nqthr = %d, tsize = %d size = %d, tw->Nthread = %d i = %d\n", tid, nqthr[tid], tsize, size, tw->NThread, i);
441 #endif
442  thrqueue[tid][nqthr[tid]] = p_i;
443  nqthr[tid]++;
444  }
445  /*Merge step for the queue.*/
446  nqueue = gadget_compact_thread_arrays(tw->WorkSet, thrqueue, nqthr, tw->NThread);
447  ta_free(thrqueue);
448  ta_free(nqthr);
449  /*Shrink memory*/
450  tw->WorkSet = (int *) myrealloc(tw->WorkSet, sizeof(int) * nqueue);
451 
452 #if 0
453  /* check the uniqueness of the active_set list. This is very slow. */
454  qsort_openmp(tw->WorkSet, nqueue, sizeof(int), cmpint);
455  for(i = 0; i < nqueue - 1; i ++) {
456  if(tw->WorkSet[i] == tw->WorkSet[i+1]) {
457  endrun(8829, "A few particles are twicely active.\n");
458  }
459  }
460 #endif
461  tw->WorkSetSize = nqueue;
462 }
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
#define mymalloc(name, size)
Definition: mymalloc.h:15
#define ta_malloc(name, type, nele)
Definition: mymalloc.h:25
#define myrealloc(ptr, size)
Definition: mymalloc.h:18
#define ta_free(p)
Definition: mymalloc.h:28
#define P
Definition: partmanager.h:88
int64_t NThread
Definition: treewalk.h:107
TreeWalkHasWorkFunction haswork
Definition: treewalk.h:100
int64_t WorkSetSize
Definition: treewalk.h:163
int work_set_stolen_from_active
Definition: treewalk.h:165
int * WorkSet
Definition: treewalk.h:161
void gadget_setup_thread_arrays(int *dest, int *srcs[], size_t sizes[], size_t total_size, int narrays)
Definition: system.c:600
size_t gadget_compact_thread_arrays(int *dest, int *srcs[], size_t sizes[], int narrays)
Definition: system.c:587
#define qsort_openmp
Definition: test_exchange.c:14

References endrun(), gadget_compact_thread_arrays(), gadget_setup_thread_arrays(), TreeWalk::haswork, mymalloc, myrealloc, TreeWalk::NThread, P, qsort_openmp, ta_free, ta_malloc, TreeWalk::work_set_stolen_from_active, TreeWalk::WorkSet, and TreeWalk::WorkSetSize.

Referenced by blackhole(), ev_begin(), and treewalk_do_hsml_loop().

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

◆ treewalk_do_hsml_loop()

void treewalk_do_hsml_loop ( TreeWalk tw,
int *  queue,
int64_t  queuesize,
int  update_hsml 
)

Definition at line 1254 of file treewalk.c.

1255 {
1256  int64_t ntot = 0;
1257  int NumThreads = omp_get_max_threads();
1258  tw->NPLeft = ta_malloc("NPLeft", size_t, NumThreads);
1259  tw->NPRedo = ta_malloc("NPRedo", int *, NumThreads);
1260  tw->maxnumngb = ta_malloc("numngb", double, NumThreads);
1261  tw->minnumngb = ta_malloc("numngb2", double, NumThreads);
1262 
1263  /* Build the first queue */
1264  treewalk_build_queue(tw, queue, queuesize, 0);
1265  /* Next call to treewalk_run will over-write these pointers*/
1266  int64_t size = tw->WorkSetSize;
1267  int * ReDoQueue = tw->WorkSet;
1268  /* First queue is allocated low*/
1269  int alloc_high = 0;
1270  /* We don't need to redo the queue generation
1271  * but need to keep track of allocated memory.*/
1272  int orig_queue_alloc = (tw->haswork != NULL);
1273  tw->haswork = NULL;
1274 
1275  /* we will repeat the whole thing for those particles where we didn't find enough neighbours */
1276  do {
1277  /* The RedoQueue needs enough memory to store every workset particle on every thread, because
1278  * we cannot guarantee that the sph particles are evenly spread across threads!*/
1279  int * CurQueue = ReDoQueue;
1280  int i;
1281  for(i = 0; i < NumThreads; i++) {
1282  tw->maxnumngb[i] = 0;
1283  tw->minnumngb[i] = 1e50;
1284  }
1285 
1286  /* The ReDoQueue swaps between high and low allocations so we can have two allocated alternately*/
1287  if(update_hsml) {
1288  if(!alloc_high) {
1289  ReDoQueue = (int *) mymalloc2("ReDoQueue", size * sizeof(int) * NumThreads);
1290  alloc_high = 1;
1291  }
1292  else {
1293  ReDoQueue = (int *) mymalloc("ReDoQueue", size * sizeof(int) * NumThreads);
1294  alloc_high = 0;
1295  }
1296  tw->Redo_thread_alloc = size;
1297  gadget_setup_thread_arrays(ReDoQueue, tw->NPRedo, tw->NPLeft, size, NumThreads);
1298  }
1299  treewalk_run(tw, CurQueue, size);
1300 
1301  /* Now done with the current queue*/
1302  if(orig_queue_alloc || tw->Niteration > 1)
1303  myfree(CurQueue);
1304 
1305  /* We can stop if we are not updating hsml*/
1306  if(!update_hsml)
1307  break;
1308 
1309  /* Set up the next queue*/
1310  size = gadget_compact_thread_arrays(ReDoQueue, tw->NPRedo, tw->NPLeft, NumThreads);
1311 
1312  MPI_Allreduce(&size, &ntot, 1, MPI_INT64, MPI_SUM, MPI_COMM_WORLD);
1313  if(ntot == 0){
1314  myfree(ReDoQueue);
1315  break;
1316  }
1317  for(i = 1; i < NumThreads; i++) {
1318  if(tw->maxnumngb[0] < tw->maxnumngb[i])
1319  tw->maxnumngb[0] = tw->maxnumngb[i];
1320  if(tw->minnumngb[0] > tw->minnumngb[i])
1321  tw->minnumngb[0] = tw->minnumngb[i];
1322  }
1323  double minngb, maxngb;
1324  MPI_Reduce(&tw->maxnumngb[0], &maxngb, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
1325  MPI_Reduce(&tw->minnumngb[0], &minngb, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD);
1326  message(0, "Max ngb=%g, min ngb=%g\n", maxngb, minngb);
1327 
1328  /*Shrink memory*/
1329  ReDoQueue = (int *) myrealloc(ReDoQueue, sizeof(int) * size);
1330 
1331  /*
1332  if(ntot < 1 ) {
1333  foreach(ActiveParticle)
1334  {
1335  if(density_haswork(i)) {
1336  MyFloat Left = DENSITY_GET_PRIV(tw)->Left[i];
1337  MyFloat Right = DENSITY_GET_PRIV(tw)->Right[i];
1338  message (1, "i=%d task=%d ID=%llu type=%d, Hsml=%g Left=%g Right=%g Ngbs=%g Right-Left=%g\n pos=(%g|%g|%g)\n",
1339  i, ThisTask, P[i].ID, P[i].Type, P[i].Hsml, Left, Right,
1340  (float) P[i].NumNgb, Right - Left, P[i].Pos[0], P[i].Pos[1], P[i].Pos[2]);
1341  }
1342  }
1343 
1344  }
1345  */
1346 #ifdef DEBUG
1347  if(ntot == 1 && size > 0 && tw->Niteration > 20 ) {
1348  int pp = ReDoQueue[0];
1349  message(1, "Remaining i=%d, t %d, pos %g %g %g, hsml: %g\n", pp, P[pp].Type, P[pp].Pos[0], P[pp].Pos[1], P[pp].Pos[2], P[pp].Hsml);
1350  }
1351 #endif
1352 
1353  if(size > 0 && tw->Niteration > MAXITER) {
1354  endrun(1155, "failed to converge density for %ld particles\n", ntot);
1355  }
1356  } while(1);
1357  ta_free(tw->minnumngb);
1358  ta_free(tw->maxnumngb);
1359  ta_free(tw->NPRedo);
1360  ta_free(tw->NPLeft);
1361 }
#define MAXITER
Definition: cooling.c:46
void message(int where, const char *fmt,...)
Definition: endrun.c:175
#define mymalloc2(name, size)
Definition: mymalloc.h:16
#define myfree(x)
Definition: mymalloc.h:19
int64_t Niteration
Definition: treewalk.h:142
double * minnumngb
Definition: treewalk.h:172
double * maxnumngb
Definition: treewalk.h:171
int ** NPRedo
Definition: treewalk.h:168
size_t Redo_thread_alloc
Definition: treewalk.h:169
size_t * NPLeft
Definition: treewalk.h:167
#define MPI_INT64
Definition: system.h:12
void treewalk_run(TreeWalk *tw, int *active_set, size_t size)
Definition: treewalk.c:619
void treewalk_build_queue(TreeWalk *tw, int *active_set, const size_t size, int may_have_garbage)
Definition: treewalk.c:394

References endrun(), gadget_compact_thread_arrays(), gadget_setup_thread_arrays(), TreeWalk::haswork, MAXITER, TreeWalk::maxnumngb, message(), TreeWalk::minnumngb, MPI_INT64, myfree, mymalloc, mymalloc2, myrealloc, TreeWalk::Niteration, TreeWalk::NPLeft, TreeWalk::NPRedo, P, TreeWalk::Redo_thread_alloc, ta_free, ta_malloc, treewalk_build_queue(), treewalk_run(), TreeWalk::WorkSet, and TreeWalk::WorkSetSize.

Referenced by density(), stellar_density(), and winds_find_weights().

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

◆ treewalk_export_particle()

int treewalk_export_particle ( LocalTreeWalk lv,
int  no 
)

Definition at line 567 of file treewalk.c.

568 {
569  if(lv->mode != 0) {
570  endrun(1, "Trying to export a ghost particle.\n");
571  }
572  const int target = lv->target;
573  int *exportflag = lv->exportflag;
574  int *exportnodecount = lv->exportnodecount;
575  size_t *exportindex = lv->exportindex;
576  TreeWalk * tw = lv->tw;
577 
578  const int task = tw->tree->TopLeaves[no - tw->tree->lastnode].Task;
579 
580  if(exportflag[task] != target)
581  {
582  exportflag[task] = target;
583  exportnodecount[task] = NODELISTLENGTH;
584  }
585 
586  if(exportnodecount[task] == NODELISTLENGTH)
587  {
588  /* out of buffer space. Need to interrupt. */
589  if(lv->Nexport >= lv->BunchSize) {
590  return -1;
591  }
592  /* This index is a unique entry in the global DataNodeList and DataIndexTable.*/
593  size_t nexp = lv->Nexport + lv->DataIndexOffset;
594  exportnodecount[task] = 0;
595  exportindex[task] = nexp;
596  DataIndexTable[nexp].Task = task;
597  DataIndexTable[nexp].Index = target;
598  DataIndexTable[nexp].IndexGet = nexp;
599  lv->Nexport++;
600  lv->NThisParticleExport++;
601  }
602 
603  /* Set the NodeList entry*/
604  DataNodeList[exportindex[task]].NodeList[exportnodecount[task]++] =
605  tw->tree->TopLeaves[no - tw->tree->lastnode].treenode;
606 
607  if(exportnodecount[task] < NODELISTLENGTH)
608  DataNodeList[exportindex[task]].NodeList[exportnodecount[task]] = -1;
609  return 0;
610 }
struct topleaf_data * TopLeaves
Definition: forcetree.h:92
int lastnode
Definition: forcetree.h:86
size_t Nexport
Definition: treewalk.h:53
int * exportnodecount
Definition: treewalk.h:58
size_t NThisParticleExport
Definition: treewalk.h:56
size_t BunchSize
Definition: treewalk.h:54
int * exportflag
Definition: treewalk.h:57
size_t DataIndexOffset
Definition: treewalk.h:60
size_t * exportindex
Definition: treewalk.h:59
TreeWalk * tw
Definition: treewalk.h:47
const ForceTree * tree
Definition: treewalk.h:88
int Index
Definition: treewalk.c:50
int Task
Definition: treewalk.c:49
size_t IndexGet
Definition: treewalk.c:51
int NodeList[NODELISTLENGTH]
Definition: treewalk.c:40
int Task
Definition: domain.h:21
int treenode
Definition: domain.h:24
static struct data_nodelist * DataNodeList
static struct data_index * DataIndexTable
#define NODELISTLENGTH
Definition: treewalk.h:8

References LocalTreeWalk::BunchSize, LocalTreeWalk::DataIndexOffset, DataIndexTable, DataNodeList, endrun(), LocalTreeWalk::exportflag, LocalTreeWalk::exportindex, LocalTreeWalk::exportnodecount, data_index::Index, data_index::IndexGet, ForceTree::lastnode, LocalTreeWalk::mode, LocalTreeWalk::Nexport, data_nodelist::NodeList, NODELISTLENGTH, LocalTreeWalk::NThisParticleExport, LocalTreeWalk::target, topleaf_data::Task, data_index::Task, ForceTree::TopLeaves, TreeWalk::tree, topleaf_data::treenode, and LocalTreeWalk::tw.

Referenced by force_treeev_shortrange(), ngb_treefind_threads(), and treewalk_visit_nolist_ngbiter().

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

◆ treewalk_run()

void treewalk_run ( TreeWalk tw,
int *  active_set,
size_t  size 
)

Definition at line 619 of file treewalk.c.

620 {
621  if(!force_tree_allocated(tw->tree)) {
622  endrun(0, "Tree has been freed before this treewalk.\n");
623  }
624 
625  GDB_current_ev = tw;
626 
627  ev_begin(tw, active_set, size);
628 
629  if(tw->preprocess) {
630  int64_t i;
631  #pragma omp parallel for
632  for(i = 0; i < tw->WorkSetSize; i ++) {
633  const int p_i = tw->WorkSet ? tw->WorkSet[i] : i;
634  tw->preprocess(p_i, tw);
635  }
636  }
637 
638  if(tw->visit) {
639  tw->Nexportfull = 0;
640  tw->evaluated = NULL;
641  do
642  {
643  /* Keep track of which particles have been evaluated across buffer fill ups.
644  * Do this if we are not allowed to evaluate anything twice,
645  * or if the buffer filled up already.*/
646  if((!tw->evaluated) && (tw->Nexportfull == 1 || tw->repeatdisallowed)) {
647  tw->evaluated = (char *) mymalloc("evaluated", sizeof(char)*tw->WorkSetSize);
648  memset(tw->evaluated, 0, sizeof(char)*tw->WorkSetSize);
649  }
650  ev_primary(tw); /* do local particles and prepare export list */
651  /* exchange particle data */
652  const struct SendRecvBuffer sndrcv = ev_get_remote(tw);
653  /* now do the particles that were sent to us */
654  ev_secondary(tw);
655 
656  /* import the result to local particles */
657  ev_reduce_result(sndrcv, tw);
658 
659  tw->Nexportfull ++;
660  tw->Nexport_sum += tw->Nexport;
661  ta_free(sndrcv.Send_count);
662  } while(ev_ndone(tw) < tw->NTask);
663  if(tw->evaluated)
664  myfree(tw->evaluated);
665  }
666 
667 #ifdef DEBUG
668  /*int64_t totNodesinlist, totlist;
669  MPI_Reduce(&tw->Nnodesinlist, &totNodesinlist, 1, MPI_INT64, MPI_SUM, 0, MPI_COMM_WORLD);
670  MPI_Reduce(&tw->Nlist, &totlist, 1, MPI_INT64, MPI_SUM, 0, MPI_COMM_WORLD);
671  message(0, "Nodes in nodelist: %g (avg). %ld nodes, %ld lists\n", ((double) totNodesinlist)/totlist, totlist, totNodesinlist);*/
672 #endif
673  double tstart, tend;
674 
675  tstart = second();
676 
677  if(tw->postprocess) {
678  int64_t i;
679  #pragma omp parallel for
680  for(i = 0; i < tw->WorkSetSize; i ++) {
681  const int p_i = tw->WorkSet ? tw->WorkSet[i] : i;
682  tw->postprocess(p_i, tw);
683  }
684  }
685  tend = second();
686  tw->timecomp3 = timediff(tstart, tend);
687  ev_finish(tw);
688  tw->Niteration++;
689 }
int force_tree_allocated(const ForceTree *tree)
Definition: forcetree.c:134
int * Send_count
Definition: treewalk.c:23
TreeWalkProcessFunction preprocess
Definition: treewalk.h:105
double timecomp3
Definition: treewalk.h:125
char * evaluated
Definition: treewalk.h:118
int64_t Nexport_sum
Definition: treewalk.h:137
TreeWalkProcessFunction postprocess
Definition: treewalk.h:104
int NTask
Definition: treewalk.h:106
int64_t Nexportfull
Definition: treewalk.h:139
TreeWalkVisitFunction visit
Definition: treewalk.h:99
int repeatdisallowed
Definition: treewalk.h:117
size_t Nexport
Definition: treewalk.h:146
double timediff(double t0, double t1)
Definition: system.c:92
double second(void)
Definition: system.c:83
static void ev_begin(TreeWalk *tw, int *active_set, const size_t size)
Definition: treewalk.c:161
static void ev_finish(TreeWalk *tw)
Definition: treewalk.c:229
static void ev_reduce_result(const struct SendRecvBuffer sndrcv, TreeWalk *tw)
Definition: treewalk.c:810
static void ev_primary(TreeWalk *tw)
Definition: treewalk.c:466
static void ev_secondary(TreeWalk *tw)
Definition: treewalk.c:526
static TreeWalk * GDB_current_ev
Definition: treewalk.c:115
static struct SendRecvBuffer ev_get_remote(TreeWalk *tw)
Definition: treewalk.c:711
static int ev_ndone(TreeWalk *tw)
Definition: treewalk.c:513

References endrun(), ev_begin(), ev_finish(), ev_get_remote(), ev_ndone(), ev_primary(), ev_reduce_result(), ev_secondary(), TreeWalk::evaluated, force_tree_allocated(), GDB_current_ev, myfree, mymalloc, TreeWalk::Nexport, TreeWalk::Nexport_sum, TreeWalk::Nexportfull, TreeWalk::Niteration, TreeWalk::NTask, TreeWalk::postprocess, TreeWalk::preprocess, TreeWalk::repeatdisallowed, second(), SendRecvBuffer::Send_count, ta_free, TreeWalk::timecomp3, timediff(), TreeWalk::tree, TreeWalk::visit, TreeWalk::WorkSet, and TreeWalk::WorkSetSize.

Referenced by blackhole(), fof_label_primary(), fof_label_secondary(), grav_short_pair(), grav_short_tree(), hydro_force(), ionize_all_part(), metal_return(), treewalk_do_hsml_loop(), and winds_and_feedback().

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

◆ treewalk_visit_ngbiter()

int treewalk_visit_ngbiter ( TreeWalkQueryBase I,
TreeWalkResultBase O,
LocalTreeWalk lv 
)

Definition at line 924 of file treewalk.c.

927 {
928 
930 
931  /* Kick-start the iteration with other == -1 */
932  iter->other = -1;
933  lv->tw->ngbiter(I, O, iter, lv);
934 #ifdef DEBUG
935  /* Check whether the tree contains the particles we are looking for*/
936  if((lv->tw->tree->mask & iter->mask) == 0)
937  endrun(5, "Tried to run treewalk for particle mask %d but tree mask is %d.\n", iter->mask, lv->tw->tree->mask);
938 #endif
939  const double BoxSize = lv->tw->tree->BoxSize;
940 
941  int ninteractions = 0;
942  int inode = 0;
943 
944  for(inode = 0; (lv->mode == 0 && inode < 1)|| (lv->mode == 1 && inode < NODELISTLENGTH && I->NodeList[inode] >= 0); inode++)
945  {
946  int numcand = ngb_treefind_threads(I, O, iter, I->NodeList[inode], lv);
947  /* Export buffer is full end prematurally */
948  if(numcand < 0) return numcand;
949 
950  /* If we are here, export is succesful. Work on the this particle -- first
951  * filter out all of the candidates that are actually outside. */
952  int numngb;
953 
954  for(numngb = 0; numngb < numcand; numngb ++) {
955  int other = lv->ngblist[numngb];
956 
957  /* Skip garbage*/
958  if(P[other].IsGarbage)
959  continue;
960  /* In case the type of the particle has changed since the tree was built.
961  * Happens for wind treewalk for gas turned into stars on this timestep.*/
962  if(!((1<<P[other].Type) & iter->mask)) {
963  continue;
964  }
965 
966  double dist;
967 
968  if(iter->symmetric == NGB_TREEFIND_SYMMETRIC) {
969  dist = DMAX(P[other].Hsml, iter->Hsml);
970  } else {
971  dist = iter->Hsml;
972  }
973 
974  double r2 = 0;
975  int d;
976  double h2 = dist * dist;
977  for(d = 0; d < 3; d ++) {
978  /* the distance vector points to 'other' */
979  iter->dist[d] = NEAREST(I->Pos[d] - P[other].Pos[d], BoxSize);
980  r2 += iter->dist[d] * iter->dist[d];
981  if(r2 > h2) break;
982  }
983  if(r2 > h2) continue;
984 
985  /* update the iter and call the iteration function*/
986  iter->r2 = r2;
987  iter->r = sqrt(r2);
988  iter->other = other;
989 
990  lv->tw->ngbiter(I, O, iter, lv);
991  }
992 
993  ninteractions += numngb;
994  }
995 
996  lv->Ninteractions += ninteractions;
997  if(lv->mode == 1) {
998  lv->Nnodesinlist += inode;
999  lv->Nlist += 1;
1000  }
1001  return 0;
1002 }
#define NEAREST(x, BoxSize)
Definition: partmanager.h:99
double BoxSize
Definition: forcetree.h:106
int mask
Definition: forcetree.h:90
int64_t Nlist
Definition: treewalk.h:65
int * ngblist
Definition: treewalk.h:62
int64_t Ninteractions
Definition: treewalk.h:63
int64_t Nnodesinlist
Definition: treewalk.h:64
double dist[3]
Definition: treewalk.h:40
enum NgbTreeFindSymmetric symmetric
Definition: treewalk.h:37
double Pos[3]
Definition: treewalk.h:23
int NodeList[NODELISTLENGTH]
Definition: treewalk.h:27
size_t ngbiter_type_elsize
Definition: treewalk.h:97
TreeWalkNgbIterFunction ngbiter
Definition: treewalk.h:103
#define DMAX(x, y)
Definition: test_interp.c:11
static int ngb_treefind_threads(TreeWalkQueryBase *I, TreeWalkResultBase *O, TreeWalkNgbIterBase *iter, int startnode, LocalTreeWalk *lv)
Definition: treewalk.c:1052

References ForceTree::BoxSize, TreeWalkNgbIterBase::dist, DMAX, endrun(), TreeWalkNgbIterBase::Hsml, ForceTree::mask, TreeWalkNgbIterBase::mask, LocalTreeWalk::mode, NEAREST, NGB_TREEFIND_SYMMETRIC, ngb_treefind_threads(), TreeWalk::ngbiter, TreeWalk::ngbiter_type_elsize, LocalTreeWalk::ngblist, LocalTreeWalk::Ninteractions, LocalTreeWalk::Nlist, LocalTreeWalk::Nnodesinlist, TreeWalkQueryBase::NodeList, TreeWalkNgbIterBase::other, P, TreeWalkQueryBase::Pos, TreeWalkNgbIterBase::r, TreeWalkNgbIterBase::r2, TreeWalkNgbIterBase::symmetric, TreeWalk::tree, and LocalTreeWalk::tw.

Referenced by blackhole(), fof_label_primary(), grav_short_pair(), hydro_force(), ionize_all_part(), and metal_return().

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

◆ treewalk_visit_nolist_ngbiter()

int treewalk_visit_nolist_ngbiter ( TreeWalkQueryBase I,
TreeWalkResultBase O,
LocalTreeWalk lv 
)

Definition at line 1143 of file treewalk.c.

1146 {
1148 
1149  /* Kick-start the iteration with other == -1 */
1150  iter->other = -1;
1151  lv->tw->ngbiter(I, O, iter, lv);
1152 
1153  int inode;
1154  for(inode = 0; (lv->mode == 0 && inode < 1)|| (lv->mode == 1 && inode < NODELISTLENGTH && I->NodeList[inode] >= 0); inode++)
1155  {
1156  int no = I->NodeList[inode];
1157  const ForceTree * tree = lv->tw->tree;
1158  const double BoxSize = tree->BoxSize;
1159 
1160  while(no >= 0)
1161  {
1162  struct NODE *current = &tree->Nodes[no];
1163 
1164  /* When walking exported particles we start from the encompassing top-level node,
1165  * so if we get back to a top-level node again we are done.*/
1166  if(lv->mode == 1) {
1167  /* The first node is always top-level*/
1168  if(current->f.TopLevel && no != I->NodeList[inode]) {
1169  /* we reached a top-level node again, which means that we are done with the branch */
1170  break;
1171  }
1172  }
1173 
1174  /* Cull the node */
1175  if(0 == cull_node(I, iter, current, BoxSize)) {
1176  /* in case the node can be discarded */
1177  no = current->sibling;
1178  continue;
1179  }
1180 
1181  /* Node contains relevant particles, add them.*/
1182  if(current->f.ChildType == PARTICLE_NODE_TYPE) {
1183  int i;
1184  int * suns = current->s.suns;
1185  for (i = 0; i < current->s.noccupied; i++) {
1186  /* must be the correct type: compare the
1187  * current type for this subnode extracted
1188  * from the bitfield to the mask.*/
1189  int type = (current->s.Types >> (3*i)) % 8;
1190 
1191  if(!((1<<type) & iter->mask))
1192  continue;
1193 
1194  /* Now evaluate a particle for the list*/
1195  int other = suns[i];
1196  /* Skip garbage*/
1197  if(P[other].IsGarbage)
1198  continue;
1199  /* In case the type of the particle has changed since the tree was built.
1200  * Happens for wind treewalk for gas turned into stars on this timestep.*/
1201  if(!((1<<P[other].Type) & iter->mask))
1202  continue;
1203 
1204  double dist = iter->Hsml;
1205  double r2 = 0;
1206  int d;
1207  double h2 = dist * dist;
1208  for(d = 0; d < 3; d ++) {
1209  /* the distance vector points to 'other' */
1210  iter->dist[d] = NEAREST(I->Pos[d] - P[other].Pos[d], BoxSize);
1211  r2 += iter->dist[d] * iter->dist[d];
1212  if(r2 > h2) break;
1213  }
1214  if(r2 > h2) continue;
1215 
1216  /* update the iter and call the iteration function*/
1217  iter->r2 = r2;
1218  iter->other = other;
1219  iter->r = sqrt(r2);
1220  lv->tw->ngbiter(I, O, iter, lv);
1221  }
1222  /* Move sideways*/
1223  no = current->sibling;
1224  continue;
1225  }
1226  else if(current->f.ChildType == PSEUDO_NODE_TYPE) {
1227  /* pseudo particle */
1228  if(lv->mode == 1) {
1229  endrun(12312, "Secondary for particle %d from node %d found pseudo at %d.\n", lv->target, I->NodeList[inode], current);
1230  } else {
1231  /* Export the pseudo particle*/
1232  if(-1 == treewalk_export_particle(lv, current->s.suns[0]))
1233  return -1;
1234  /* Move sideways*/
1235  no = current->sibling;
1236  continue;
1237  }
1238  }
1239  /* ok, we need to open the node */
1240  no = current->s.suns[0];
1241  }
1242  }
1243 
1244  if(lv->mode == 1) {
1245  lv->Nnodesinlist += inode;
1246  lv->Nlist += 1;
1247  }
1248  return 0;
1249 }
#define PARTICLE_NODE_TYPE
Definition: forcetree.h:15
#define PSEUDO_NODE_TYPE
Definition: forcetree.h:17
struct NODE * Nodes
Definition: forcetree.h:97
Definition: forcetree.h:39
int sibling
Definition: forcetree.h:40
unsigned int ChildType
Definition: forcetree.h:49
unsigned int TopLevel
Definition: forcetree.h:47
struct NodeChild s
Definition: forcetree.h:66
struct NODE::@8 f
int noccupied
Definition: forcetree.h:35
int suns[NMAXCHILD]
Definition: forcetree.h:32
unsigned int Types
Definition: forcetree.h:30
static int cull_node(const TreeWalkQueryBase *const I, const TreeWalkNgbIterBase *const iter, const struct NODE *const current, const double BoxSize)
Definition: treewalk.c:1011
int treewalk_export_particle(LocalTreeWalk *lv, int no)
Definition: treewalk.c:567

References ForceTree::BoxSize, NODE::ChildType, cull_node(), TreeWalkNgbIterBase::dist, endrun(), NODE::f, TreeWalkNgbIterBase::Hsml, TreeWalkNgbIterBase::mask, LocalTreeWalk::mode, NEAREST, TreeWalk::ngbiter, TreeWalk::ngbiter_type_elsize, LocalTreeWalk::Nlist, LocalTreeWalk::Nnodesinlist, NodeChild::noccupied, TreeWalkQueryBase::NodeList, ForceTree::Nodes, TreeWalkNgbIterBase::other, P, PARTICLE_NODE_TYPE, TreeWalkQueryBase::Pos, PSEUDO_NODE_TYPE, TreeWalkNgbIterBase::r, TreeWalkNgbIterBase::r2, NODE::s, NODE::sibling, NodeChild::suns, LocalTreeWalk::target, NODE::TopLevel, TreeWalk::tree, treewalk_export_particle(), LocalTreeWalk::tw, and NodeChild::Types.

Referenced by density(), fof_label_secondary(), stellar_density(), and winds_find_weights().

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