velociraptor_interface.c 18.5 KB
Newer Older
1
2
/*******************************************************************************
 * This file is part of SWIFT.
3
 * Copyright (c) 2018 James Willis (james.s.willis@durham.ac.uk)
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/

/* Config parameters. */
#include "../config.h"

23
/* Some standard headers. */
24
25
#include <unistd.h>

26
27
28
/* This object's header. */
#include "velociraptor_interface.h"

29
/* Local includes. */
30
#include "cooling.h"
31
#include "engine.h"
James Willis's avatar
James Willis committed
32
#include "hydro.h"
33
#include "swift_velociraptor_part.h"
34
#include "velociraptor_struct.h"
35
36
37

#ifdef HAVE_VELOCIRAPTOR

38
39
40
/**
 * @brief Structure for passing cosmological information to VELOCIraptor.
 */
41
42
43
44
45
46
47
48
49
50
51
struct cosmoinfo {

  /*! Current expansion factor of the Universe. (cosmology.a) */
  double atime;

  /*! Reduced Hubble constant (H0 / (100km/s/Mpc) (cosmology.h) */
  double littleh;

  /*! Matter density parameter (cosmology.Omega_m) */
  double Omega_m;

52
53
54
55
56
57
58
59
60
  /*! Radiation density parameter (cosmology.Omega_r) */
  double Omega_r;

  /*! Neutrino density parameter (0 in SWIFT) */
  double Omega_nu;

  /*! Neutrino density parameter (cosmology.Omega_k) */
  double Omega_k;

61
62
63
64
65
66
67
68
69
70
71
72
73
  /*! Baryon density parameter (cosmology.Omega_b) */
  double Omega_b;

  /*! Radiation constant density parameter (cosmology.Omega_lambda) */
  double Omega_Lambda;

  /*! Dark matter density parameter (cosmology.Omega_m - cosmology.Omega_b) */
  double Omega_cdm;

  /*! Dark-energy equation of state at the current time (cosmology.w)*/
  double w_de;
};

74
75
76
/**
 * @brief Structure for passing unit information to VELOCIraptor.
 */
77
78
struct unitinfo {

79
  /*! Length conversion factor to kpc. */
80
81
  double lengthtokpc;

82
  /*! Velocity conversion factor to km/s. */
83
84
  double velocitytokms;

85
  /*! Mass conversion factor to solar masses. */
86
87
  double masstosolarmass;

88
  /*! Potential conversion factor to (km/s)^2. */
89
90
91
92
93
94
95
96
97
  double energyperunitmass;

  /*! Newton's gravitationl constant (phys_const.const_newton_G)*/
  double gravity;

  /*! Hubble constant at the current redshift (cosmology.H) */
  double hubbleunit;
};

98
99
100
/**
 * @brief Structure to hold the location of a top-level cell.
 */
101
102
struct cell_loc {

103
  /*! Coordinates x,y,z */
104
105
106
  double loc[3];
};

107
108
109
110
/**
 * @brief Structure for passing simulation information to VELOCIraptor for a
 * given call.
 */
111
112
struct siminfo {

113
114
115
116
117
118
119
120
121
122
123
124
125
  /*! Size of periodic replications */
  double period;

  /*! Mass of the high-resolution DM particles in a zoom-in run. */
  double zoomhigresolutionmass;

  /*! Mean inter-particle separation of the DM particles */
  double interparticlespacing;

  /*! Spacial extent of the simulation volume */
  double spacedimension[3];

  /*! Number of top-level cells. */
126
127
128
129
130
131
132
133
134
135
136
  int numcells;

  /*! Locations of top-level cells. */
  struct cell_loc *cell_loc;

  /*! Top-level cell width. */
  double cellwidth[3];

  /*! Inverse of the top-level cell width. */
  double icellwidth[3];

137
138
139
  /*! Holds the node ID of each top-level cell. */
  int *cellnodeids;

140
  /*! Is this a cosmological simulation? */
141
  int icosmologicalsim;
142
143

  /*! Is this a zoom-in simulation? */
144
  int izoomsim;
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

  /*! Do we have DM particles? */
  int idarkmatter;

  /*! Do we have gas particles? */
  int igas;

  /*! Do we have star particles? */
  int istar;

  /*! Do we have BH particles? */
  int ibh;

  /*! Do we have other particles? */
  int iother;
160
161
};

