MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
Typedefs | Functions
exchange.h File Reference
#include "partmanager.h"
#include "slotsmanager.h"
#include "drift.h"
Include dependency graph for exchange.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef int(* ExchangeLayoutFunc) (int p, const void *userdata)
 

Functions

int domain_exchange (ExchangeLayoutFunc, const void *layout_userdata, int do_gc, struct DriftData *drift, struct part_manager_type *pman, struct slots_manager_type *sman, int maxiter, MPI_Comm Comm)
 
void domain_test_id_uniqueness (struct part_manager_type *pman)
 

Typedef Documentation

◆ ExchangeLayoutFunc

typedef int(* ExchangeLayoutFunc) (int p, const void *userdata)

Definition at line 8 of file exchange.h.

Function Documentation

◆ domain_exchange()

int domain_exchange ( ExchangeLayoutFunc  layoutfunc,
const void *  layout_userdata,
int  do_gc,
struct DriftData drift,
struct part_manager_type pman,
struct slots_manager_type sman,
int  maxiter,
MPI_Comm  Comm 
)

Definition at line 103 of file exchange.c.

103  {
104  int failure = 0;
105 
106  /* register the MPI types used in communication if not yet. */
107  if (MPI_TYPE_PLAN_ENTRY == 0) {
108  MPI_Type_contiguous(sizeof(ExchangePlanEntry), MPI_BYTE, &MPI_TYPE_PLAN_ENTRY);
109  MPI_Type_commit(&MPI_TYPE_PLAN_ENTRY);
110  }
111 
112  /*Structure for building a list of particles that will be exchanged*/
114 
115  walltime_measure("/Domain/exchange/init");
116 
117  int iter = 0;
118 
119  do {
120  if(iter >= maxiter) {
121  failure = 1;
122  break;
123  }
124  domain_build_exchange_list(layoutfunc, layout_userdata, &plan, (iter > 0 ? NULL : drift), pman, sman, Comm);
125 
126  /*Exit early if nothing to do*/
127  if(!MPIU_Any(plan.nexchange > 0, Comm))
128  {
129  myfree(plan.ExchangeList);
130  walltime_measure("/Domain/exchange/togo");
131  break;
132  }
133 
134  /* determine for each rank how many particles have to be shifted to other ranks */
135  plan.last = domain_find_iter_space(&plan, pman, sman);
136  domain_build_plan(iter, layoutfunc, layout_userdata, &plan, pman, Comm);
137  walltime_measure("/Domain/exchange/togo");
138 
139 
140  /* Do a GC if we are asked to or if this isn't the last iteration.
141  * The gc decision is made collective in domain_exchange_once,
142  * and a gc will also be done if we have no space for particles.*/
143  int really_do_gc = do_gc || (plan.last < plan.nexchange);
144 
145  failure = domain_exchange_once(&plan, really_do_gc, pman, sman, Comm);
146 
147  myfree(plan.ExchangeList);
148 
149  if(failure)
150  break;
151  iter++;
152  }
153  while(MPIU_Any(plan.last < plan.nexchange, Comm));
154 #ifdef DEBUG
155  /* This does not apply for the FOF code, where the exchange list is pre-assigned
156  * and we only get one iteration. */
157  if(!failure && maxiter > 1) {
159  /* Do not drift again*/
160  domain_build_exchange_list(layoutfunc, layout_userdata, &plan9, NULL, pman, sman, Comm);
161  if(plan9.nexchange > 0)
162  endrun(5, "Still have %ld particles in exchange list\n", plan9.nexchange);
163  myfree(plan9.ExchangeList);
164  domain_free_exchangeplan(&plan9);
165  }
166 #endif
168 
169  return failure;
170 }
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
static void domain_build_plan(int iter, ExchangeLayoutFunc layoutfunc, const void *layout_userdata, ExchangePlan *plan, struct part_manager_type *pman, MPI_Comm Comm)
Definition: exchange.c:502
static ExchangePlan domain_init_exchangeplan(MPI_Comm Comm)
Definition: exchange.c:78
static int domain_exchange_once(ExchangePlan *plan, int do_gc, struct part_manager_type *pman, struct slots_manager_type *sman, MPI_Comm Comm)
Definition: exchange.c:191
static void domain_build_exchange_list(ExchangeLayoutFunc layoutfunc, const void *layout_userdata, ExchangePlan *plan, struct DriftData *drift, struct part_manager_type *pman, struct slots_manager_type *sman, MPI_Comm Comm)
Definition: exchange.c:386
static MPI_Datatype MPI_TYPE_PLAN_ENTRY
Definition: exchange.c:20
static void domain_free_exchangeplan(ExchangePlan *plan)
Definition: exchange.c:94
static size_t domain_find_iter_space(ExchangePlan *plan, const struct part_manager_type *pman, const struct slots_manager_type *sman)
Definition: exchange.c:443
#define myfree(x)
Definition: mymalloc.h:19
size_t nexchange
Definition: exchange.c:39
size_t last
Definition: exchange.c:44
int * ExchangeList
Definition: exchange.c:37
int MPIU_Any(int condition, MPI_Comm comm)
Definition: system.c:545
#define walltime_measure(name)
Definition: walltime.h:8

