logger.c 21.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*******************************************************************************
 * This file is part of SWIFT.
 * Copyright (c) 2017 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
 *
 * 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
#ifdef HAVE_POSIX_FALLOCATE /* Are we on a sensible platform? */
lhausamm's avatar
lhausamm committed
24
#ifdef WITH_LOGGER
25

26
/* Some standard headers. */
Loic Hausammann's avatar
Format    
Loic Hausammann committed
27
#include <hdf5.h>
28
#include <math.h>
29
#include <stdint.h>
30
31
32
33
34
35
36
37
38
#include <stdlib.h>
#include <string.h>

/* This object's header. */
#include "logger.h"

/* Local headers. */
#include "atomic.h"
#include "dump.h"
Loic Hausammann's avatar
Format    
Loic Hausammann committed
39
#include "engine.h"
40
41
#include "error.h"
#include "part.h"
lhausamm's avatar
lhausamm committed
42
#include "units.h"
43

44
/*
45
46
 * Thoses are definitions from the format and therefore should not be changed!
 */
47
/* number of bytes for a mask */
48
// TODO change this to number of bits
49
50
#define logger_mask_size 1

51
52
53
/* number of bits for chunk header */
#define logger_header_bytes 8

54
/* number bytes for an offset */
55
#define logger_offset_size logger_header_bytes - logger_mask_size
56

57
/* number of bytes for the version information */
58
59
#define logger_version_size 20

60
61
/* number of bytes for the labels in the header */
#define logger_label_size 20
62

63
64
/* number of bytes for the number in the header */
#define logger_number_size 4
65

66
char logger_version[logger_version_size] = "0.1";
lhausamm's avatar
lhausamm committed
67

Loic Hausammann's avatar
Loic Hausammann committed
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
const struct mask_data logger_mask_data[logger_count_mask] = {
    /* Particle's position */
    {3 * sizeof(double), 1 << logger_x, "positions"},
    /* Particle's velocity */
    {3 * sizeof(float), 1 << logger_v, "velocities"},
    /* Particle's acceleration */
    {3 * sizeof(float), 1 << logger_a, "accelerations"},
    /* Particle's entropy */
    {sizeof(float), 1 << logger_u, "entropy"},
    /* Particle's smoothing length */
    {sizeof(float), 1 << logger_h, "smoothing length"},
    /* Particle's density */
    {sizeof(float), 1 << logger_rho, "density"},
    /* Particle's constants: mass (float) and ID (long long) */
    {sizeof(float) + sizeof(long long), 1 << logger_consts, "consts"},
    /* Simulation time stamp: integertime and double time (e.g. scale
       factor or time) */
    {sizeof(integertime_t) + sizeof(double), 1 << logger_timestamp,
     "timestamp"}};
87

lhausamm's avatar
lhausamm committed
88
/**
89
90
91
 * @brief Write the header of a chunk (offset + mask).
 *
 * This is maybe broken for big(?) endian.
lhausamm's avatar
lhausamm committed
92
93
94
95
96
97
98
99
 *
 * @param buff The writing buffer
 * @param mask The mask to write
 * @param offset The old offset
 * @param offset_new The new offset
 *
 * @return updated buff
 */
Loic Hausammann's avatar
Format    
Loic Hausammann committed
100
101
char *logger_write_chunk_header(char *buff, const unsigned int *mask,
                                const size_t *offset, const size_t offset_new) {
lhausamm's avatar
lhausamm committed
102
  /* write mask */
103
104
  memcpy(buff, mask, logger_mask_size);
  buff += logger_mask_size;
lhausamm's avatar
lhausamm committed
105
106

  /* write offset */
lhausamm's avatar
lhausamm committed
107
  size_t diff_offset = offset_new - *offset;
108
109
  memcpy(buff, &diff_offset, logger_offset_size);
  buff += logger_offset_size;
lhausamm's avatar
lhausamm committed
110
111
112
113
114

  return buff;
}

/**
lhausamm's avatar
lhausamm committed
115
 * @brief Write to the dump
lhausamm's avatar
lhausamm committed
116
117
 *
 * @param d #dump file
lhausamm's avatar
lhausamm committed
118
 * @param offset (return) offset of the data
lhausamm's avatar
lhausamm committed
119
120
121
 * @param size number of bytes to write
 * @param p pointer to the data
 */