162
163
164
/**
 * @brief Structure for group information back to swift
 */
165
struct groupinfo {
166
167

  /*! Index of a #gpart in the global array on this MPI rank */
168
  int index;
169
170

  /*! Group number of the #gpart. */
171
  long long groupID;
172
173
};

pelahi's avatar
pelahi committed
174
175
176
int InitVelociraptor(char *config_name, struct unitinfo unit_info,
                     struct siminfo sim_info, const int numthreads);

177
struct groupinfo *InvokeVelociraptor(
178
179
    const int snapnum, char *output_name, struct cosmoinfo cosmo_info,
    struct siminfo sim_info, const size_t num_gravity_parts,
180
181
182
183
    const size_t num_hydro_parts, const size_t num_star_parts,
    struct swift_vel_part *swift_parts, const int *cell_node_ids,
    const int numthreads, const int return_group_flags,
    int *const num_in_groups);
184
185

#endif /* HAVE_VELOCIRAPTOR */
186

187
/**
188
189
 * @brief Initialise VELOCIraptor with configuration, units,
 * simulation info needed to run.
190
191
192
 *
 * @param e The #engine.
 */
193
void velociraptor_init(struct engine *e) {
194

195
#ifdef HAVE_VELOCIRAPTOR
196
197
  const ticks tic = getticks();

198
  /* Internal SWIFT units */
199
200
  const struct unit_system *swift_us = e->internal_units;

201
  /* CGS units and physical constants in CGS */
202
203
204
205
206
  struct unit_system cgs_us;
  units_init_cgs(&cgs_us);
  struct phys_const cgs_pc;
  phys_const_init(&cgs_us, /*params=*/NULL, &cgs_pc);

Matthieu Schaller's avatar
Matthieu Schaller committed
207
  /* Set unit conversions. */
208
  struct unitinfo unit_info;
209
210
211
212
213
214
215
216
217
218
219
  unit_info.lengthtokpc =
      units_cgs_conversion_factor(swift_us, UNIT_CONV_LENGTH) /
      (1000. * cgs_pc.const_parsec);
  unit_info.velocitytokms =
      units_cgs_conversion_factor(swift_us, UNIT_CONV_VELOCITY) / 1.0e5;
  unit_info.masstosolarmass =
      units_cgs_conversion_factor(swift_us, UNIT_CONV_MASS) /
      cgs_pc.const_solar_mass;
  unit_info.energyperunitmass =
      units_cgs_conversion_factor(swift_us, UNIT_CONV_ENERGY_PER_UNIT_MASS) /
      (1.0e10);
Matthieu Schaller's avatar
Matthieu Schaller committed
220
  unit_info.gravity = e->physical_constants->const_newton_G;
James Willis's avatar
James Willis committed
221
  unit_info.hubbleunit = e->cosmology->H0 / e->cosmology->h;
Matthieu Schaller's avatar
Matthieu Schaller committed
222

223
224
  /* Gather some information about the simulation */
  struct siminfo sim_info;
Matthieu Schaller's avatar
Matthieu Schaller committed
225

226
227
  /* Are we running with cosmology? */
  if (e->policy & engine_policy_cosmology) {
Matthieu Schaller's avatar
Matthieu Schaller committed
228
    sim_info.icosmologicalsim = 1;
229
  } else {
Matthieu Schaller's avatar
Matthieu Schaller committed
230
    sim_info.icosmologicalsim = 0;
231
  }
232
  sim_info.izoomsim = 0;
233
234
235
236
237

  /* Tell VELOCIraptor what we have in the simulation */
  sim_info.idarkmatter = (e->total_nr_gparts - e->total_nr_parts > 0);
  sim_info.igas = (e->policy & engine_policy_hydro);
  sim_info.istar = (e->policy & engine_policy_stars);
238
  sim_info.ibh = 0;  // sim_info.ibh = (e->policy&engine_policy_bh);
239
  sim_info.iother = 0;
240
241
242
243
244
245
246
247
248

  /* Be nice, talk! */
  if (e->verbose) {
    message("VELOCIraptor conf: Length conversion factor: %e",
            unit_info.lengthtokpc);
    message("VELOCIraptor conf: Velocity conversion factor: %e",
            unit_info.velocitytokms);
    message("VELOCIraptor conf: Mass conversion factor: %e",
            unit_info.masstosolarmass);
249
    message("VELOCIraptor conf: Internal energy conversion factor: %e",
250
251
252
253
254
255
256
            unit_info.energyperunitmass);
    message("VELOCIraptor conf: G: %e", unit_info.gravity);
    message("VELOCIraptor conf: H0/h: %e", unit_info.hubbleunit);
    message("VELOCIraptor conf: Config file name: %s", e->stf_config_file_name);
    message("VELOCIraptor conf: Cosmological Simulation: %d",
            sim_info.icosmologicalsim);
  }
Matthieu Schaller's avatar
Matthieu Schaller committed
257
258

  /* Initialise VELOCIraptor. */
259
260
  if (InitVelociraptor(e->stf_config_file_name, unit_info, sim_info,
                       e->nr_threads) != 1)
261
    error("VELOCIraptor initialisation failed.");
262
263
264
265

  if (e->verbose)
    message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
            clocks_getunit());