References domain_build_exchange_list(), domain_build_plan(), domain_exchange_once(), domain_find_iter_space(), domain_free_exchangeplan(), domain_init_exchangeplan(), endrun(), ExchangePlan::ExchangeList, ExchangePlan::last, MPI_TYPE_PLAN_ENTRY, MPIU_Any(), myfree, ExchangePlan::nexchange, and walltime_measure.

Referenced by domain_decompose_full(), domain_maintain(), fof_try_particle_exchange(), test_exchange(), test_exchange_uneven(), test_exchange_with_garbage(), and test_exchange_zero_slots().

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

◆ domain_test_id_uniqueness()

void domain_test_id_uniqueness ( struct part_manager_type pman)

Definition at line 570 of file exchange.c.

571 {
572  int64_t i;
573  MyIDType *ids;
574  int NTask, ThisTask;
575  MPI_Comm_size(MPI_COMM_WORLD, &NTask);
576  MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask);
577 
578  message(0, "Testing ID uniqueness...\n");
579 
580  ids = (MyIDType *) mymalloc("ids", pman->NumPart * sizeof(MyIDType));
581 
582  #pragma omp parallel for
583  for(i = 0; i < pman->NumPart; i++) {
584  ids[i] = pman->Base[i].ID;
585  if(pman->Base[i].IsGarbage)
586  ids[i] = (MyIDType) -1;
587  }
588 
589  mpsort_mpi(ids, pman->NumPart, sizeof(MyIDType), mp_order_by_id, 8, NULL, MPI_COMM_WORLD);
590 
591  /*Remove garbage from the end*/
592  int64_t nids = pman->NumPart;
593  while(nids > 0 && (ids[nids-1] == (MyIDType)-1)) {
594  nids--;
595  }
596 
597  #pragma omp parallel for
598  for(i = 1; i < nids; i++) {
599  if(ids[i] <= ids[i - 1])
600  {
601  endrun(12, "non-unique (or non-ordered) ID=%013ld found on task=%d (i=%d NumPart=%ld)\n",
602  ids[i], ThisTask, i, nids);
603  }
604  }
605 
606  MyIDType * prev = ta_malloc("prev", MyIDType, 1);
607  memset(prev, 0, sizeof(MyIDType));
608  const int TAG = 0xdead;
609 
610  if(NTask > 1) {
611  if(ThisTask == 0) {
612  MyIDType * ptr = prev;
613  if(nids > 0) {
614  ptr = ids;
615  }
616  MPI_Send(ptr, sizeof(MyIDType), MPI_BYTE, ThisTask + 1, TAG, MPI_COMM_WORLD);
617  }
618  else if(ThisTask == NTask - 1) {
619  MPI_Recv(prev, sizeof(MyIDType), MPI_BYTE,
620  ThisTask - 1, TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
621  }
622  else if(nids == 0) {
623  /* simply pass through whatever we get */
624  MPI_Recv(prev, sizeof(MyIDType), MPI_BYTE, ThisTask - 1, TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
625  MPI_Send(prev, sizeof(MyIDType), MPI_BYTE, ThisTask + 1, TAG, MPI_COMM_WORLD);
626  }
627  else
628  {
629  MPI_Sendrecv(
630  ids+(nids - 1), sizeof(MyIDType), MPI_BYTE,
631  ThisTask + 1, TAG,
632  prev, sizeof(MyIDType), MPI_BYTE,
633  ThisTask - 1, TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
634  }
635  }
636 
637  if(ThisTask > 1) {
638  if(nids > 0) {
639  if(ids[0] <= *prev && ids[0])
640  endrun(13, "non-unique ID=%ld found on task=%d\n", ids[0], ThisTask);
641  }
642  }
643 
644  myfree(prev);
645  myfree(ids);
646 }
void message(int where, const char *fmt,...)
Definition: endrun.c:175
static void mp_order_by_id(const void *data, void *radix, void *arg)
Definition: exchange.c:565
#define mpsort_mpi(base, nmemb, elsize, radix, rsize, arg, comm)
Definition: mpsort.h:26
#define mymalloc(name, size)
Definition: mymalloc.h:15
#define ta_malloc(name, type, nele)
Definition: mymalloc.h:25
struct particle_data * Base
Definition: partmanager.h:74
MyIDType ID
Definition: partmanager.h:38
unsigned int IsGarbage
Definition: partmanager.h:19
int ThisTask
Definition: test_exchange.c:23
int NTask
Definition: test_exchange.c:23
uint64_t MyIDType
Definition: types.h:10

References part_manager_type::Base, endrun(), particle_data::ID, particle_data::IsGarbage, message(), mp_order_by_id(), mpsort_mpi, myfree, mymalloc, NTask, part_manager_type::NumPart, ta_malloc, and ThisTask.

Referenced by domain_decompose_full(), domain_exchange_once(), init(), test_exchange(), test_exchange_uneven(), test_exchange_with_garbage(), and test_exchange_zero_slots().

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