Loic Hausammann's avatar
Format    
Loic Hausammann committed
122
123
void logger_write_data(struct dump *d, size_t *offset, size_t size,
                       const void *p) {
lhausamm's avatar
lhausamm committed
124
  /* get buffer */
lhausamm's avatar
lhausamm committed
125
  char *buff = dump_get(d, size, offset);
lhausamm's avatar
lhausamm committed
126
127

  /* write data to the buffer */
128
  memcpy(buff, p, size);
129

130
  /* Update offset to end of chunk */
131
  *offset += size;
132
133
}

134
135
/**
 * @brief Compute the size of a message given its mask.
136
137
138
139
 *
 * @param mask The mask that will be used to dump a #part or #gpart.
 *
 * @return The size of the logger message in bytes.
140
 */
lhausamm's avatar
lhausamm committed
141
int logger_compute_chunk_size(unsigned int mask) {
142
143

  /* Start with 8 bytes for the header. */
lhausamm's avatar
lhausamm committed
144
  int size = logger_mask_size + logger_offset_size;
145
146

  /* Is this a particle or a timestep? */
147
  if (mask & logger_mask_data[logger_timestamp].mask) {
148
149

    /* The timestamp should not contain any other bits. */
150
    if (mask != logger_mask_data[logger_timestamp].mask)
151
152
153
      error("Timestamps should not include any other data.");

    /* A timestamp consists of an unsigned long long int. */
154
    size += logger_mask_data[logger_timestamp].size;
155
156
157

  } else {

Loic Hausammann's avatar
Loic Hausammann committed
158
    for (int i = 0; i < logger_count_mask; i++) {
159
      if (mask & logger_mask_data[i].mask) {
Loic Hausammann's avatar
Loic Hausammann committed
160
        size += logger_mask_data[i].size;
161
      }
Loic Hausammann's avatar
Loic Hausammann committed
162
    }
163
164
165
166
  }

  return size;
}
167

lhausamm's avatar
lhausamm committed
168
/**
lhausamm's avatar
lhausamm committed
169
 * @brief log all particles in the engine.
lhausamm's avatar
lhausamm committed
170
 *
lhausamm's avatar
lhausamm committed
171
172
 * @param log The #logger
 * @param e The #engine
lhausamm's avatar
lhausamm committed
173
 */
lhausamm's avatar
lhausamm committed
174
void logger_log_all(struct logger *log, const struct engine *e) {
175
176
177
178
179
180
181

  /* Ensure that enough space is available */
  logger_ensure_size(log, e->total_nr_parts, e->total_nr_gparts, 0);
#ifdef SWIFT_DEBUG_CHECKS
  message("Need to implement stars");
#endif

lhausamm's avatar
lhausamm committed
182
  /* some constants */
lhausamm's avatar
lhausamm committed
183
  const struct space *s = e->s;
184
185
186
187
188
  const unsigned int mask =
      logger_mask_data[logger_x].mask | logger_mask_data[logger_v].mask |
      logger_mask_data[logger_a].mask | logger_mask_data[logger_u].mask |
      logger_mask_data[logger_h].mask | logger_mask_data[logger_rho].mask |
      logger_mask_data[logger_consts].mask;
lhausamm's avatar
lhausamm committed
189
190

  /* loop over all parts */
Loic Hausammann's avatar
Format    
Loic Hausammann committed
191
192
193
  for (long long i = 0; i < e->total_nr_parts; i++) {
    logger_log_part(log, &s->parts[i], mask,
                    &s->xparts[i].logger_data.last_offset);
194
    s->xparts[i].logger_data.steps_since_last_output = 0;
lhausamm's avatar
lhausamm committed
195
  }
lhausamm's avatar
lhausamm committed
196

lhausamm's avatar
lhausamm committed
197
  /* loop over all gparts */
Loic Hausammann's avatar
Format    
Loic Hausammann committed
198
  if (e->total_nr_gparts > 0) error("Not implemented");
lhausamm's avatar
lhausamm committed
199

lhausamm's avatar
lhausamm committed
200
201
  /* loop over all sparts */
  // TODO
lhausamm's avatar
lhausamm committed
202
203
}