266
267
#else
  error("SWIFT not configure to run with VELOCIraptor.");
268
#endif /* HAVE_VELOCIRAPTOR */
269
270
271
272
273
274
}

/**
 * @brief Run VELOCIraptor with current particle data.
 *
 * @param e The #engine.
275
 * @param linked_with_snap Are we running at the same time as a snapshot dump?
276
 */
277
void velociraptor_invoke(struct engine *e, const int linked_with_snap) {
278

279
#ifdef HAVE_VELOCIRAPTOR
280

281
282
283
284
285
286
287
  const struct cosmology *cosmo = e->cosmology;
  const struct hydro_props *hydro_props = e->hydro_properties;
  const struct unit_system *us = e->internal_units;
  const struct phys_const *phys_const = e->physical_constants;
  const struct cooling_function_data *cool_func = e->cooling_func;

  /* Handle on the particles */
288
289
  const struct space *s = e->s;
  const struct part *parts = s->parts;
290
291
  const struct xpart *xparts = s->xparts;
  const struct gpart *gparts = s->gparts;
292
  const struct spart *sparts = s->sparts;
Matthieu Schaller's avatar
Matthieu Schaller committed
293
  const size_t nr_gparts = s->nr_gparts;
294
295
  const size_t nr_parts = s->nr_parts;
  const size_t nr_sparts = s->nr_sparts;
Matthieu Schaller's avatar
Matthieu Schaller committed
296
  const int nr_cells = s->nr_cells;
297
  const struct cell *cells_top = s->cells_top;
298

Matthieu Schaller's avatar
Matthieu Schaller committed
299
  /* Allow thread to run on any core for the duration of the call to
300
301
   * VELOCIraptor so that  when OpenMP threads are spawned
   * they can run on any core on the processor. */
Matthieu Schaller's avatar
Matthieu Schaller committed
302
303
304
305
  const int nr_cores = sysconf(_SC_NPROCESSORS_ONLN);
  pthread_t thread = pthread_self();

  /* Set affinity mask to include all cores on the CPU for VELOCIraptor. */
306
  cpu_set_t cpuset;
Matthieu Schaller's avatar
Matthieu Schaller committed
307
308
309
310
  CPU_ZERO(&cpuset);
  for (int j = 0; j < nr_cores; j++) CPU_SET(j, &cpuset);
  pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);

311
312
  /* Set cosmology information for this point in time */
  struct cosmoinfo cosmo_info;
313
314
315
316
  cosmo_info.atime = e->cosmology->a;
  cosmo_info.littleh = e->cosmology->h;
  cosmo_info.Omega_m = e->cosmology->Omega_m;
  cosmo_info.Omega_b = e->cosmology->Omega_b;
317
318
319
  cosmo_info.Omega_r = e->cosmology->Omega_r;
  cosmo_info.Omega_k = e->cosmology->Omega_k;
  cosmo_info.Omega_nu = 0.;
320
321
322
323
  cosmo_info.Omega_Lambda = e->cosmology->Omega_lambda;
  cosmo_info.Omega_cdm = e->cosmology->Omega_m - e->cosmology->Omega_b;
  cosmo_info.w_de = e->cosmology->w;

