/*******************************************************************************
* This file is part of SWIFT.
* Copyright (c) 2017 Matthieu Schaller (schaller@strw.leidenuniv.nl).
*
* 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 .
*
******************************************************************************/
/* Config parameters. */
#include
/* This object's header. */
#include "common_io.h"
/* Local includes. */
#include "engine.h"
#include "io_properties.h"
#include "threadpool.h"
/**
* @brief Mapper function to copy #part or #gpart fields into a buffer.
*/
void io_copy_mapper(void* restrict temp, int N, void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const size_t typeSize = io_sizeof_type(props.type);
const size_t copySize = typeSize * props.dimension;
/* How far are we with this chunk? */
char* restrict temp_c = (char*)temp;
const ptrdiff_t delta = (temp_c - props.start_temp_c) / copySize;
for (int k = 0; k < N; k++) {
memcpy(&temp_c[k * copySize], props.field + (delta + k) * props.partSize,
copySize);
}
}
/**
* @brief Mapper function to copy #part into a buffer of floats using a
* conversion function.
*/
void io_convert_part_f_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct part* restrict parts = props.parts;
const struct xpart* restrict xparts = props.xparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
float* restrict temp_f = (float*)temp;
const ptrdiff_t delta = (temp_f - props.start_temp_f) / dim;
for (int i = 0; i < N; i++)
props.convert_part_f(e, parts + delta + i, xparts + delta + i,
&temp_f[i * dim]);
}
/**
* @brief Mapper function to copy #part into a buffer of ints using a
* conversion function.
*/
void io_convert_part_i_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct part* restrict parts = props.parts;
const struct xpart* restrict xparts = props.xparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
int* restrict temp_i = (int*)temp;
const ptrdiff_t delta = (temp_i - props.start_temp_i) / dim;
for (int i = 0; i < N; i++)
props.convert_part_i(e, parts + delta + i, xparts + delta + i,
&temp_i[i * dim]);
}
/**
* @brief Mapper function to copy #part into a buffer of doubles using a
* conversion function.
*/
void io_convert_part_d_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct part* restrict parts = props.parts;
const struct xpart* restrict xparts = props.xparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
double* restrict temp_d = (double*)temp;
const ptrdiff_t delta = (temp_d - props.start_temp_d) / dim;
for (int i = 0; i < N; i++)
props.convert_part_d(e, parts + delta + i, xparts + delta + i,
&temp_d[i * dim]);
}
/**
* @brief Mapper function to copy #part into a buffer of doubles using a
* conversion function.
*/
void io_convert_part_l_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct part* restrict parts = props.parts;
const struct xpart* restrict xparts = props.xparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
long long* restrict temp_l = (long long*)temp;
const ptrdiff_t delta = (temp_l - props.start_temp_l) / dim;
for (int i = 0; i < N; i++)
props.convert_part_l(e, parts + delta + i, xparts + delta + i,
&temp_l[i * dim]);
}
/**
* @brief Mapper function to copy #gpart into a buffer of floats using a
* conversion function.
*/
void io_convert_gpart_f_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct gpart* restrict gparts = props.gparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
float* restrict temp_f = (float*)temp;
const ptrdiff_t delta = (temp_f - props.start_temp_f) / dim;
for (int i = 0; i < N; i++)
props.convert_gpart_f(e, gparts + delta + i, &temp_f[i * dim]);
}
/**
* @brief Mapper function to copy #gpart into a buffer of ints using a
* conversion function.
*/
void io_convert_gpart_i_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct gpart* restrict gparts = props.gparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
int* restrict temp_i = (int*)temp;
const ptrdiff_t delta = (temp_i - props.start_temp_i) / dim;
for (int i = 0; i < N; i++)
props.convert_gpart_i(e, gparts + delta + i, &temp_i[i * dim]);
}
/**
* @brief Mapper function to copy #gpart into a buffer of doubles using a
* conversion function.
*/
void io_convert_gpart_d_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct gpart* restrict gparts = props.gparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
double* restrict temp_d = (double*)temp;
const ptrdiff_t delta = (temp_d - props.start_temp_d) / dim;
for (int i = 0; i < N; i++)
props.convert_gpart_d(e, gparts + delta + i, &temp_d[i * dim]);
}
/**
* @brief Mapper function to copy #gpart into a buffer of doubles using a
* conversion function.
*/
void io_convert_gpart_l_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct gpart* restrict gparts = props.gparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
long long* restrict temp_l = (long long*)temp;
const ptrdiff_t delta = (temp_l - props.start_temp_l) / dim;
for (int i = 0; i < N; i++)
props.convert_gpart_l(e, gparts + delta + i, &temp_l[i * dim]);
}
/**
* @brief Mapper function to copy #spart into a buffer of floats using a
* conversion function.
*/
void io_convert_spart_f_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct spart* restrict sparts = props.sparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
float* restrict temp_f = (float*)temp;
const ptrdiff_t delta = (temp_f - props.start_temp_f) / dim;
for (int i = 0; i < N; i++)
props.convert_spart_f(e, sparts + delta + i, &temp_f[i * dim]);
}
/**
* @brief Mapper function to copy #spart into a buffer of ints using a
* conversion function.
*/
void io_convert_spart_i_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct spart* restrict sparts = props.sparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
int* restrict temp_i = (int*)temp;
const ptrdiff_t delta = (temp_i - props.start_temp_i) / dim;
for (int i = 0; i < N; i++)
props.convert_spart_i(e, sparts + delta + i, &temp_i[i * dim]);
}
/**
* @brief Mapper function to copy #spart into a buffer of doubles using a
* conversion function.
*/
void io_convert_spart_d_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct spart* restrict sparts = props.sparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
double* restrict temp_d = (double*)temp;
const ptrdiff_t delta = (temp_d - props.start_temp_d) / dim;
for (int i = 0; i < N; i++)
props.convert_spart_d(e, sparts + delta + i, &temp_d[i * dim]);
}
/**
* @brief Mapper function to copy #spart into a buffer of doubles using a
* conversion function.
*/
void io_convert_spart_l_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct spart* restrict sparts = props.sparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
long long* restrict temp_l = (long long*)temp;
const ptrdiff_t delta = (temp_l - props.start_temp_l) / dim;
for (int i = 0; i < N; i++)
props.convert_spart_l(e, sparts + delta + i, &temp_l[i * dim]);
}
/**
* @brief Mapper function to copy #bpart into a buffer of floats using a
* conversion function.
*/
void io_convert_bpart_f_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct bpart* restrict bparts = props.bparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
float* restrict temp_f = (float*)temp;
const ptrdiff_t delta = (temp_f - props.start_temp_f) / dim;
for (int i = 0; i < N; i++)
props.convert_bpart_f(e, bparts + delta + i, &temp_f[i * dim]);
}
/**
* @brief Mapper function to copy #bpart into a buffer of ints using a
* conversion function.
*/
void io_convert_bpart_i_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct bpart* restrict bparts = props.bparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
int* restrict temp_i = (int*)temp;
const ptrdiff_t delta = (temp_i - props.start_temp_i) / dim;
for (int i = 0; i < N; i++)
props.convert_bpart_i(e, bparts + delta + i, &temp_i[i * dim]);
}
/**
* @brief Mapper function to copy #bpart into a buffer of doubles using a
* conversion function.
*/
void io_convert_bpart_d_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct bpart* restrict bparts = props.bparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
double* restrict temp_d = (double*)temp;
const ptrdiff_t delta = (temp_d - props.start_temp_d) / dim;
for (int i = 0; i < N; i++)
props.convert_bpart_d(e, bparts + delta + i, &temp_d[i * dim]);
}
/**
* @brief Mapper function to copy #bpart into a buffer of doubles using a
* conversion function.
*/
void io_convert_bpart_l_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct bpart* restrict bparts = props.bparts;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
long long* restrict temp_l = (long long*)temp;
const ptrdiff_t delta = (temp_l - props.start_temp_l) / dim;
for (int i = 0; i < N; i++)
props.convert_bpart_l(e, bparts + delta + i, &temp_l[i * dim]);
}
/**
* @brief Mapper function to copy #sink into a buffer of floats using a
* conversion function.
*/
void io_convert_sink_f_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct sink* restrict sinks = props.sinks;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
float* restrict temp_f = (float*)temp;
const ptrdiff_t delta = (temp_f - props.start_temp_f) / dim;
for (int i = 0; i < N; i++)
props.convert_sink_f(e, sinks + delta + i, &temp_f[i * dim]);
}
/**
* @brief Mapper function to copy #sink into a buffer of ints using a
* conversion function.
*/
void io_convert_sink_i_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct sink* restrict sinks = props.sinks;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
int* restrict temp_i = (int*)temp;
const ptrdiff_t delta = (temp_i - props.start_temp_i) / dim;
for (int i = 0; i < N; i++)
props.convert_sink_i(e, sinks + delta + i, &temp_i[i * dim]);
}
/**
* @brief Mapper function to copy #sink into a buffer of doubles using a
* conversion function.
*/
void io_convert_sink_d_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct sink* restrict sinks = props.sinks;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
double* restrict temp_d = (double*)temp;
const ptrdiff_t delta = (temp_d - props.start_temp_d) / dim;
for (int i = 0; i < N; i++)
props.convert_sink_d(e, sinks + delta + i, &temp_d[i * dim]);
}
/**
* @brief Mapper function to copy #sink into a buffer of doubles using a
* conversion function.
*/
void io_convert_sink_l_mapper(void* restrict temp, int N,
void* restrict extra_data) {
const struct io_props props = *((const struct io_props*)extra_data);
const struct sink* restrict sinks = props.sinks;
const struct engine* e = props.e;
const size_t dim = props.dimension;
/* How far are we with this chunk? */
long long* restrict temp_l = (long long*)temp;
const ptrdiff_t delta = (temp_l - props.start_temp_l) / dim;
for (int i = 0; i < N; i++)
props.convert_sink_l(e, sinks + delta + i, &temp_l[i * dim]);
}
/**
* @brief Copy the particle data into a temporary buffer ready for i/o.
*
* @param temp The buffer to be filled. Must be allocated and aligned properly.
* @param e The #engine.
* @param props The #io_props corresponding to the particle field we are
* copying.
* @param N The number of particles to copy
* @param internal_units The system of units used internally.
* @param snapshot_units The system of units used for the snapshots.
*/
void io_copy_temp_buffer(void* temp, const struct engine* e,
struct io_props props, size_t N,
const struct unit_system* internal_units,
const struct unit_system* snapshot_units) {
const size_t typeSize = io_sizeof_type(props.type);
const size_t copySize = typeSize * props.dimension;
const size_t num_elements = N * props.dimension;
/* Copy particle data to temporary buffer */
if (props.conversion == 0) { /* No conversion */
/* Prepare some parameters */
char* temp_c = (char*)temp;
props.start_temp_c = temp_c;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool, io_copy_mapper, temp_c,
N, copySize, threadpool_auto_chunk_size, (void*)&props);
} else { /* Converting particle to data */
if (props.type == FLOAT && props.parts != NULL) {
/* Prepare some parameters */
float* temp_f = (float*)temp;
props.start_temp_f = (float*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_part_f_mapper, temp_f, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == INT && props.parts != NULL) {
/* Prepare some parameters */
int* temp_i = (int*)temp;
props.start_temp_i = (int*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_part_i_mapper, temp_i, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == DOUBLE && props.parts != NULL) {
/* Prepare some parameters */
double* temp_d = (double*)temp;
props.start_temp_d = (double*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_part_d_mapper, temp_d, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == LONGLONG && props.parts != NULL) {
/* Prepare some parameters */
long long* temp_l = (long long*)temp;
props.start_temp_l = (long long*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_part_l_mapper, temp_l, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == FLOAT && props.gparts != NULL) {
/* Prepare some parameters */
float* temp_f = (float*)temp;
props.start_temp_f = (float*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_gpart_f_mapper, temp_f, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == INT && props.gparts != NULL) {
/* Prepare some parameters */
int* temp_i = (int*)temp;
props.start_temp_i = (int*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_gpart_i_mapper, temp_i, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == DOUBLE && props.gparts != NULL) {
/* Prepare some parameters */
double* temp_d = (double*)temp;
props.start_temp_d = (double*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_gpart_d_mapper, temp_d, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == LONGLONG && props.gparts != NULL) {
/* Prepare some parameters */
long long* temp_l = (long long*)temp;
props.start_temp_l = (long long*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_gpart_l_mapper, temp_l, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == FLOAT && props.sparts != NULL) {
/* Prepare some parameters */
float* temp_f = (float*)temp;
props.start_temp_f = (float*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_spart_f_mapper, temp_f, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == INT && props.sparts != NULL) {
/* Prepare some parameters */
int* temp_i = (int*)temp;
props.start_temp_i = (int*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_spart_i_mapper, temp_i, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == DOUBLE && props.sparts != NULL) {
/* Prepare some parameters */
double* temp_d = (double*)temp;
props.start_temp_d = (double*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_spart_d_mapper, temp_d, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == LONGLONG && props.sparts != NULL) {
/* Prepare some parameters */
long long* temp_l = (long long*)temp;
props.start_temp_l = (long long*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_spart_l_mapper, temp_l, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == FLOAT && props.sinks != NULL) {
/* Prepare some parameters */
float* temp_f = (float*)temp;
props.start_temp_f = (float*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_sink_f_mapper, temp_f, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == INT && props.sinks != NULL) {
/* Prepare some parameters */
int* temp_i = (int*)temp;
props.start_temp_i = (int*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_sink_i_mapper, temp_i, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == DOUBLE && props.sinks != NULL) {
/* Prepare some parameters */
double* temp_d = (double*)temp;
props.start_temp_d = (double*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_sink_d_mapper, temp_d, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == LONGLONG && props.sinks != NULL) {
/* Prepare some parameters */
long long* temp_l = (long long*)temp;
props.start_temp_l = (long long*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_sink_l_mapper, temp_l, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == FLOAT && props.bparts != NULL) {
/* Prepare some parameters */
float* temp_f = (float*)temp;
props.start_temp_f = (float*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_bpart_f_mapper, temp_f, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == INT && props.bparts != NULL) {
/* Prepare some parameters */
int* temp_i = (int*)temp;
props.start_temp_i = (int*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_bpart_i_mapper, temp_i, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == DOUBLE && props.bparts != NULL) {
/* Prepare some parameters */
double* temp_d = (double*)temp;
props.start_temp_d = (double*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_bpart_d_mapper, temp_d, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else if (props.type == LONGLONG && props.bparts != NULL) {
/* Prepare some parameters */
long long* temp_l = (long long*)temp;
props.start_temp_l = (long long*)temp;
props.e = e;
/* Copy the whole thing into a buffer */
threadpool_map((struct threadpool*)&e->threadpool,
io_convert_bpart_l_mapper, temp_l, N, copySize,
threadpool_auto_chunk_size, (void*)&props);
} else {
if (N != 0 && props.ptr_func != NULL)
error("Missing conversion function");
}
}
/* Unit conversion if necessary */
const double factor =
units_conversion_factor(internal_units, snapshot_units, props.units);
if (factor != 1.) {
/* message("Converting ! factor=%e", factor); */
if (io_is_double_precision(props.type)) {
swift_declare_aligned_ptr(double, temp_d, (double*)temp,
IO_BUFFER_ALIGNMENT);
for (size_t i = 0; i < num_elements; ++i) temp_d[i] *= factor;
} else {
swift_declare_aligned_ptr(float, temp_f, (float*)temp,
IO_BUFFER_ALIGNMENT);
for (size_t i = 0; i < num_elements; ++i) temp_f[i] *= factor;
}
}
}