GADGET-4
main.cc
Go to the documentation of this file.
1 /*******************************************************************************
2  * \copyright This file is part of the GADGET4 N-body/SPH code developed
3  * \copyright by Volker Springel. Copyright (C) 2014-2020 by Volker Springel
4  * \copyright (vspringel@mpa-garching.mpg.de) and all contributing authors.
5  *******************************************************************************/
6 
12 #include "gadgetconfig.h"
13 
14 #include <gsl/gsl_math.h>
15 #include <math.h>
16 #include <mpi.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <time.h>
21 
22 #include "../cooling_sfr/cooling.h"
23 #include "../data/allvars.h"
24 #include "../data/dtypes.h"
25 #include "../half/half.hpp"
26 #include "../io/io.h"
27 #include "../io/restart.h"
28 #include "../io/snap_io.h"
29 #include "../logs/logs.h"
30 #include "../main/main.h"
31 #include "../main/simulation.h"
32 #include "../mergertree/mergertree.h"
33 #include "../mpi_utils/shared_mem_handler.h"
34 #include "../ngenic/ngenic.h"
35 #include "../system/system.h"
36 #include "../time_integration/driftfac.h"
37 
38 /* create instances of global objects */
39 
42 ewald Ewald; /* get an instance of the Ewald correction tables */
44 memory Mem; /* our instance of the memory object */
46 
55 int main(int argc, char **argv)
56 {
57  /* find out how many core we have per CPU and which ones we can use */
58  pinning Pin;
59  Pin.detect_topology();
60  Pin.get_core_set();
61 
62  /* initialize MPI, this may already impose some pinning */
63  MPI_Init(&argc, &argv);
64 
65  MPI_Comm_rank(MPI_COMM_WORLD, &Shmem.World_ThisTask);
66  MPI_Comm_size(MPI_COMM_WORLD, &Shmem.World_NTask);
67 
68 #if NUMBER_OF_MPI_LISTENERS_PER_NODE > 1
69  MPI_Comm fullsharedmemnode;
70  MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, 0, MPI_INFO_NULL, &fullsharedmemnode);
71 
72  int fullsharedmemnode_ThisTask, fullsharedmemnode_NTask;
73  MPI_Comm_rank(fullsharedmemnode, &fullsharedmemnode_ThisTask);
74  MPI_Comm_size(fullsharedmemnode, &fullsharedmemnode_NTask);
75 
76  int bin;
77  subdivide_evenly_get_bin(fullsharedmemnode_NTask, NUMBER_OF_MPI_LISTENERS_PER_NODE, fullsharedmemnode_ThisTask, &bin);
78 
79  MPI_Comm_split(fullsharedmemnode, bin, fullsharedmemnode_ThisTask, &Shmem.SharedMemComm);
80 #else
81  MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, 0, MPI_INFO_NULL, &Shmem.SharedMemComm);
82 #endif
83 
84  MPI_Comm_rank(Shmem.SharedMemComm, &Shmem.Island_ThisTask);
85  MPI_Comm_size(Shmem.SharedMemComm, &Shmem.Island_NTask);
86 
87  int min_ntask, max_ntask;
88  MPI_Allreduce(&Shmem.Island_NTask, &max_ntask, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
89  MPI_Allreduce(&Shmem.Island_NTask, &min_ntask, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
90  MPI_Allreduce(&Shmem.World_ThisTask, &Shmem.Island_Smallest_WorldTask, 1, MPI_INT, MPI_MIN, Shmem.SharedMemComm);
91 
92  if(Shmem.World_ThisTask == 0)
93  printf("Shared memory islands host a minimum of %d and a maximum of %d MPI ranks.\n", min_ntask, max_ntask);
94 
95  Shmem.GhostRank = 0;
96 
97  if(max_ntask < Shmem.World_NTask)
98  {
99  if(Shmem.Island_ThisTask == Shmem.Island_NTask - 1) // selected the ghost MPI ranks
100  Shmem.GhostRank = 1;
101 
102  if(min_ntask > 1)
103  {
104  int comm_ranks;
105  MPI_Allreduce(&Shmem.GhostRank, &comm_ranks, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
106 
107  if(Shmem.World_ThisTask == 0)
108  printf("We shall use %d MPI ranks in total for assisting one-sided communication (%d per shared memory node).\n",
110  }
111  else
112  {
113  if(Shmem.World_ThisTask == 0)
114  Terminate("We have shared memory islands with just one MPI rank -- can't put aside this one just for communication");
115  }
116 
118  {
119  if(Shmem.World_ThisTask == 0)
120  Terminate(
121  "We have shared memory islands with %d MPI ranks, which is larger than MAX_NUMBER_OF_RANKS_WITH_SHARED_MEMORY=%d\n"
122  "You may consider increasing NUMBER_OF_MPI_LISTENERS_PER_NODE, current value is %d\n",
124  }
125  }
126 
127  /* we can now split the communicator into the processing ones, and the ones reserved for communication */
128  MPI_Comm_split(MPI_COMM_WORLD, Shmem.GhostRank, Shmem.World_ThisTask, &Shmem.SimulationComm);
129 
130  MPI_Comm_rank(Shmem.SimulationComm, &Shmem.Sim_ThisTask);
131  MPI_Comm_size(Shmem.SimulationComm, &Shmem.Sim_NTask);
132 
133  /* Let's now find out for everyone the global rank of the responsible shared memory ghost */
135 
136  MPI_Bcast(&Shmem.MyShmRankInGlobal, 1, MPI_INT, Shmem.Island_NTask - 1, Shmem.SharedMemComm);
137 
138  if(Shmem.GhostRank == 1)
139  {
141  Shmem.shared_memory_handler(); // note: this call will not return
142  }
143 
144  /* creating main simulation object, holding all the data and objects of our simulation */
145  sim Sim{Shmem.SimulationComm};
146 
147  Sim.determine_compute_nodes();
148 
149  /* initialize the communicator structures of our global objects */
150  Ewald.initcomm(Sim.Communicator); // a global class
151  Logs.initcomm(Sim.Communicator); // a global class
152  All.initcomm(Sim.Communicator); // a global class
153  Mem.initcomm(Sim.Communicator); // a global class
155 
156  /* output a welcome message */
157  Sim.hello();
158 
159  /* initialize CPU-time/Wallclock-time measurement */
160  Logs.init_cpu_log(&Sim.Sp);
161 
162  /* pin the MPI ranks to the available core set */
163  Pin.pin_to_core_set(&Sim);
164 
165 #ifdef HOST_MEMORY_REPORTING
166  Sim.mpi_report_comittable_memory();
167  Mem.MemoryOnNode = Sim.MemoryOnNode;
168  Mem.SharedMemoryOnNode = Sim.SharedMemoryOnNode;
169 #endif
170 
171  if(argc < 2)
172  {
173  if(Sim.ThisTask == 0)
174  {
175  printf("\nParameters are missing.\n");
176  printf("Start as ./Gadget4 <ParameterFile> [<RestartFlag>] [<SpecialOptions>]\n");
177  printf("\n");
178  printf(" RestartFlag Action\n");
179  printf(" %2d Read initial conditions and start simulation\n", RST_BEGIN);
180  printf(" %2d Read restart files and resume simulation\n", RST_RESUME);
181  printf(" %2d Restart from specified snapshot dump and resume simulation\n", RST_STARTFROMSNAP);
182  printf(" %2d Run FOF and optionally SUBFIND\n", RST_FOF);
183  printf(" %2d Calculate a matter power spectrum\n", RST_POWERSPEC);
184  printf(" %2d Convert snapshot file to different format [input=ICFormat output=SnapFormat\n", RST_CONVERTSNAP);
185  printf(" %2d Create cosmological initial conditions\n", RST_CREATEICS);
186  printf(" %2d Calculate descendants/progenitors [connecting group catalogues SnapNum-1 and SnapNum]\n",
187  RST_CALCDESC);
188  printf(" %2d Arrange halos in merger trees [using group catalogues up to SnapNum]\n", RST_MAKETREES);
189  printf(" %2d Carry out I/O bandwidth test to determine best setting for number of concurrent reads/writes\n",
191  printf(" %2d Rearrange particle-lightcone data in merger tree order <conenr> <firstnum> <lastnum>\n",
193  printf(" %2d Rearrange most-bound snapshot data in merger tree order <firstnum> <lastnum>\n",
195  printf("\n");
196  }
197  Sim.endrun();
198  }
199 
200  /* argv[1] holds the parameterfile */
201 
202  if(argc >= 3)
203  All.RestartFlag = (enum restart_options)atoi(argv[2]);
204  else
206 
207  int restartSnapNum = -1;
208  if(argc >= 4)
209  restartSnapNum = atoi(argv[3]);
210 
211  /* Do minimal validation of arguments here rather than in random places in the code */
214  restartSnapNum < 0)
215  {
216  Terminate("Need to give the snapshot number for the chosen option.\n");
217  }
218 
219  /* set-up run based on parameterfile */
220  Sim.begrun1(argv[1]);
221 
222  /* see if we are loading a restart file or an IC file */
223  if(All.RestartFlag == RST_RESUME)
224  {
225  restart Restart{Sim.Communicator};
226  Restart.load(&Sim);
227  }
228  else
229  {
230  /* We're reading an IC file. Is it a snapshot or really an IC? */
231  char fname[MAXLEN_PATH_EXTRA];
232 
233  if(All.RestartFlag != RST_BEGIN && All.RestartFlag != RST_RESUME && restartSnapNum >= 0)
234  {
235  if(All.NumFilesPerSnapshot > 1)
236  sprintf(fname, "%s/snapdir_%03d/%s_%03d", All.OutputDir, restartSnapNum, All.SnapshotFileBase, restartSnapNum);
237  else
238  sprintf(fname, "%s%s_%03d", All.OutputDir, All.SnapshotFileBase, restartSnapNum);
239  }
240  else
241  {
242  strcpy(fname, All.InitCondFile);
243  }
244 
246  {
248  }
249 
251  {
252 #ifdef MERGERTREE
253  Sim.MergerTree.descendants_in_postprocessing(restartSnapNum);
254  Sim.endrun();
255 #else
256  Terminate("Compile with option MERGERTREE for this option");
257 #endif
258  }
259 
261  {
262 #ifdef MERGERTREE
263  Sim.MergerTree.halotrees_construct(restartSnapNum);
264  Sim.endrun();
265 #else
266  Terminate("Compile with option MERGERTREE for this option");
267 #endif
268  }
269 
271  {
272  Sim.measure_io_bandwidth();
273  Sim.endrun();
274  }
275 
277  {
278 #if defined(LIGHTCONE) && defined(LIGHTCONE_PARTICLES) && defined(REARRANGE_OPTION)
279  Sim.rearrange_lightcone(argc, argv);
280 #else
281  Terminate("need to compile with REARRANGE_OPTION for this option to work\n");
282 #endif
283  Sim.endrun();
284  }
285 
287  {
288 #if defined(MERGERTREE) && defined(REARRANGE_OPTION)
289  Sim.rearrange_snapshot(argc, argv);
290 #else
291  Terminate("need to compile with REARRANGE_OPTION for this option to work\n");
292 #endif
293  Sim.endrun();
294  }
295 
296 #ifdef CREATE_GRID
298  Sim.Ngenic.create_grid();
299  else
300 #endif
301  {
302  snap_io Snap(&Sim.Sp, Sim.Communicator, All.ICFormat); /* get an I/O object */
303 
304  Snap.read_ic(fname);
305  }
306 
307  /* If we are supposed to just convert the file, write and exit here. */
309  {
310 #ifdef COOLING
311  Sim.CoolSfr.InitCool();
312 #endif
313  strcat(All.SnapshotFileBase, "_converted");
314  Sim.mpi_printf("Start writing file %s\nSnapNum %d\n", All.SnapshotFileBase, restartSnapNum);
315 
316  snap_io Snap(&Sim.Sp, Sim.Communicator, All.SnapFormat); /* get an I/O object */
317  Snap.write_snapshot(restartSnapNum, NORMAL_SNAPSHOT);
318 
319  Sim.endrun();
320  }
321 
322  Sim.init(restartSnapNum);
323  }
324 
325  Sim.begrun2();
326 
327  Sim.run(); /* main simulation loop */
328 
329  Sim.endrun(); /* clean up & finalize MPI */
330 
331  return 0;
332 }
Ewald correction functionality.
Definition: ewald.h:54
Definition: logs.h:28
void init_cpu_log(simparticles *Sp_ptr)
Definition: logs.cc:296
void get_core_set(void)
Definition: pinning.cc:25
void detect_topology(void)
Definition: pinning.cc:33
void pin_to_core_set(setcomm *sc)
Definition: pinning.cc:69
long long MemoryOnNode
Definition: setcomm.h:42
void determine_compute_nodes(void)
Definition: setcomm.h:98
MPI_Comm Communicator
Definition: setcomm.h:31
long long SharedMemoryOnNode
Definition: setcomm.h:43
void initcomm(MPI_Comm Comm)
Definition: setcomm.h:45
MPI_Comm SharedMemComm
void shared_memory_handler(void)
int Island_ThisTask
int Island_NTask
MPI_Comm SimulationComm
int Island_Smallest_WorldTask
int Sim_ThisTask
int MyShmRankInGlobal
int World_ThisTask
Definition: simulation.h:50
void read_ic(const char *fname)
This function reads initial conditions that are in on of the default file formats of Gadget.
Definition: snap_io.cc:289
void write_snapshot(int num, mysnaptype snap_type)
Save snapshot to disk.
Definition: snap_io.cc:559
#define MAXLEN_PATH_EXTRA
Definition: constants.h:301
#define NUMBER_OF_MPI_LISTENERS_PER_NODE
Definition: dtypes.h:126
@ NORMAL_SNAPSHOT
Definition: dtypes.h:306
#define MAX_NUMBER_OF_RANKS_WITH_SHARED_MEMORY
Definition: dtypes.h:130
restart_options
Definition: dtypes.h:312
@ RST_CONVERTSNAP
Definition: dtypes.h:318
@ RST_LCREARRANGE
Definition: dtypes.h:323
@ RST_STARTFROMSNAP
Definition: dtypes.h:315
@ RST_POWERSPEC
Definition: dtypes.h:317
@ RST_CREATEICS
Definition: dtypes.h:319
@ RST_MAKETREES
Definition: dtypes.h:321
@ RST_IOBANDWIDTH
Definition: dtypes.h:322
@ RST_FOF
Definition: dtypes.h:316
@ RST_SNPREARRANGE
Definition: dtypes.h:324
@ RST_BEGIN
Definition: dtypes.h:313
@ RST_RESUME
Definition: dtypes.h:314
@ RST_CALCDESC
Definition: dtypes.h:320
#define Terminate(...)
Definition: macros.h:19
logs Logs
Definition: main.cc:43
memory Mem
Definition: main.cc:44
int main(int argc, char **argv)
Definition: main.cc:55
global_data_all_processes All
Definition: main.cc:40
shmem Shmem
Definition: main.cc:45
ewald Ewald
Definition: main.cc:42
driftfac Driftfac
Definition: main.cc:41
enum restart_options RestartFlag
Definition: allvars.h:68
char OutputDir[MAXLEN_PATH]
Definition: allvars.h:272
char SnapshotFileBase[MAXLEN_PATH]
Definition: allvars.h:272
char InitCondFile[MAXLEN_PATH]
Definition: allvars.h:272
void subdivide_evenly_get_bin(int N, int pieces, int index, int *bin)
Definition: system.cc:70