324
325
326
327
328
329
330
331
332
333
334
335
336
  /* Report the cosmo info we use */
  if (e->verbose) {
    message("VELOCIraptor conf: Scale factor: %e", cosmo_info.atime);
    message("VELOCIraptor conf: Little h: %e", cosmo_info.littleh);
    message("VELOCIraptor conf: Omega_m: %e", cosmo_info.Omega_m);
    message("VELOCIraptor conf: Omega_b: %e", cosmo_info.Omega_b);
    message("VELOCIraptor conf: Omega_Lambda: %e", cosmo_info.Omega_Lambda);
    message("VELOCIraptor conf: Omega_cdm: %e", cosmo_info.Omega_cdm);
    message("VELOCIraptor conf: w_de: %e", cosmo_info.w_de);
  }

  /* Update the simulation information */
  struct siminfo sim_info;
337

338
  /* Period of the box (Note we assume a cubic box!) */
339
  if (e->s->periodic) {
340
    sim_info.period = s->dim[0];
341
  } else {
342
343
    sim_info.period = 0.0;
  }
344
345

  /* Tell VELOCIraptor this is not a zoom-in simulation */
346
347
  sim_info.zoomhigresolutionmass = -1.0;

348
  /* Are we running with cosmology? */
349
350
  if (e->policy & engine_policy_cosmology) {
    sim_info.icosmologicalsim = 1;
351
    sim_info.izoomsim = 0;
352
353
    const size_t total_nr_baryons = e->total_nr_parts + e->total_nr_sparts;
    const size_t total_nr_dmparts = e->total_nr_gparts - total_nr_baryons;
354
355
    sim_info.interparticlespacing = sim_info.period / cbrt(total_nr_dmparts);
  } else {
356
    sim_info.icosmologicalsim = 0;
357
    sim_info.izoomsim = 0;
358
359
360
    sim_info.interparticlespacing = -1;
  }

361
  /* Set the spatial extent of the simulation volume */
362
363
364
  sim_info.spacedimension[0] = s->dim[0];
  sim_info.spacedimension[1] = s->dim[1];
  sim_info.spacedimension[2] = s->dim[2];
365

366
  /* Store number of top-level cells */
367
  sim_info.numcells = s->nr_cells;
368
369

  /* Size and inverse size of the top-level cells in VELOCIraptor units */
370
371
372
373
374
375
  sim_info.cellwidth[0] = s->cells_top[0].width[0];
  sim_info.cellwidth[1] = s->cells_top[0].width[1];
  sim_info.cellwidth[2] = s->cells_top[0].width[2];
  sim_info.icellwidth[0] = s->iwidth[0];
  sim_info.icellwidth[1] = s->iwidth[1];
  sim_info.icellwidth[2] = s->iwidth[2];
376

377
378
  ticks tic = getticks();

379
380
381
  /* Allocate and populate array of cell node IDs and positions. */
  int *cell_node_ids = NULL;
  if (posix_memalign((void **)&sim_info.cell_loc, SWIFT_STRUCT_ALIGNMENT,
382
383
                     s->nr_cells * sizeof(struct cell_loc)) != 0)
    error("Failed to allocate top-level cell locations for VELOCIraptor.");
384
385
386
387
  if (posix_memalign((void **)&cell_node_ids, SWIFT_STRUCT_ALIGNMENT,
                     nr_cells * sizeof(int)) != 0)
    error("Failed to allocate list of cells node IDs for VELOCIraptor.");

388
  for (int i = 0; i < s->nr_cells; i++) {
389
390
391
392
393
    cell_node_ids[i] = cells_top[i].nodeID;

    sim_info.cell_loc[i].loc[0] = cells_top[i].loc[0];
    sim_info.cell_loc[i].loc[1] = cells_top[i].loc[1];
    sim_info.cell_loc[i].loc[2] = cells_top[i].loc[2];
394
  }
395

396
397
398
399
400
401
402
403
404
405
406
407
408
  if (e->verbose) {
    message("VELOCIraptor conf: Space dimensions: (%e,%e,%e)",
            sim_info.spacedimension[0], sim_info.spacedimension[1],
            sim_info.spacedimension[2]);
    message("VELOCIraptor conf: No. of top-level cells: %d", sim_info.numcells);
    message(
        "VELOCIraptor conf: Top-level cell locations range: (%e,%e,%e) -> "
        "(%e,%e,%e)",
        sim_info.cell_loc[0].loc[0], sim_info.cell_loc[0].loc[1],
        sim_info.cell_loc[0].loc[2],
        sim_info.cell_loc[sim_info.numcells - 1].loc[0],
        sim_info.cell_loc[sim_info.numcells - 1].loc[1],
        sim_info.cell_loc[sim_info.numcells - 1].loc[2]);
409
410
  }