204
205
206
/**
 * @brief Dump a #part to the log.
 *
lhausamm's avatar
lhausamm committed
207
 * @param log The #logger
Pedro Gonnet's avatar
Pedro Gonnet committed
208
 * @param p The #part to dump.
209
 * @param mask The mask of the data to dump.
Loic Hausammann's avatar
Format    
Loic Hausammann committed
210
211
 * @param offset Pointer to the offset of the previous log of this particle;
 * (return) offset of this log.
212
 */
Loic Hausammann's avatar
Format    
Loic Hausammann committed
213
214
void logger_log_part(struct logger *log, const struct part *p,
                     unsigned int mask, size_t *offset) {
215
216

  /* Make sure we're not writing a timestamp. */
217
  if (mask & logger_mask_data[logger_timestamp].mask)
218
219
220
    error("You should not log particles as timestamps.");

  /* Start by computing the size of the message. */
lhausamm's avatar
lhausamm committed
221
  const int size = logger_compute_chunk_size(mask);
222
223
224

  /* Allocate a chunk of memory in the dump of the right size. */
  size_t offset_new;
225
  char *buff = (char *)dump_get(&log->dump, size, &offset_new);
226
227

  /* Write the header. */
lhausamm's avatar
lhausamm committed
228
  buff = logger_write_chunk_header(buff, &mask, offset, offset_new);
229
230

  /* Particle position as three doubles. */
231
  if (mask & logger_mask_data[logger_x].mask) {
232
233
    memcpy(buff, p->x, logger_mask_data[logger_x].size);
    buff += logger_mask_data[logger_x].size;
234
235
236
  }

  /* Particle velocity as three floats. */
237
  if (mask & logger_mask_data[logger_v].mask) {
238
239
    memcpy(buff, p->v, logger_mask_data[logger_v].size);
    buff += logger_mask_data[logger_v].size;
240
241
242
  }

  /* Particle accelleration as three floats. */
243
  if (mask & logger_mask_data[logger_a].mask) {
244
245
    memcpy(buff, p->a_hydro, logger_mask_data[logger_a].size);
    buff += logger_mask_data[logger_a].size;
246
247
  }

248
249
#if defined(GADGET2_SPH)

250
  /* Particle internal energy as a single float. */
251
  if (mask & logger_mask_data[logger_u].mask) {
252
253
    memcpy(buff, &p->entropy, logger_mask_data[logger_u].size);
    buff += logger_mask_data[logger_u].size;
254
255
256
  }

  /* Particle smoothing length as a single float. */
257
  if (mask & logger_mask_data[logger_h].mask) {
258
259
    memcpy(buff, &p->h, logger_mask_data[logger_h].size);
    buff += logger_mask_data[logger_h].size;
260
261
262
  }

  /* Particle density as a single float. */
263
  if (mask & logger_mask_data[logger_rho].mask) {
264
265
    memcpy(buff, &p->rho, logger_mask_data[logger_rho].size);
    buff += logger_mask_data[logger_rho].size;
266
267
268
  }

  /* Particle constants, which is a bit more complicated. */
269
  if (mask & logger_mask_data[logger_consts].mask) {
270
    // TODO make it dependent of logger_mask_data
271
272
273
274
275
276
    memcpy(buff, &p->mass, sizeof(float));
    buff += sizeof(float);
    memcpy(buff, &p->id, sizeof(long long));
    buff += sizeof(long long);
  }

277
278
#endif

279
280
281
  /* Update the log message offset. */
  *offset = offset_new;
}
282
283
284
285

/**
 * @brief Dump a #gpart to the log.
 *
lhausamm's avatar
lhausamm committed
286
 * @param log The #logger
Pedro Gonnet's avatar
Pedro Gonnet committed
287
 * @param p The #gpart to dump.
288
 * @param mask The mask of the data to dump.
Loic Hausammann's avatar
Format    
Loic Hausammann committed
289
290
 * @param offset Pointer to the offset of the previous log of this particle;
 * (return) offset of this log.
291
 */
Loic Hausammann's avatar
Format    
Loic Hausammann committed
292
293
void logger_log_gpart(struct logger *log, const struct gpart *p,
                      unsigned int mask, size_t *offset) {
294
295

  /* Make sure we're not writing a timestamp. */
296
  if (mask & logger_mask_data[logger_timestamp].mask)
297
298
299
    error("You should not log particles as timestamps.");

  /* Make sure we're not looging fields not supported by gparts. */
300
301
  if (mask &
      (logger_mask_data[logger_u].mask | logger_mask_data[logger_rho].mask))
302
303
304
    error("Can't log SPH quantities for gparts.");

  /* Start by computing the size of the message. */
lhausamm's avatar
lhausamm committed
305
  const int size = logger_compute_chunk_size(mask);
306
307
308

  /* Allocate a chunk of memory in the dump of the right size. */
  size_t offset_new;
309
  char *buff = (char *)dump_get(&log->dump, size, &offset_new);
310
311

  /* Write the header. */
lhausamm's avatar
lhausamm committed
312
  buff = logger_write_chunk_header(buff, &mask, offset, offset_new);
313
314

  /* Particle position as three doubles. */
315
  if (mask & logger_mask_data[logger_x].mask) {
316
317
    memcpy(buff, p->x, logger_mask_data[logger_x].size);
    buff += logger_mask_data[logger_x].size;
318
319
320
  }

  /* Particle velocity as three floats. */
321
  if (mask & logger_mask_data[logger_v].mask) {
322
323
    memcpy(buff, p->v_full, logger_mask_data[logger_v].size);
    buff += logger_mask_data[logger_v].size;
324
325
326
  }

  /* Particle accelleration as three floats. */
327
  if (mask & logger_mask_data[logger_a].mask) {
328
329
    memcpy(buff, p->a_grav, logger_mask_data[logger_a].size);
    buff += logger_mask_data[logger_a].size;
330
331
332
  }

  /* Particle constants, which is a bit more complicated. */
333
  if (mask & logger_mask_data[logger_consts].mask) {
334
    // TODO make it dependent of logger_mask_data
335
336
337
338
339
340
341
342
343
344
    memcpy(buff, &p->mass, sizeof(float));
    buff += sizeof(float);
    memcpy(buff, &p->id_or_neg_offset, sizeof(long long));
    buff += sizeof(long long);
  }

  /* Update the log message offset. */
  *offset = offset_new;
}

lhausamm's avatar
lhausamm committed
345
346
347
/**
 * @brief write a timestamp
 *
lhausamm's avatar
lhausamm committed
348
 * @param log The #logger
lhausamm's avatar
lhausamm committed
349
 * @param timestamp time to write
350
 * @param time time or scale factor
Loic Hausammann's avatar
Format    
Loic Hausammann committed
351
352
 * @param offset Pointer to the offset of the previous log of this particle;
 * (return) offset of this log.
lhausamm's avatar
lhausamm committed
353
 */
Loic Hausammann's avatar
Format    
Loic Hausammann committed
354
void logger_log_timestamp(struct logger *log, integertime_t timestamp,
355
                          double time, size_t *offset) {
356
  struct dump *dump = &log->dump;
Loic Hausammann's avatar
Format    
Loic Hausammann committed
357

358
  /* Start by computing the size of the message. */
359
360
  const int size =
      logger_compute_chunk_size(logger_mask_data[logger_timestamp].mask);
361
362
363

  /* Allocate a chunk of memory in the dump of the right size. */
  size_t offset_new;
364
  char *buff = (char *)dump_get(dump, size, &offset_new);
365
366

  /* Write the header. */
367
  unsigned int mask = logger_mask_data[logger_timestamp].mask;
lhausamm's avatar
lhausamm committed
368
  buff = logger_write_chunk_header(buff, &mask, offset, offset_new);
Pedro Gonnet's avatar
Pedro Gonnet committed
369

370
  /* Store the timestamp. */
371
  // TODO make it dependent of logger_mask_data
372
  memcpy(buff, &timestamp, sizeof(integertime_t));
373
374
375
376
  buff += sizeof(integertime_t);

  /* Store the time */
  memcpy(buff, &time, sizeof(double));
377
378
379
380

  /* Update the log message offset. */
  *offset = offset_new;
}
Pedro Gonnet's avatar
Pedro Gonnet committed
381