411
412
413
414
415
  /* Report timing */
  if (e->verbose)
    message("VR Collecting top-level cell info took %.3f %s.",
            clocks_from_ticks(getticks() - tic), clocks_getunit());

416
  /* Mention the number of particles being sent */
417
  if (e->verbose)
418
419
420
    message(
        "VELOCIraptor conf: MPI rank %d sending %zu gparts to VELOCIraptor.",
        engine_rank, nr_gparts);
Matthieu Schaller's avatar
Matthieu Schaller committed
421

422
  /* Append base name with the current output number */
Matthieu Schaller's avatar
Matthieu Schaller committed
423
  char outputFileName[PARSER_MAX_LINE_SIZE + 128];
424

425
426
427
428
429
430
431
432
  /* What should the filename be? */
  if (linked_with_snap) {
    snprintf(outputFileName, PARSER_MAX_LINE_SIZE + 128,
             "stf_%s_%04i.VELOCIraptor", e->snapshot_base_name,
             e->snapshot_output_count);
  } else {
    snprintf(outputFileName, PARSER_MAX_LINE_SIZE + 128, "%s_%04i.VELOCIraptor",
             e->stf_base_name, e->stf_output_count);
433
434
435
436
437
438
439
  }

  /* What is the snapshot number? */
  int snapnum;
  if (linked_with_snap) {
    snapnum = e->snapshot_output_count;
  } else {
440
    snapnum = e->stf_output_count;
441
  }
Matthieu Schaller's avatar
Matthieu Schaller committed
442

443
444
  tic = getticks();

Matthieu Schaller's avatar
Matthieu Schaller committed
445
446
447
448
449
450
451
  /* Allocate and populate an array of swift_vel_parts to be passed to
   * VELOCIraptor. */
  struct swift_vel_part *swift_parts = NULL;
  if (posix_memalign((void **)&swift_parts, part_align,
                     nr_gparts * sizeof(struct swift_vel_part)) != 0)
    error("Failed to allocate array of particles for VELOCIraptor.");

452
  const float a_inv = e->cosmology->a_inv;
Matthieu Schaller's avatar
Matthieu Schaller committed
453

454
455
456
457
458
459
460
461
  /* Convert particle properties into VELOCIraptor units.
   * VELOCIraptor wants:
   * - Co-moving positions,
   * - Peculiar velocities,
   * - Co-moving potential,
   * - Physical internal energy (for the gas),
   * - Temperatures (for the gas).
   */
Matthieu Schaller's avatar
Matthieu Schaller committed
462
  for (size_t i = 0; i < nr_gparts; i++) {
463

Matthieu Schaller's avatar
Matthieu Schaller committed
464
465
466
    swift_parts[i].x[0] = gparts[i].x[0];
    swift_parts[i].x[1] = gparts[i].x[1];
    swift_parts[i].x[2] = gparts[i].x[2];
467
468
469
470
471

    swift_parts[i].v[0] = gparts[i].v_full[0] * a_inv;
    swift_parts[i].v[1] = gparts[i].v_full[1] * a_inv;
    swift_parts[i].v[2] = gparts[i].v_full[2] * a_inv;

Matthieu Schaller's avatar
Matthieu Schaller committed
472
    swift_parts[i].mass = gravity_get_mass(&gparts[i]);
James Willis's avatar
James Willis committed
473
    swift_parts[i].potential = gravity_get_comoving_potential(&gparts[i]);
474

Matthieu Schaller's avatar
Matthieu Schaller committed
475
476
    swift_parts[i].type = gparts[i].type;

477
478
    swift_parts[i].index = i;
#ifdef WITH_MPI
479
    swift_parts[i].task = e->nodeID;
480
481
482
483
#else
    swift_parts[i].task = 0;
#endif

Matthieu Schaller's avatar
Matthieu Schaller committed
484
485
    /* Set gas particle IDs from their hydro counterparts and set internal
     * energies. */
486
487
    switch (gparts[i].type) {

488
489
490
      case swift_type_gas: {
        const struct part *p = &parts[-gparts[i].id_or_neg_offset];
        const struct xpart *xp = &xparts[-gparts[i].id_or_neg_offset];
491
492

        swift_parts[i].id = parts[-gparts[i].id_or_neg_offset].id;
493
494
495
496
        swift_parts[i].u = hydro_get_drifted_physical_internal_energy(p, cosmo);
        swift_parts[i].T = cooling_get_temperature(phys_const, hydro_props, us,
                                                   cosmo, cool_func, p, xp);
      } break;
497

498
499
500
501
      case swift_type_stars:

        swift_parts[i].id = sparts[-gparts[i].id_or_neg_offset].id;
        swift_parts[i].u = 0.f;
502
        swift_parts[i].T = 0.f;
503
504
        break;

505
506
507
508
      case swift_type_dark_matter:

        swift_parts[i].id = gparts[i].id_or_neg_offset;
        swift_parts[i].u = 0.f;
509
        swift_parts[i].T = 0.f;
510
511
512
513
        break;

      default:
        error("Particle type not handled by VELOCIraptor.");
514
    }
Matthieu Schaller's avatar
Matthieu Schaller committed
515
  }