lhausamm's avatar
lhausamm committed
382
/**
lhausamm's avatar
lhausamm committed
383
 * @brief Ensure that the buffer is large enough for a step.
lhausamm's avatar
lhausamm committed
384
385
 *
 * Check if logger parameters are large enough to write all particles
lhausamm's avatar
lhausamm committed
386
 * and ensure that enough space is available in the buffer.
lhausamm's avatar
lhausamm committed
387
 *
388
 * @param log The #logger
lhausamm's avatar
lhausamm committed
389
390
391
 * @param total_nr_parts total number of part
 * @param total_nr_gparts total number of gpart
 * @param total_nr_sparts total number of spart
lhausamm's avatar
lhausamm committed
392
 */
Loic Hausammann's avatar
Format    
Loic Hausammann committed
393
394
void logger_ensure_size(struct logger *log, size_t total_nr_parts,
                        size_t total_nr_gparts, size_t total_nr_sparts) {
lhausamm's avatar
lhausamm committed
395
396

  /* count part memory */
397
  size_t limit = log->max_chunk_size;
lhausamm's avatar
lhausamm committed
398
399
400

  limit *= total_nr_parts;

lhausamm's avatar
lhausamm committed
401
  /* count gpart memory */
Loic Hausammann's avatar
Format    
Loic Hausammann committed
402
  if (total_nr_gparts > 0) error("Not implemented");
403

lhausamm's avatar
lhausamm committed
404
  /* count spart memory */
Loic Hausammann's avatar
Format    
Loic Hausammann committed
405
  if (total_nr_sparts > 0) error("Not implemented");
lhausamm's avatar
lhausamm committed
406
407

  /* ensure enough space in dump */
408
  dump_ensure(&log->dump, limit, log->buffer_scale * limit);
lhausamm's avatar
lhausamm committed
409
410
411
412
413
414
}

/**
 * @brief intialize the logger structure
 *
 * @param log The #logger
415
 * @param params The #swift_params
lhausamm's avatar
lhausamm committed
416
 */
Loic Hausammann's avatar
Format    
Loic Hausammann committed
417
void logger_init(struct logger *log, struct swift_params *params) {
lhausamm's avatar
lhausamm committed
418
419
  /* read parameters */
  log->delta_step = parser_get_param_int(params, "Logger:delta_step");
Loic Hausammann's avatar
Loic Hausammann committed
420
  size_t buffer_size =
Loic Hausammann's avatar
Loic Hausammann committed
421
422
      parser_get_opt_param_float(params, "Logger:initial_buffer_size", 0.5) *
      1e9;
Loic Hausammann's avatar
Format    
Loic Hausammann committed
423
  log->buffer_scale =
424
      parser_get_opt_param_float(params, "Logger:buffer_scale", 10);
lhausamm's avatar
lhausamm committed
425
426
  parser_get_param_string(params, "Logger:basename", log->base_name);

lhausamm's avatar
lhausamm committed
427
428
429
  /* set initial value of parameters */
  log->timestamp_offset = 0;

lhausamm's avatar
lhausamm committed
430
431
432
433
434
  /* generate dump filename */
  char logger_name_file[PARSER_MAX_LINE_SIZE];
  strcpy(logger_name_file, log->base_name);
  strcat(logger_name_file, ".dump");

435
436
437
438
439
440
441
442
  /* Compute max size for a particle chunk */
  int max_size = logger_offset_size + logger_mask_size;

  /* Loop over all fields except timestamp */
  for (int i = 0; i < logger_count_mask - 1; i++) {
    max_size += logger_mask_data[i].size;
  }
  log->max_chunk_size = max_size;
443

lhausamm's avatar
lhausamm committed
444
  /* init dump */
445
  dump_init(&log->dump, logger_name_file, buffer_size);
lhausamm's avatar
lhausamm committed
446
447
448
449
450
451
452
}

/**
 * @brief Close dump file and desallocate memory
 *
 * @param log The #logger
 */
453
void logger_clean(struct logger *log) { dump_close(&log->dump); }
lhausamm's avatar
lhausamm committed
454

455
456
457
/**
 * @brief Write a file header to a logger file
 *
458
 * @param log The #logger
459
460
461
 * @param dump The #dump in which to log the particle data.
 *
 */
462
void logger_write_file_header(struct logger *log, const struct engine *e) {
lhausamm's avatar
lhausamm committed
463

lhausamm's avatar
lhausamm committed
464
  /* get required variables */
465
  struct dump *dump = &log->dump;
Loic Hausammann's avatar
Format    
Loic Hausammann committed
466

lhausamm's avatar
lhausamm committed
467
  size_t file_offset = dump->file_offset;
Loic Hausammann's avatar
Format    
Loic Hausammann committed
468

lhausamm's avatar
lhausamm committed
469
  if (file_offset != 0)
Loic Hausammann's avatar
Format    
Loic Hausammann committed
470
471
472
    error(
        "The logger is not empty."
        "This function should be called before writing anything in the logger");
473
474

  /* Write version information */
lhausamm's avatar
lhausamm committed
475
  logger_write_data(dump, &file_offset, logger_version_size, &logger_version);
Loic Hausammann's avatar
Format    
Loic Hausammann committed
476

lhausamm's avatar
lhausamm committed
477
  /* write offset direction */
478
  const int reversed = 0;
479
  logger_write_data(dump, &file_offset, logger_number_size, &reversed);
lhausamm's avatar
lhausamm committed
480

481
  /* placeholder to write the offset of the first log here */
482
  char *skip_header = dump_get(dump, logger_offset_size, &file_offset);
483
484

  /* write number of bytes used for names */
485
  const int label_size = logger_label_size;
486
  logger_write_data(dump, &file_offset, logger_number_size, &label_size);
lhausamm's avatar
lhausamm committed
487
488

  /* write number of masks */
489
  int count_mask = logger_count_mask;
490
  logger_write_data(dump, &file_offset, logger_number_size, &count_mask);
491

lhausamm's avatar
lhausamm committed
492
  /* write masks */
lhausamm's avatar
lhausamm committed
493
  // loop over all mask type
494
  for (int i = 0; i < logger_count_mask; i++) {
495
    // mask name
496
    logger_write_data(dump, &file_offset, logger_label_size,
497
                      &logger_mask_data[i].name);
498
499

    // mask size
500
    logger_write_data(dump, &file_offset, logger_number_size,
501
                      &logger_mask_data[i].size);
502
  }
503

lhausamm's avatar
lhausamm committed
504
  /* last step: write first offset */
505
  memcpy(skip_header, &file_offset, logger_offset_size);
lhausamm's avatar
lhausamm committed
506
}
507

lhausamm's avatar
lhausamm committed
508
509
510
511
512
/**
 * @brief read chunk header
 *
 * @param buff The reading buffer
 * @param mask The mask to read
lhausamm's avatar
lhausamm committed
513
 * @param offset (return) the offset pointed by this chunk (absolute)
lhausamm's avatar
lhausamm committed
514
515
516
517
 * @param offset_cur The current chunk offset
 *
 * @return Number of bytes read
 */
Loic Hausammann's avatar
Format    
Loic Hausammann committed
518
519
__attribute__((always_inline)) INLINE static int logger_read_chunk_header(
    const char *buff, unsigned int *mask, size_t *offset, size_t cur_offset) {
lhausamm's avatar
lhausamm committed
520
521
  memcpy(mask, buff, logger_mask_size);
  buff += logger_mask_size;
lhausamm's avatar
lhausamm committed
522
523

  *offset = 0;
lhausamm's avatar
lhausamm committed
524
  memcpy(offset, buff, logger_offset_size);
lhausamm's avatar
lhausamm committed
525
  *offset = cur_offset - *offset;
Loic Hausammann's avatar
Format    
Loic Hausammann committed
526

lhausamm's avatar
lhausamm committed
527
  return logger_mask_size + logger_offset_size;
lhausamm's avatar
lhausamm committed
528
529
}

Pedro Gonnet's avatar
Pedro Gonnet committed
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
/**
 * @brief Read a logger message and store the data in a #part.
 *
 * @param p The #part in which to store the values.
 * @param offset Pointer to the offset of the logger message in the buffer,
 *        will be overwritten with the offset of the previous message.
 * @param buff Pointer to the start of an encoded logger message.
 *
 * @return The mask containing the values read.
 */