516

517
518
519
520
521
522
523
  /* Report timing */
  if (e->verbose)
    message("VR Collecting particle info took %.3f %s.",
            clocks_from_ticks(getticks() - tic), clocks_getunit());

  tic = getticks();

524
525
526
527
  /* Values returned by VELOCIRaptor */
  int num_gparts_in_groups = -1;
  struct groupinfo *group_info = NULL;

Matthieu Schaller's avatar
Matthieu Schaller committed
528
  /* Call VELOCIraptor. */
529
  group_info = (struct groupinfo *)InvokeVelociraptor(
530
531
      snapnum, outputFileName, cosmo_info, sim_info, nr_gparts, nr_parts,
      nr_sparts, swift_parts, cell_node_ids, e->nr_threads, linked_with_snap,
532
      &num_gparts_in_groups);
533
534

  /* Check that the ouput is valid */
535
  if (linked_with_snap && group_info == NULL && num_gparts_in_groups < 0) {
Matthieu Schaller's avatar
Matthieu Schaller committed
536
    error("Exiting. Call to VELOCIraptor failed on rank: %d.", e->nodeID);
537
  }
538
539
540
  if (!linked_with_snap && group_info != NULL) {
    error("VELOCIraptor returned an array whilst it should not have.");
  }
Matthieu Schaller's avatar
Matthieu Schaller committed
541

542
543
544
545
546
547
548
  /* Report timing */
  if (e->verbose)
    message("VR Invokation of velociraptor took %.3f %s.",
            clocks_from_ticks(getticks() - tic), clocks_getunit());

  tic = getticks();

549
  /* Assign the group IDs back to the gparts */
550
  if (linked_with_snap) {
551

552
553
554
555
556
557
    if (posix_memalign((void **)&s->gpart_group_data, part_align,
                       nr_gparts * sizeof(struct velociraptor_gpart_data)) != 0)
      error("Failed to allocate array of gpart data for VELOCIraptor i/o.");

    struct velociraptor_gpart_data *data = s->gpart_group_data;

558
    /* Zero the array (gparts not in groups have an ID of 0) */
559
560
561
    bzero(data, nr_gparts * sizeof(struct velociraptor_gpart_data));

    /* Copy the data at the right place */
562
    for (int i = 0; i < num_gparts_in_groups; i++) {
563
      data[group_info[i].index].groupID = group_info[i].groupID;
564
565
    }

566
567
568
569
570
    /* Report timing */
    if (e->verbose)
      message("VR Copying group information back took %.3f %s.",
              clocks_from_ticks(getticks() - tic), clocks_getunit());

571
572
573
    /* Free the array returned by VELOCIraptor */
    free(group_info);
  }
Matthieu Schaller's avatar
Matthieu Schaller committed
574

575
576
577
  /* Reset the pthread affinity mask after VELOCIraptor returns. */
  pthread_setaffinity_np(thread, sizeof(cpu_set_t), engine_entry_affinity());

578
  /* Increase output counter (if not linked with snapshots) */
579
  if (!linked_with_snap) e->stf_output_count++;
580

581
#else
Matthieu Schaller's avatar
Matthieu Schaller committed
582
  error("SWIFT not configure to run with VELOCIraptor.");
583
#endif /* HAVE_VELOCIRAPTOR */
584
}