int logger_read_part(struct part *p, size_t *offset, const char *buff) {

  /* Jump to the offset. */
  buff = &buff[*offset];

  /* Start by reading the logger mask for this entry. */
lhausamm's avatar
lhausamm committed
546
547
548
  const size_t cur_offset = *offset;
  unsigned int mask = 0;
  buff += logger_read_chunk_header(buff, &mask, offset, cur_offset);
Pedro Gonnet's avatar
Pedro Gonnet committed
549
550

  /* We are only interested in particle data. */
551
  if (mask & logger_mask_data[logger_timestamp].mask)
Pedro Gonnet's avatar
Pedro Gonnet committed
552
553
554
    error("Trying to read timestamp as particle.");

  /* Particle position as three doubles. */
555
  if (mask & logger_mask_data[logger_x].mask) {
556
557
    memcpy(p->x, buff, logger_mask_data[logger_x].size);
    buff += logger_mask_data[logger_x].size;
Pedro Gonnet's avatar
Pedro Gonnet committed
558
559
560
  }

  /* Particle velocity as three floats. */
561
  if (mask & logger_mask_data[logger_v].mask) {
562
563
    memcpy(p->v, buff, logger_mask_data[logger_v].size);
    buff += logger_mask_data[logger_v].size;
Pedro Gonnet's avatar
Pedro Gonnet committed
564
565
566
  }

  /* Particle accelleration as three floats. */
567
  if (mask & logger_mask_data[logger_a].mask) {
568
569
    memcpy(p->a_hydro, buff, logger_mask_data[logger_a].size);
    buff += logger_mask_data[logger_a].size;
Pedro Gonnet's avatar
Pedro Gonnet committed
570
571
  }

572
573
#if defined(GADGET2_SPH)

Pedro Gonnet's avatar
Pedro Gonnet committed
574
  /* Particle internal energy as a single float. */
575
  if (mask & logger_mask_data[logger_u].mask) {
576
577
    memcpy(&p->entropy, buff, logger_mask_data[logger_u].size);
    buff += logger_mask_data[logger_u].size;
Pedro Gonnet's avatar
Pedro Gonnet committed
578
579
580
  }

  /* Particle smoothing length as a single float. */
581
  if (mask & logger_mask_data[logger_h].mask) {
582
583
    memcpy(&p->h, buff, logger_mask_data[logger_h].size);
    buff += logger_mask_data[logger_h].size;
Pedro Gonnet's avatar
Pedro Gonnet committed
584
585
586
  }

  /* Particle density as a single float. */
587
  if (mask & logger_mask_data[logger_rho].mask) {
588
589
    memcpy(&p->rho, buff, logger_mask_data[logger_rho].size);
    buff += logger_mask_data[logger_rho].size;
Pedro Gonnet's avatar
Pedro Gonnet committed
590
591
592
  }

  /* Particle constants, which is a bit more complicated. */
593
  if (mask & logger_mask_data[logger_rho].mask) {
594
    // TODO make it dependent of logger_mask_data
Pedro Gonnet's avatar
Pedro Gonnet committed
595
596
597
598
599
600
    memcpy(&p->mass, buff, sizeof(float));
    buff += sizeof(float);
    memcpy(&p->id, buff, sizeof(long long));
    buff += sizeof(long long);
  }

601
602
#endif

Pedro Gonnet's avatar
Pedro Gonnet committed
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
  /* Finally, return the mask of the values we just read. */
  return mask;
}

/**
 * @brief Read a logger message and store the data in a #gpart.
 *
 * @param p The #gpart in which to store the values.
 * @param offset Pointer to the offset of the logger message in the buffer,
 *        will be overwritten with the offset of the previous message.
 * @param buff Pointer to the start of an encoded logger message.
 *
 * @return The mask containing the values read.
 */
int logger_read_gpart(struct gpart *p, size_t *offset, const char *buff) {

  /* Jump to the offset. */
  buff = &buff[*offset];

  /* Start by reading the logger mask for this entry. */
lhausamm's avatar
lhausamm committed
623
624
625
  const size_t cur_offset = *offset;
  unsigned int mask = 0;
  buff += logger_read_chunk_header(buff, &mask, offset, cur_offset);
Pedro Gonnet's avatar
Pedro Gonnet committed
626
627

  /* We are only interested in particle data. */
628
  if (mask & logger_mask_data[logger_timestamp].mask)
Pedro Gonnet's avatar
Pedro Gonnet committed
629
    error("Trying to read timestamp as particle.");
Pedro Gonnet's avatar
Pedro Gonnet committed
630

Pedro Gonnet's avatar
Pedro Gonnet committed
631
  /* We can't store all part fields in a gpart. */
632
633
  if (mask &
      (logger_mask_data[logger_u].mask | logger_mask_data[logger_rho].mask))
Pedro Gonnet's avatar
Pedro Gonnet committed
634
635
636
    error("Trying to read SPH quantities into a gpart.");

  /* Particle position as three doubles. */
637
  if (mask & logger_mask_data[logger_x].mask) {
638
639
    memcpy(p->x, buff, logger_mask_data[logger_x].size);
    buff += logger_mask_data[logger_x].size;
Pedro Gonnet's avatar
Pedro Gonnet committed
640
641
642
  }

  /* Particle velocity as three floats. */
643
  if (mask & logger_mask_data[logger_v].mask) {
644
645
    memcpy(p->v_full, buff, logger_mask_data[logger_v].size);
    buff += logger_mask_data[logger_v].size;
Pedro Gonnet's avatar
Pedro Gonnet committed
646
647
648
  }

  /* Particle accelleration as three floats. */
649
  if (mask & logger_mask_data[logger_a].mask) {
650
651
    memcpy(p->a_grav, buff, logger_mask_data[logger_a].size);
    buff += logger_mask_data[logger_a].size;
Pedro Gonnet's avatar
Pedro Gonnet committed
652
653
654
  }

  /* Particle constants, which is a bit more complicated. */
655
  if (mask & logger_mask_data[logger_rho].mask) {
656
    // TODO make it dependent of logger_mask_data
Pedro Gonnet's avatar
Pedro Gonnet committed
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
    memcpy(&p->mass, buff, sizeof(float));
    buff += sizeof(float);
    memcpy(&p->id_or_neg_offset, buff, sizeof(long long));
    buff += sizeof(long long);
  }

  /* Finally, return the mask of the values we just read. */
  return mask;
}

/**
 * @brief Read a logger message for a timestamp.
 *
 * @param t The timestamp in which to store the value.
 * @param offset Pointer to the offset of the logger message in the buffer,
 *        will be overwritten with the offset of the previous message.
 * @param buff Pointer to the start of an encoded logger message.
 *
 * @return The mask containing the values read.
 */
677
678
int logger_read_timestamp(unsigned long long int *t, double *time,
                          size_t *offset, const char *buff) {
Pedro Gonnet's avatar
Pedro Gonnet committed
679
680
681
682
683

  /* Jump to the offset. */
  buff = &buff[*offset];

  /* Start by reading the logger mask for this entry. */
lhausamm's avatar
lhausamm committed
684
685
686
  const size_t cur_offset = *offset;
  unsigned int mask = 0;
  buff += logger_read_chunk_header(buff, &mask, offset, cur_offset);
Pedro Gonnet's avatar
Pedro Gonnet committed
687
688

  /* We are only interested in timestamps. */
689
  if (!(mask & logger_mask_data[logger_timestamp].mask))
Pedro Gonnet's avatar
Pedro Gonnet committed
690
    error("Trying to read timestamp from a particle.");
Pedro Gonnet's avatar
Pedro Gonnet committed
691

Pedro Gonnet's avatar
Pedro Gonnet committed
692
  /* Make sure we don't have extra fields. */
693
  if (mask != logger_mask_data[logger_timestamp].mask)
Pedro Gonnet's avatar
Pedro Gonnet committed
694
695
696
    error("Timestamp message contains extra fields.");

  /* Copy the timestamp value from the buffer. */
697
  // TODO make it dependent of logger_mask_data
Pedro Gonnet's avatar
Pedro Gonnet committed
698
  memcpy(t, buff, sizeof(unsigned long long int));
699
700
701
  buff += sizeof(unsigned long long int);

  /* Copy the timestamp value from the buffer. */
702
  memcpy(time, buff, sizeof(double));
Pedro Gonnet's avatar
Pedro Gonnet committed
703
704
705
706

  /* Finally, return the mask of the values we just read. */
  return mask;
}
707

lhausamm's avatar
lhausamm committed
708
709
#endif /* WITH_LOGGER */

710
#endif /* HAVE_POSIX_FALLOCATE */