Initial import
This commit is contained in:
commit
56a50eead3
820 changed files with 192077 additions and 0 deletions
14
extra/dm_sheet/README.md
Normal file
14
extra/dm_sheet/README.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
# README #
|
||||
|
||||
### Documentation ###
|
||||
|
||||
Please see this page on the Aquila Consortium wiki: https://athos.iap.fr/wiki/index.php/ARES_Extras/dm_sheet
|
||||
|
||||
### Contributors ###
|
||||
|
||||
The main authors of this module are:
|
||||
|
||||
* Florent Leclercq
|
||||
* Guilhem Lavaux
|
||||
|
||||
To add more features, please contact these people, or submit pull requests.
|
6
extra/dm_sheet/libLSS/dm_sheet.cmake
Normal file
6
extra/dm_sheet/libLSS/dm_sheet.cmake
Normal file
|
@ -0,0 +1,6 @@
|
|||
SET(EXTRA_DM_SHEET ${CMAKE_SOURCE_DIR}/extra/dm_sheet)
|
||||
|
||||
SET(EXTRA_LIBLSS ${EXTRA_LIBLSS}
|
||||
${EXTRA_DM_SHEET}/libLSS/physics/dm_sheet/dm_sheet.cpp
|
||||
${EXTRA_DM_SHEET}/libLSS/physics/velocity/velocity_sic.cpp
|
||||
)
|
519
extra/dm_sheet/libLSS/physics/dm_sheet/dm_sheet.cpp
Normal file
519
extra/dm_sheet/libLSS/physics/dm_sheet/dm_sheet.cpp
Normal file
|
@ -0,0 +1,519 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./extra/dm_sheet/libLSS/physics/dm_sheet/dm_sheet.cpp
|
||||
Copyright (C) 2016-2018 Florent Leclercq <florent.leclercq@polytechnique.org>
|
||||
Copyright (C) 2018 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2019-2020 James Prideaux-Ghee <j.prideaux-ghee19@imperial.ac.uk>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <boost/multi_array.hpp>
|
||||
#include <Eigen/Dense>
|
||||
#include "libLSS/tools/console.hpp"
|
||||
#include "libLSS/tools/log_traits.hpp"
|
||||
#include "libLSS/tools/string_tools.hpp"
|
||||
#include "libLSS/tools/fused_array.hpp"
|
||||
#include "libLSS/physics/dm_sheet/dm_sheet.hpp"
|
||||
#include "libLSS/physics/dm_sheet/tools.hpp"
|
||||
#include "libLSS/physics/dm_sheet/tetrahedron_tools.hpp"
|
||||
|
||||
using namespace LibLSS;
|
||||
using namespace LibLSS::DM_Sheet;
|
||||
|
||||
///-------------------------------------------------------------------------------------
|
||||
/** @fn project_tetrahedron
|
||||
* Project a tetrahedron to the Eulerian grid
|
||||
* @param TetrahedronCoords input tetrahedron vertices coordinates
|
||||
* @param N0 mesh size x
|
||||
* @param N1 mesh size y
|
||||
* @param N2 mesh size z
|
||||
* @param L0 box size x
|
||||
* @param L1 box size y
|
||||
* @param L2 box size z
|
||||
* @param f functor to use for projection
|
||||
*/
|
||||
template <typename Functor>
|
||||
void project_tetrahedron(
|
||||
const double *TetrahedronCoords, const size_t N0, const size_t N1,
|
||||
const size_t N2, const double L0, const double L1, const double L2,
|
||||
Functor f) {
|
||||
const double d0 = L0 / N0;
|
||||
const double d1 = L1 / N1;
|
||||
const double d2 = L2 / N2;
|
||||
|
||||
double xA, yA, zA, xB, yB, zB, xC, yC, zC, xD, yD, zD;
|
||||
xA = TetrahedronCoords[0];
|
||||
yA = TetrahedronCoords[1];
|
||||
zA = TetrahedronCoords[2];
|
||||
xB = TetrahedronCoords[3];
|
||||
yB = TetrahedronCoords[4];
|
||||
zB = TetrahedronCoords[5];
|
||||
xC = TetrahedronCoords[6];
|
||||
yC = TetrahedronCoords[7];
|
||||
zC = TetrahedronCoords[8];
|
||||
xD = TetrahedronCoords[9];
|
||||
yD = TetrahedronCoords[10];
|
||||
zD = TetrahedronCoords[11];
|
||||
|
||||
double xmin = std::min({xA, xB, xC, xD}), xmax = std::max({xA, xB, xC, xD});
|
||||
double ymin = std::min({yA, yB, yC, yD}), ymax = std::max({yA, yB, yC, yD});
|
||||
double zmin = std::min({zA, zB, zC, zD}), zmax = std::max({zA, zB, zC, zD});
|
||||
|
||||
ssize_t imin = ssize_t(floor(xmin / d0)), imax = ssize_t(floor(xmax / d0));
|
||||
ssize_t jmin = ssize_t(floor(ymin / d1)), jmax = ssize_t(floor(ymax / d1));
|
||||
ssize_t kmin = ssize_t(floor(zmin / d2)), kmax = ssize_t(floor(zmax / d2));
|
||||
|
||||
Eigen::Matrix4d M;
|
||||
M << xA, yA, zA, 1., xB, yB, zB, 1., xC, yC, zC, 1., xD, yD, zD, 1.;
|
||||
double D0 = M.determinant();
|
||||
|
||||
// Check if this grid point is in the tetrahedron and project
|
||||
/// \note in this loop it is possible to have i>N0, j>N1, k>N2 !!
|
||||
for (ssize_t i = imin; i <= imax; i++)
|
||||
for (ssize_t j = jmin; j <= jmax; j++)
|
||||
for (ssize_t k = kmin; k <= kmax; k++) {
|
||||
// check the current grid point
|
||||
double x = i * d0;
|
||||
double y = j * d1;
|
||||
double z = k * d2;
|
||||
if (isInTetrahedron(TetrahedronCoords, D0, x, y, z)) {
|
||||
// important: check periodic boundary conditions here
|
||||
size_t igrid = p_mod(i, ssize_t(N0));
|
||||
size_t jgrid = p_mod(j, ssize_t(N1));
|
||||
size_t kgrid = p_mod(k, ssize_t(N2));
|
||||
|
||||
// interpolate with Shepard's method (1/distance^2 weights)
|
||||
double wA = 1 / ((x - xA) * (x - xA) + (y - yA) * (y - yA) +
|
||||
(z - zA) * (z - zA));
|
||||
double wB = 1 / ((x - xB) * (x - xB) + (y - yB) * (y - yB) +
|
||||
(z - zB) * (z - zB));
|
||||
double wC = 1 / ((x - xC) * (x - xC) + (y - yC) * (y - yC) +
|
||||
(z - zC) * (z - zC));
|
||||
double wD = 1 / ((x - xD) * (x - xD) + (y - yD) * (y - yD) +
|
||||
(z - zD) * (z - zD));
|
||||
double w = wA + wB + wC + wD;
|
||||
|
||||
f(igrid, jgrid, kgrid, wA, wB, wC, wD, w);
|
||||
}
|
||||
}
|
||||
} //project_tetrahedron
|
||||
///-------------------------------------------------------------------------------------
|
||||
static massparticleID_t get_NpM(const particleID_t NpF) {
|
||||
// There is exactly 24 times more mass tracers than flow tracers
|
||||
return massparticleID_t(24) * NpF;
|
||||
} //get_NpM
|
||||
///-------------------------------------------------------------------------------------
|
||||
/** @fn get_masstracers
|
||||
* Return a Snapshot *containing the mass tracers
|
||||
* @warning Take care to use the same type for flow tracers and mass tracers IDs in this function!
|
||||
*/
|
||||
void get_masstracers(
|
||||
const arrayID_view_t &flowtracers_Ids,
|
||||
const arrayPosition_view_t &flowtracers_positions, const double L0,
|
||||
const double L1, const double L2, const size_t Np0, const size_t Np1,
|
||||
const size_t Np2, arrayPosition_t &masstracers_positions) {
|
||||
const particleID_t NpF = flowtracers_positions.shape()[0];
|
||||
const massparticleID_t NpM = get_NpM(NpF);
|
||||
// Types should match here!
|
||||
|
||||
// Loop on flow tracers
|
||||
#pragma omp parallel for schedule(static)
|
||||
for (particleID_t mpF = 0; mpF < NpF; mpF++) {
|
||||
particleID_t Id = flowtracers_Ids[mpF];
|
||||
// Loop on the 6 tetrahedra for this particle
|
||||
for (int itet = 0; itet < 6; itet++) {
|
||||
particleID_t mpM, mpA, mpB, mpC, mpD;
|
||||
|
||||
// Get the indices of the 4 vertices
|
||||
particleID_t TetrahedronIndices[4];
|
||||
get_tetrahedron_indices(Id, itet, Np0, Np1, Np2, TetrahedronIndices);
|
||||
mpA = TetrahedronIndices[0];
|
||||
mpB = TetrahedronIndices[1];
|
||||
mpC = TetrahedronIndices[2];
|
||||
mpD = TetrahedronIndices[3];
|
||||
|
||||
// Get the coordinates
|
||||
double TetrahedronCoords[12];
|
||||
get_tetrahedron_coords(
|
||||
flowtracers_positions, mpA, mpB, mpC, mpD, L0, L1, L2,
|
||||
TetrahedronCoords);
|
||||
|
||||
// Loop on the 4 sides for this tetrahedron
|
||||
for (unsigned int iside = 0; iside < 4; iside++) {
|
||||
// Get the positions of the mass tracers
|
||||
mpM = 24 * mpF + 4 * itet + iside;
|
||||
double MassTracerCoords[3];
|
||||
get_masstracer_coords(TetrahedronCoords, iside, MassTracerCoords);
|
||||
|
||||
// check periodic boundary conditions here
|
||||
masstracers_positions[mpM][0] = p_mod(MassTracerCoords[0], L0);
|
||||
masstracers_positions[mpM][1] = p_mod(MassTracerCoords[1], L1);
|
||||
masstracers_positions[mpM][2] = p_mod(MassTracerCoords[2], L2);
|
||||
} //end loop on sides
|
||||
} //end loop on tetrahedra
|
||||
} //end loop on flow tracers
|
||||
} //get_masstracers
|
||||
///-------------------------------------------------------------------------------------
|
||||
/** @fn lagrangian_transport
|
||||
* Do the Lagrangian transport of various quantities
|
||||
*/
|
||||
template <
|
||||
typename ParticlePropertyArray, typename ApplyPropertyFunctor,
|
||||
typename WeightFunctor>
|
||||
void lagrangian_transport(
|
||||
const arrayID_view_t &flowtracers_Ids,
|
||||
const arrayPosition_view_t &flowtracers_positions,
|
||||
const ParticlePropertyArray &properties, WeightFunctor weighter,
|
||||
const double L0, const double L1, const double L2, const size_t Np0,
|
||||
const size_t Np1, const size_t Np2, const size_t N0, const size_t N1,
|
||||
const size_t N2, ApplyPropertyFunctor applier) {
|
||||
const double m = 1.0;
|
||||
const double d = L0 / Np0;
|
||||
const size_t N = N0 * N1 * N2;
|
||||
const particleID_t NpF = flowtracers_Ids.shape()[0];
|
||||
|
||||
Console::instance().print<LOG_VERBOSE>("Npf = " + to_string(NpF));
|
||||
|
||||
// loop on particles
|
||||
for (particleID_t mpF = 0; mpF < NpF; mpF++) {
|
||||
particleID_t Id = flowtracers_Ids[mpF];
|
||||
|
||||
// loop on the 6 tetrahedra for this particle
|
||||
for (unsigned int itet = 0; itet < 6; itet++) {
|
||||
particleID_t mpA, mpB, mpC, mpD;
|
||||
|
||||
// get the indices of the 4 vertices
|
||||
particleID_t TetrahedronIndices[4];
|
||||
get_tetrahedron_indices(Id, itet, Np0, Np1, Np2, TetrahedronIndices);
|
||||
mpA = TetrahedronIndices[0];
|
||||
mpB = TetrahedronIndices[1];
|
||||
mpC = TetrahedronIndices[2];
|
||||
mpD = TetrahedronIndices[3];
|
||||
|
||||
// get the coordinates
|
||||
double TetrahedronCoords[12];
|
||||
get_tetrahedron_coords(
|
||||
flowtracers_positions, mpA, mpB, mpC, mpD, L0, L1, L2,
|
||||
TetrahedronCoords);
|
||||
|
||||
// get the volume and mass
|
||||
double Vtet = get_tetrahedron_volume(TetrahedronCoords);
|
||||
double rhotet =
|
||||
m / (6 * std::abs(Vtet)); //equation (6) in Abel, Hahn & Kaehler 2012
|
||||
|
||||
// get weights for each vertex
|
||||
auto pA = weighter(properties[mpA], rhotet),
|
||||
pB = weighter(properties[mpB], rhotet),
|
||||
pC = weighter(properties[mpC], rhotet),
|
||||
pD = weighter(properties[mpD], rhotet);
|
||||
|
||||
// project tetrahedron
|
||||
project_tetrahedron(
|
||||
TetrahedronCoords, N0, N1, N2, L0, L1, L2,
|
||||
[&pA, &pB, &pC, &pD, &applier](
|
||||
size_t i, size_t j, size_t k, double wA, double wB, double wC,
|
||||
double wD, double w) {
|
||||
applier(i, j, k, pA, wA, pB, wB, pC, wC, pD, wD, w);
|
||||
});
|
||||
|
||||
} //end loop on tetrahedra
|
||||
} //end loop on particles
|
||||
} //lagrangian_transport
|
||||
|
||||
namespace LibLSS {
|
||||
namespace DM_Sheet {
|
||||
|
||||
void get_nbstreams_tetrahedra(
|
||||
arrayID_view_t flowtracers_Ids,
|
||||
arrayPosition_view_t flowtracers_positions, const double L0,
|
||||
const double L1, const double L2, const int Np0, const int Np1,
|
||||
const int Np2, const int N0, const int N1, const int N2,
|
||||
boost::multi_array_ref<double, 3> &nbstreams_grid) {
|
||||
auto mass_array =
|
||||
b_fused_idx<double, 2>([](int, int) -> double { return 1; });
|
||||
typedef decltype(mass_array[0]) Mass_t;
|
||||
|
||||
auto weighter = [](const Mass_t &, double rhotet) -> double {
|
||||
return 1.;
|
||||
};
|
||||
auto applier = [&nbstreams_grid](
|
||||
size_t i, size_t j, size_t k, double, double wA,
|
||||
double, double wB, double, double wC, double,
|
||||
double wD,
|
||||
double w) { nbstreams_grid[i][j][k] += 1.; };
|
||||
|
||||
lagrangian_transport(
|
||||
flowtracers_Ids, flowtracers_positions, mass_array, weighter, L0, L1,
|
||||
L2, Np0, Np1, Np2, N0, N1, N2, applier);
|
||||
} //get_nbstreams_tetrahedra
|
||||
|
||||
void get_density_tetrahedra(
|
||||
arrayID_view_t flowtracers_Ids,
|
||||
arrayPosition_view_t flowtracers_positions, const double L0,
|
||||
const double L1, const double L2, const int Np0, const int Np1,
|
||||
const int Np2, const int N0, const int N1, const int N2,
|
||||
boost::multi_array_ref<double, 3> &density_grid) {
|
||||
auto mass_array =
|
||||
b_fused_idx<double, 2>([](int, int) -> double { return 1; });
|
||||
typedef decltype(mass_array[0]) Mass_t;
|
||||
|
||||
auto weighter = [](const Mass_t &, double rhotet) -> double {
|
||||
return rhotet;
|
||||
};
|
||||
auto applier = [&density_grid](
|
||||
size_t i, size_t j, size_t k, double rho, double wA,
|
||||
double, double wB, double, double wC, double,
|
||||
double wD, double w) { density_grid[i][j][k] += rho; };
|
||||
|
||||
lagrangian_transport(
|
||||
flowtracers_Ids, flowtracers_positions, mass_array, weighter, L0, L1,
|
||||
L2, Np0, Np1, Np2, N0, N1, N2, applier);
|
||||
} //get_density_tetrahedra
|
||||
|
||||
void get_momenta_tetrahedra(
|
||||
arrayID_view_t flowtracers_Ids,
|
||||
arrayPosition_view_t flowtracers_positions,
|
||||
arrayVelocity_view_t flowtracers_velocities, const double L0,
|
||||
const double L1, const double L2, const int Np0, const int Np1,
|
||||
const int Np2, const int N0, const int N1, const int N2,
|
||||
boost::multi_array_ref<double, 4> &momenta_grid) {
|
||||
typedef decltype(flowtracers_velocities[0]) Flow_t;
|
||||
typedef std::tuple<Flow_t, double> TupleV;
|
||||
typedef TupleV const &TupleV_c;
|
||||
|
||||
auto weighter = [](Flow_t v, double rhotet) -> TupleV {
|
||||
return TupleV(v, rhotet);
|
||||
};
|
||||
auto applier = [&momenta_grid](
|
||||
size_t i, size_t j, size_t k, TupleV_c tA, double wA,
|
||||
TupleV_c tB, double wB, TupleV_c tC, double wC,
|
||||
TupleV_c tD, double wD, double w) {
|
||||
auto vg = momenta_grid[i][j][k];
|
||||
auto const &vA = std::get<0>(tA);
|
||||
auto const &vB = std::get<0>(tB);
|
||||
auto const &vC = std::get<0>(tC);
|
||||
auto const &vD = std::get<0>(tD);
|
||||
double rhotet_w = std::get<1>(tA) / w;
|
||||
|
||||
for (unsigned int l = 0; l < 3; l++)
|
||||
vg[l] +=
|
||||
rhotet_w * (vA[l] * wA + vB[l] * wB + vC[l] * wC + vD[l] * wD);
|
||||
};
|
||||
|
||||
lagrangian_transport(
|
||||
flowtracers_Ids, flowtracers_positions, flowtracers_velocities,
|
||||
weighter, L0, L1, L2, Np0, Np1, Np2, N0, N1, N2, applier);
|
||||
} //get_momenta_tetrahedra
|
||||
|
||||
void get_mass_and_momenta_tetrahedra(
|
||||
arrayID_view_t flowtracers_Ids,
|
||||
arrayPosition_view_t flowtracers_positions,
|
||||
arrayVelocity_view_t flowtracers_velocities, const double L0,
|
||||
const double L1, const double L2, const int Np0, const int Np1,
|
||||
const int Np2, const int N0, const int N1, const int N2,
|
||||
boost::multi_array_ref<double, 3> &density_grid,
|
||||
boost::multi_array_ref<double, 4> &momenta_grid) {
|
||||
typedef decltype(flowtracers_velocities[0]) Flow_t;
|
||||
typedef std::tuple<Flow_t, double> TupleV;
|
||||
typedef TupleV const &TupleV_c;
|
||||
|
||||
auto weighter = [](Flow_t v, double rhotet) -> TupleV {
|
||||
return TupleV(v, rhotet);
|
||||
};
|
||||
auto applier = [&density_grid, &momenta_grid](
|
||||
size_t i, size_t j, size_t k, TupleV_c tA, double wA,
|
||||
TupleV_c tB, double wB, TupleV_c tC, double wC,
|
||||
TupleV_c tD, double wD, double w) {
|
||||
auto vg = momenta_grid[i][j][k];
|
||||
auto const &vA = std::get<0>(tA);
|
||||
auto const &vB = std::get<0>(tB);
|
||||
auto const &vC = std::get<0>(tC);
|
||||
auto const &vD = std::get<0>(tD);
|
||||
double rhotet = std::get<1>(tA);
|
||||
double rhotet_w = rhotet / w;
|
||||
|
||||
for (unsigned int l = 0; l < 3; l++)
|
||||
vg[l] +=
|
||||
rhotet_w * (vA[l] * wA + vB[l] * wB + vC[l] * wC + vD[l] * wD);
|
||||
|
||||
density_grid[i][j][k] += rhotet;
|
||||
};
|
||||
|
||||
lagrangian_transport(
|
||||
flowtracers_Ids, flowtracers_positions, flowtracers_velocities,
|
||||
weighter, L0, L1, L2, Np0, Np1, Np2, N0, N1, N2, applier);
|
||||
} //get_mass_and_momenta_tetrahedra
|
||||
|
||||
void get_velocity_dispersion_tetrahedra(
|
||||
arrayID_view_t flowtracers_Ids,
|
||||
arrayPosition_view_t flowtracers_positions,
|
||||
arrayVelocity_view_t flowtracers_velocities, const double L0,
|
||||
const double L1, const double L2, const int Np0, const int Np1,
|
||||
const int Np2, const int N0, const int N1, const int N2,
|
||||
boost::multi_array_ref<double, 3> &nbstreams_grid,
|
||||
boost::multi_array_ref<double, 3> &density_grid,
|
||||
boost::multi_array_ref<double, 4> &momenta_grid,
|
||||
boost::multi_array_ref<double, 4> &dispersion_grid) {
|
||||
typedef decltype(flowtracers_velocities[0]) Flow_t;
|
||||
typedef std::tuple<Flow_t, double> TupleV;
|
||||
typedef TupleV const &TupleV_c;
|
||||
|
||||
auto weighter = [](Flow_t v, double rhotet) -> TupleV {
|
||||
return TupleV(v, rhotet);
|
||||
};
|
||||
auto applier = [&momenta_grid, &dispersion_grid](
|
||||
size_t i, size_t j, size_t k, TupleV_c tA, double wA,
|
||||
TupleV_c tB, double wB, TupleV_c tC, double wC,
|
||||
TupleV_c tD, double wD, double w) {
|
||||
auto vg = momenta_grid[i][j][k];
|
||||
auto vp = dispersion_grid[i][j][k];
|
||||
auto const &vA = std::get<0>(tA);
|
||||
auto const &vB = std::get<0>(tB);
|
||||
auto const &vC = std::get<0>(tC);
|
||||
auto const &vD = std::get<0>(tD);
|
||||
double rhotet = std::get<1>(tA);
|
||||
double rhotet_w = rhotet / w;
|
||||
|
||||
for (unsigned int l = 0; l < 3; l++) {
|
||||
vg[l] +=
|
||||
rhotet_w * (vA[l] * wA + vB[l] * wB + vC[l] * wC + vD[l] * wD);
|
||||
}
|
||||
|
||||
vp[0] += rhotet_w * (vA[0] * vA[0] * wA + vB[0] * vB[0] * wB +
|
||||
vC[0] * vC[0] * wC + vD[0] * vD[0] * wD);
|
||||
vp[1] += rhotet_w * (vA[1] * vA[1] * wA + vB[1] * vB[1] * wB +
|
||||
vC[1] * vC[1] * wC + vD[1] * vD[1] * wD);
|
||||
vp[2] += rhotet_w * (vA[2] * vA[2] * wA + vB[2] * vB[2] * wB +
|
||||
vC[2] * vC[2] * wC + vD[2] * vD[2] * wD);
|
||||
vp[3] += rhotet_w * (vA[0] * vA[1] * wA + vB[0] * vB[1] * wB +
|
||||
vC[0] * vC[1] * wC + vD[0] * vD[1] * wD);
|
||||
vp[4] += rhotet_w * (vA[0] * vA[2] * wA + vB[0] * vB[2] * wB +
|
||||
vC[0] * vC[2] * wC + vD[0] * vD[2] * wD);
|
||||
vp[5] += rhotet_w * (vA[1] * vA[2] * wA + vB[1] * vB[2] * wB +
|
||||
vC[1] * vC[2] * wC + vD[1] * vD[2] * wD);
|
||||
};
|
||||
|
||||
lagrangian_transport(
|
||||
flowtracers_Ids, flowtracers_positions, flowtracers_velocities,
|
||||
weighter, L0, L1, L2, Np0, Np1, Np2, N0, N1, N2, applier);
|
||||
|
||||
} // get_velocity_dispersion_tetrahedra
|
||||
|
||||
void get_nbstreams_mass_and_momenta_tetrahedra(
|
||||
arrayID_view_t flowtracers_Ids,
|
||||
arrayPosition_view_t flowtracers_positions,
|
||||
arrayVelocity_view_t flowtracers_velocities, const double L0,
|
||||
const double L1, const double L2, const int Np0, const int Np1,
|
||||
const int Np2, const int N0, const int N1, const int N2,
|
||||
boost::multi_array_ref<double, 3> &nbstreams_grid,
|
||||
boost::multi_array_ref<double, 3> &density_grid,
|
||||
boost::multi_array_ref<double, 4> &momenta_grid) {
|
||||
typedef decltype(flowtracers_velocities[0]) Flow_t;
|
||||
typedef std::tuple<Flow_t, double> TupleV;
|
||||
typedef TupleV const &TupleV_c;
|
||||
|
||||
auto weighter = [](Flow_t v, double rhotet) -> TupleV {
|
||||
return TupleV(v, rhotet);
|
||||
};
|
||||
auto applier = [&nbstreams_grid, &density_grid, &momenta_grid](
|
||||
size_t i, size_t j, size_t k, TupleV_c tA, double wA,
|
||||
TupleV_c tB, double wB, TupleV_c tC, double wC,
|
||||
TupleV_c tD, double wD, double w) {
|
||||
auto vg = momenta_grid[i][j][k];
|
||||
auto const &vA = std::get<0>(tA);
|
||||
auto const &vB = std::get<0>(tB);
|
||||
auto const &vC = std::get<0>(tC);
|
||||
auto const &vD = std::get<0>(tD);
|
||||
double rhotet = std::get<1>(tA);
|
||||
double rhotet_w = rhotet / w;
|
||||
|
||||
for (unsigned int l = 0; l < 3; l++)
|
||||
vg[l] +=
|
||||
rhotet_w * (vA[l] * wA + vB[l] * wB + vC[l] * wC + vD[l] * wD);
|
||||
|
||||
density_grid[i][j][k] += rhotet;
|
||||
nbstreams_grid[i][j][k] += 1.;
|
||||
};
|
||||
|
||||
lagrangian_transport(
|
||||
flowtracers_Ids, flowtracers_positions, flowtracers_velocities,
|
||||
weighter, L0, L1, L2, Np0, Np1, Np2, N0, N1, N2, applier);
|
||||
} //get_nbstreams_mass_and_momenta_tetrahedra
|
||||
|
||||
//get_nbstreams_mass_momenta_and_velocity_dispersion_tetrahedra
|
||||
|
||||
void get_nbstreams_mass_momenta_and_velocity_dispersion_tetrahedra(
|
||||
arrayID_view_t flowtracers_Ids,
|
||||
arrayPosition_view_t flowtracers_positions,
|
||||
arrayVelocity_view_t flowtracers_velocities, const double L0,
|
||||
const double L1, const double L2, const int Np0, const int Np1,
|
||||
const int Np2, const int N0, const int N1, const int N2,
|
||||
boost::multi_array_ref<double, 3> &nbstreams_grid,
|
||||
boost::multi_array_ref<double, 3> &density_grid,
|
||||
boost::multi_array_ref<double, 4> &momenta_grid,
|
||||
boost::multi_array_ref<double, 4> &dispersion_grid) {
|
||||
typedef decltype(flowtracers_velocities[0]) Flow_t;
|
||||
typedef std::tuple<Flow_t, double> TupleV;
|
||||
typedef TupleV const &TupleV_c;
|
||||
|
||||
auto weighter = [](Flow_t v, double rhotet) -> TupleV {
|
||||
return TupleV(v, rhotet);
|
||||
};
|
||||
auto applier = [&nbstreams_grid, &density_grid, &momenta_grid,
|
||||
&dispersion_grid](
|
||||
size_t i, size_t j, size_t k, TupleV_c tA, double wA,
|
||||
TupleV_c tB, double wB, TupleV_c tC, double wC,
|
||||
TupleV_c tD, double wD, double w) {
|
||||
auto vg = momenta_grid[i][j][k];
|
||||
auto vp = dispersion_grid[i][j][k];
|
||||
auto const &vA = std::get<0>(tA);
|
||||
auto const &vB = std::get<0>(tB);
|
||||
auto const &vC = std::get<0>(tC);
|
||||
auto const &vD = std::get<0>(tD);
|
||||
double rhotet = std::get<1>(tA);
|
||||
double rhotet_w = rhotet / w;
|
||||
|
||||
for (unsigned int l = 0; l < 3; l++) {
|
||||
vg[l] +=
|
||||
rhotet_w * (vA[l] * wA + vB[l] * wB + vC[l] * wC + vD[l] * wD);
|
||||
}
|
||||
|
||||
vp[0] += rhotet_w * (vA[0] * vA[0] * wA + vB[0] * vB[0] * wB +
|
||||
vC[0] * vC[0] * wC + vD[0] * vD[0] * wD);
|
||||
vp[1] += rhotet_w * (vA[1] * vA[1] * wA + vB[1] * vB[1] * wB +
|
||||
vC[1] * vC[1] * wC + vD[1] * vD[1] * wD);
|
||||
vp[2] += rhotet_w * (vA[2] * vA[2] * wA + vB[2] * vB[2] * wB +
|
||||
vC[2] * vC[2] * wC + vD[2] * vD[2] * wD);
|
||||
vp[3] += rhotet_w * (vA[0] * vA[1] * wA + vB[0] * vB[1] * wB +
|
||||
vC[0] * vC[1] * wC + vD[0] * vD[1] * wD);
|
||||
vp[4] += rhotet_w * (vA[0] * vA[2] * wA + vB[0] * vB[2] * wB +
|
||||
vC[0] * vC[2] * wC + vD[0] * vD[2] * wD);
|
||||
vp[5] += rhotet_w * (vA[1] * vA[2] * wA + vB[1] * vB[2] * wB +
|
||||
vC[1] * vC[2] * wC + vD[1] * vD[2] * wD);
|
||||
|
||||
density_grid[i][j][k] += rhotet;
|
||||
nbstreams_grid[i][j][k] += 1.;
|
||||
};
|
||||
|
||||
lagrangian_transport(
|
||||
flowtracers_Ids, flowtracers_positions, flowtracers_velocities,
|
||||
weighter, L0, L1, L2, Np0, Np1, Np2, N0, N1, N2, applier);
|
||||
} //get_nbstreams_mass_momenta_and_velocity_dispersion_tetrahedra
|
||||
|
||||
} // namespace DM_Sheet
|
||||
} // namespace LibLSS
|
||||
|
||||
// ARES TAG: authors_num = 3
|
||||
// ARES TAG: name(0) = Florent Leclercq
|
||||
// ARES TAG: year(0) = 2016-2018
|
||||
// ARES TAG: email(0) = florent.leclercq@polytechnique.org
|
||||
// ARES TAG: name(1) = Guilhem Lavaux
|
||||
// ARES TAG: year(1) = 2018
|
||||
// ARES TAG: email(1) = guilhem.lavaux@iap.fr
|
||||
// ARES TAG: name(2) = James Prideaux-Ghee
|
||||
// ARES TAG: year(2) = 2019-2020
|
||||
// ARES TAG: email(2) = j.prideaux-ghee19@imperial.ac.uk
|
||||
|
178
extra/dm_sheet/libLSS/physics/dm_sheet/dm_sheet.hpp
Normal file
178
extra/dm_sheet/libLSS/physics/dm_sheet/dm_sheet.hpp
Normal file
|
@ -0,0 +1,178 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./extra/dm_sheet/libLSS/physics/dm_sheet/dm_sheet.hpp
|
||||
Copyright (C) 2016-2018 Florent Leclercq <florent.leclercq@polytechnique.org>
|
||||
Copyright (C) 2018 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2019-2020 James Prideaux-Ghee <j.prideaux-ghee19@imperial.ac.uk>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_DMSHEET_HPP
|
||||
# define __LIBLSS_DMSHEET_HPP
|
||||
|
||||
# include <boost/multi_array.hpp>
|
||||
# include "libLSS/physics/dm_sheet/tetrahedron_tools.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
namespace DM_Sheet {
|
||||
typedef boost::multi_array_ref<particleID_t, 1> arrayID_t;
|
||||
typedef boost::multi_array_ref<double, 2> arrayPosition_t;
|
||||
typedef boost::multi_array_ref<double, 2> arrayVelocity_t;
|
||||
typedef arrayID_t::const_array_view<1>::type arrayID_view_t;
|
||||
typedef arrayPosition_t::const_array_view<2>::type arrayPosition_view_t;
|
||||
typedef arrayVelocity_t::const_array_view<2>::type arrayVelocity_view_t;
|
||||
|
||||
/**
|
||||
* This function computes projects tetrahedra on the provided density grid
|
||||
* with the indicated flow tracers.
|
||||
*
|
||||
* @param flowtracers_Ids lagrangian ids of the flowtracers
|
||||
* @param flowtracers_positions Eulerian position of the flowtracers
|
||||
* @param L0 first dimension of the box
|
||||
* @param L1 second dimension of the box
|
||||
* @param L2 third dimension of hte box
|
||||
* @param Np0 first dimension of the Lagrangian grid
|
||||
* @param Np1 second dimension of the Lagrangian grid
|
||||
* @param Np2 third dimension of the Lagrangian grid
|
||||
* @param N0 first dimension of the expected Eulerian grid
|
||||
* @param N1 second dimension of the expected Eulerian grid
|
||||
* @param N2 third dimension of the expected Eulerian grid
|
||||
* @param density_grid unnormalized mass density
|
||||
*/
|
||||
void get_nbstreams_tetrahedra(
|
||||
arrayID_view_t flowtracers_Ids,
|
||||
arrayPosition_view_t flowtracers_positions, const double L0,
|
||||
const double L1, const double L2, const int Np0, const int Np1,
|
||||
const int Np2, const int N0, const int N1, const int N2,
|
||||
boost::multi_array_ref<double, 3> &nbstreams_grid);
|
||||
|
||||
/**
|
||||
* This function computes the density field from tetrahedra on the provided density grid
|
||||
* with the indicated flow tracers.
|
||||
*
|
||||
* @param flowtracers_Ids lagrangian ids of the flowtracers
|
||||
* @param flowtracers_positions Eulerian position of the flowtracers
|
||||
* @param L0 first dimension of the box
|
||||
* @param L1 second dimension of the box
|
||||
* @param L2 third dimension of hte box
|
||||
* @param Np0 first dimension of the Lagrangian grid
|
||||
* @param Np1 second dimension of the Lagrangian grid
|
||||
* @param Np2 third dimension of the Lagrangian grid
|
||||
* @param N0 first dimension of the expected Eulerian grid
|
||||
* @param N1 second dimension of the expected Eulerian grid
|
||||
* @param N2 third dimension of the expected Eulerian grid
|
||||
* @param density_grid unnormalized mass density
|
||||
*/
|
||||
void get_density_tetrahedra(
|
||||
arrayID_view_t flowtracers_Ids,
|
||||
arrayPosition_view_t flowtracers_positions, const double L0,
|
||||
const double L1, const double L2, const int Np0, const int Np1,
|
||||
const int Np2, const int N0, const int N1, const int N2,
|
||||
boost::multi_array_ref<double, 3> &density_grid);
|
||||
|
||||
/**
|
||||
* This function computes the \emph{momenta} from tetrahedra
|
||||
* on the provided momenta grid with the indicated flow tracers.
|
||||
*
|
||||
* @param flowtracers_Ids lagrangian ids of the flowtracers
|
||||
* @param flowtracers_positions Eulerian position of the flowtracers
|
||||
* @param L0 first dimension of the box
|
||||
* @param L1 second dimension of the box
|
||||
* @param L2 third dimension of hte box
|
||||
* @param Np0 first dimension of the Lagrangian grid
|
||||
* @param Np1 second dimension of the Lagrangian grid
|
||||
* @param Np2 third dimension of the Lagrangian grid
|
||||
* @param N0 first dimension of the expected Eulerian grid
|
||||
* @param N1 second dimension of the expected Eulerian grid
|
||||
* @param N2 third dimension of the expected Eulerian grid
|
||||
* @param momenta_grid output momenta grid
|
||||
*/
|
||||
void get_momenta_tetrahedra(
|
||||
arrayID_view_t flowtracers_Ids,
|
||||
arrayPosition_view_t flowtracers_positions,
|
||||
arrayVelocity_view_t flowtracers_velocities, const double L0,
|
||||
const double L1, const double L2, const int Np0, const int Np1,
|
||||
const int Np2, const int N0, const int N1, const int N2,
|
||||
boost::multi_array_ref<double, 4> &momenta_grid);
|
||||
|
||||
/**
|
||||
* This function computes density and \emph{momenta} fields from tetrahedra
|
||||
* on the provided grids with the indicated flow tracers.
|
||||
*
|
||||
* @param flowtracers_Ids lagrangian ids of the flowtracers
|
||||
* @param flowtracers_positions Eulerian position of the flowtracers
|
||||
* @param L0 first dimension of the box
|
||||
* @param L1 second dimension of the box
|
||||
* @param L2 third dimension of hte box
|
||||
* @param Np0 first dimension of the Lagrangian grid
|
||||
* @param Np1 second dimension of the Lagrangian grid
|
||||
* @param Np2 third dimension of the Lagrangian grid
|
||||
* @param N0 first dimension of the expected Eulerian grid
|
||||
* @param N1 second dimension of the expected Eulerian grid
|
||||
* @param N2 third dimension of the expected Eulerian grid
|
||||
* @param density_grid output mass density
|
||||
* @param momenta_grid output momenta grid
|
||||
*/
|
||||
void get_mass_and_momenta_tetrahedra(
|
||||
arrayID_view_t flowtracers_Ids,
|
||||
arrayPosition_view_t flowtracers_positions,
|
||||
arrayVelocity_view_t flowtracers_velocities, const double L0,
|
||||
const double L1, const double L2, const int Np0, const int Np1,
|
||||
const int Np2, const int N0, const int N1, const int N2,
|
||||
boost::multi_array_ref<double, 3> &density_grid,
|
||||
boost::multi_array_ref<double, 4> &momenta_grid);
|
||||
|
||||
void get_nbstreams_mass_and_momenta_tetrahedra(
|
||||
arrayID_view_t flowtracers_Ids,
|
||||
arrayPosition_view_t flowtracers_positions,
|
||||
arrayVelocity_view_t flowtracers_velocities, const double L0,
|
||||
const double L1, const double L2, const int Np0, const int Np1,
|
||||
const int Np2, const int N0, const int N1, const int N2,
|
||||
boost::multi_array_ref<double, 3> &nbstreams_grid,
|
||||
boost::multi_array_ref<double, 3> &density_grid,
|
||||
boost::multi_array_ref<double, 4> &momenta_grid);
|
||||
|
||||
void get_velocity_dispersion_tetrahedra(
|
||||
arrayID_view_t flowtracers_Ids,
|
||||
arrayPosition_view_t flowtracers_positions,
|
||||
arrayVelocity_view_t flowtracers_velocities, const double L0,
|
||||
const double L1, const double L2, const int Np0, const int Np1,
|
||||
const int Np2, const int N0, const int N1, const int N2,
|
||||
boost::multi_array_ref<double, 3> &
|
||||
nbstreams_grid, // Introduce a 3d array with the no. dm streams per point.
|
||||
boost::multi_array_ref<double, 3> &
|
||||
density_grid, // Introduce a 3d array with the density at each point
|
||||
boost::multi_array_ref<double, 4> &
|
||||
momenta_grid, // Introduce a 4d array, with the velocity components at each point
|
||||
boost::multi_array_ref<double, 4> &
|
||||
dispersion_grid); // Introduce a 5d array with the velocity dispersion tensor
|
||||
|
||||
void get_nbstreams_mass_momenta_and_velocity_dispersion_tetrahedra(
|
||||
arrayID_view_t flowtracers_Ids,
|
||||
arrayPosition_view_t flowtracers_positions,
|
||||
arrayVelocity_view_t flowtracers_velocities, const double L0,
|
||||
const double L1, const double L2, const int Np0, const int Np1,
|
||||
const int Np2, const int N0, const int N1, const int N2,
|
||||
boost::multi_array_ref<double, 3> &nbstreams_grid,
|
||||
boost::multi_array_ref<double, 3> &density_grid,
|
||||
boost::multi_array_ref<double, 4> &momenta_grid,
|
||||
boost::multi_array_ref<double, 4> &dispersion_grid);
|
||||
|
||||
} // namespace DM_Sheet
|
||||
|
||||
} // namespace LibLSS
|
||||
|
||||
#endif
|
||||
// ARES TAG: authors_num = 3
|
||||
// ARES TAG: name(0) = Florent Leclercq
|
||||
// ARES TAG: year(0) = 2016-2018
|
||||
// ARES TAG: email(0) = florent.leclercq@polytechnique.org
|
||||
// ARES TAG: name(1) = Guilhem Lavaux
|
||||
// ARES TAG: year(1) = 2018
|
||||
// ARES TAG: email(1) = guilhem.lavaux@iap.fr
|
||||
// ARES TAG: name(2) = James Prideaux-Ghee
|
||||
// ARES TAG: year(2) = 2019-2020
|
||||
// ARES TAG: email(2) = j.prideaux-ghee19@imperial.ac.uk
|
||||
#pragma once
|
380
extra/dm_sheet/libLSS/physics/dm_sheet/tetrahedron_tools.hpp
Normal file
380
extra/dm_sheet/libLSS/physics/dm_sheet/tetrahedron_tools.hpp
Normal file
|
@ -0,0 +1,380 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./extra/dm_sheet/libLSS/physics/dm_sheet/tetrahedron_tools.hpp
|
||||
Copyright (C) 2016-2018 Florent Leclercq <florent.leclercq@polytechnique.org>
|
||||
Copyright (C) 2018 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_DMSHEET_TETRAHEDRON_TOOLS_HPP
|
||||
# define __LIBLSS_DMSHEET_TETRAHEDRON_TOOLS_HPP
|
||||
|
||||
# include <array>
|
||||
# include <Eigen/Dense>
|
||||
# include "libLSS/physics/dm_sheet/tools.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
namespace DM_Sheet {
|
||||
typedef size_t particleID_t;
|
||||
typedef size_t massparticleID_t;
|
||||
#if defined(__GNUC__) && !(defined(__clang__) || defined(__INTEL_COMPILER))
|
||||
static constexpr double INV_SQRT_5 = 1.0 / std::sqrt(5.0);
|
||||
static constexpr double ONE_MINUS_INV_SQRT_5 = 1 - 1.0 / std::sqrt(5.0);
|
||||
#else
|
||||
static const double INV_SQRT_5 = 1.0 / std::sqrt(5.0);
|
||||
static const double ONE_MINUS_INV_SQRT_5 = 1 - 1.0 / std::sqrt(5.0);
|
||||
#endif
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
/** @fn get_Lagrangian_indices
|
||||
* Get indices on the Lagrangian grid from particle Id
|
||||
* @param Id particle id
|
||||
* @param Np0 particle mesh size x
|
||||
* @param Np1 particle mesh size y
|
||||
* @param Np2 particle mesh size z
|
||||
* @param indices output indices
|
||||
* \warning Assumes row major!
|
||||
*/
|
||||
static inline void get_Lagrangian_indices(
|
||||
const particleID_t Id, const size_t Np0, const size_t Np1,
|
||||
const size_t Np2, std::array<size_t, 3> &indices) {
|
||||
// assumes Id = k+Np2*(j+Np1*i)
|
||||
size_t i = (Id / (Np1 * Np2)) % Np0;
|
||||
size_t j = ((Id - Np1 * Np2 * i) / Np2) % Np1;
|
||||
size_t k = ((Id - Np2 * j - Np2 * Np1 * i)) % Np2;
|
||||
|
||||
indices[0] = i;
|
||||
indices[1] = j;
|
||||
indices[2] = k;
|
||||
} //get_Lagrangian_indices
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
/** @fn get_index
|
||||
* Get mapping from 3D to 1D array
|
||||
* @param i index x
|
||||
* @param j index y
|
||||
* @param k index z
|
||||
* @param N0 array size x
|
||||
* @param N1 array size y
|
||||
* @param N2 array size z
|
||||
* @return index
|
||||
* \warning Assumes row major!
|
||||
*/
|
||||
static inline size_t get_index(
|
||||
const int i, const int j, const int k, const int, const int N1,
|
||||
const int N2) {
|
||||
return size_t(k + N2 * (j + N1 * i));
|
||||
} //get_index
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
/** @fn get_Lagrangian_Id
|
||||
* Get particle Id from indices on the Lagrangian grid
|
||||
* @param mp0 index x
|
||||
* @param mp1 index y
|
||||
* @param mp2 index z
|
||||
* @param Np0 particle mesh size x
|
||||
* @param Np1 particle mesh size y
|
||||
* @param Np2 particle mesh size z
|
||||
* @return particle id
|
||||
* \warning Assumes row major!
|
||||
*/
|
||||
static inline particleID_t get_Lagrangian_Id(
|
||||
const size_t mp0, const size_t mp1, const size_t mp2, const size_t Np0,
|
||||
const size_t Np1, const size_t Np2) {
|
||||
return particleID_t(get_index(mp0, mp1, mp2, Np0, Np1, Np2));
|
||||
} //get_Lagrangian_Id
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
/** @fn get_tetrahedron_indices
|
||||
* Get the particle indices of a tetrahedron
|
||||
* @param Id particle id
|
||||
* @param itet the id of the tetrahedron (0 to 5)
|
||||
* @param Np0 particle mesh size x
|
||||
* @param Np1 particle mesh size y
|
||||
* @param Np2 particle mesh size z
|
||||
* @param TetrahedronIndices output tetrahedron particle indices
|
||||
*/
|
||||
static inline void get_tetrahedron_indices(
|
||||
const particleID_t Id, const size_t itet, const size_t Np0,
|
||||
const size_t Np1, const size_t Np2, particleID_t *TetrahedronIndices) {
|
||||
std::array<size_t, 3> indices;
|
||||
get_Lagrangian_indices(Id, Np0, Np1, Np2, indices);
|
||||
size_t i = indices[0];
|
||||
size_t j = indices[1];
|
||||
size_t k = indices[2];
|
||||
size_t ii = (i + 1) % Np0;
|
||||
size_t jj = (j + 1) % Np1;
|
||||
size_t kk = (k + 1) % Np2;
|
||||
|
||||
particleID_t mpA, mpB, mpC, mpD;
|
||||
|
||||
switch (itet) {
|
||||
case 0:
|
||||
// Tetrahedron 1: (0,1,3,4)
|
||||
mpA = get_Lagrangian_Id(i, j, k, Np0, Np1, Np2); //0
|
||||
mpB = get_Lagrangian_Id(ii, j, k, Np0, Np1, Np2); //1
|
||||
mpC = get_Lagrangian_Id(i, jj, k, Np0, Np1, Np2); //3
|
||||
mpD = get_Lagrangian_Id(i, j, kk, Np0, Np1, Np2); //4
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Tetrahedron 2: (1,3,4,7)
|
||||
mpA = get_Lagrangian_Id(ii, j, k, Np0, Np1, Np2); //1
|
||||
mpB = get_Lagrangian_Id(i, jj, k, Np0, Np1, Np2); //3
|
||||
mpC = get_Lagrangian_Id(i, j, kk, Np0, Np1, Np2); //4
|
||||
mpD = get_Lagrangian_Id(i, jj, kk, Np0, Np1, Np2); //7
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Tetrahedron 3: (1,4,5,7)
|
||||
mpA = get_Lagrangian_Id(ii, j, k, Np0, Np1, Np2); //1
|
||||
mpB = get_Lagrangian_Id(i, j, kk, Np0, Np1, Np2); //4
|
||||
mpC = get_Lagrangian_Id(ii, j, kk, Np0, Np1, Np2); //5
|
||||
mpD = get_Lagrangian_Id(i, jj, kk, Np0, Np1, Np2); //7
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// Tetrahedron 4: (1,2,5,7)
|
||||
mpA = get_Lagrangian_Id(ii, j, k, Np0, Np1, Np2); //1
|
||||
mpB = get_Lagrangian_Id(ii, jj, k, Np0, Np1, Np2); //2
|
||||
mpC = get_Lagrangian_Id(ii, j, kk, Np0, Np1, Np2); //5
|
||||
mpD = get_Lagrangian_Id(i, jj, kk, Np0, Np1, Np2); //7
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// Tetrahedron 5: (1,2,3,7)
|
||||
mpA = get_Lagrangian_Id(ii, j, k, Np0, Np1, Np2); //1
|
||||
mpB = get_Lagrangian_Id(ii, jj, k, Np0, Np1, Np2); //2
|
||||
mpC = get_Lagrangian_Id(i, jj, k, Np0, Np1, Np2); //3
|
||||
mpD = get_Lagrangian_Id(i, jj, kk, Np0, Np1, Np2); //7
|
||||
break;
|
||||
|
||||
case 5:
|
||||
// Tetrahedron 6: (2,5,6,7)
|
||||
mpA = get_Lagrangian_Id(ii, jj, k, Np0, Np1, Np2); //2
|
||||
mpB = get_Lagrangian_Id(ii, j, kk, Np0, Np1, Np2); //5
|
||||
mpC = get_Lagrangian_Id(ii, jj, kk, Np0, Np1, Np2); //6
|
||||
mpD = get_Lagrangian_Id(i, jj, kk, Np0, Np1, Np2); //7
|
||||
break;
|
||||
}
|
||||
|
||||
TetrahedronIndices[0] = mpA;
|
||||
TetrahedronIndices[1] = mpB;
|
||||
TetrahedronIndices[2] = mpC;
|
||||
TetrahedronIndices[3] = mpD;
|
||||
} //get_tetrahedron_indices
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
/** @fn get_tetrahedron_coords
|
||||
* Get physical coordinates of the tetrahedron vertices
|
||||
* @param positions particles' positions
|
||||
* @param mpA particle Id first vertex
|
||||
* @param mpB particle Id second vertex
|
||||
* @param mpC particle Id third vertex
|
||||
* @param mpD particle Id fourth vertex
|
||||
* @param TetrahedronCoords output tetrahedron vertices coordinates
|
||||
*/
|
||||
template <typename ArrayPosition>
|
||||
static inline void get_tetrahedron_coords(
|
||||
const ArrayPosition &positions, const size_t mpA, const size_t mpB,
|
||||
const size_t mpC, const size_t mpD, const double L0, const double L1,
|
||||
const double L2, double *TetrahedronCoords) {
|
||||
double xA = positions[mpA][0], yA = positions[mpA][1],
|
||||
zA = positions[mpA][2];
|
||||
double xB = positions[mpB][0], yB = positions[mpB][1],
|
||||
zB = positions[mpB][2];
|
||||
double xC = positions[mpC][0], yC = positions[mpC][1],
|
||||
zC = positions[mpC][2];
|
||||
double xD = positions[mpD][0], yD = positions[mpD][1],
|
||||
zD = positions[mpD][2];
|
||||
|
||||
// Correction for periodic boundary conditions
|
||||
double xmax = std::max({xA, xB, xC, xD});
|
||||
periodic_boundary_correct(xmax, xA, L0);
|
||||
periodic_boundary_correct(xmax, xB, L0);
|
||||
periodic_boundary_correct(xmax, xC, L0);
|
||||
periodic_boundary_correct(xmax, xD, L0);
|
||||
|
||||
double ymax = std::max({yA, yB, yC, yD});
|
||||
periodic_boundary_correct(ymax, yA, L1);
|
||||
periodic_boundary_correct(ymax, yB, L1);
|
||||
periodic_boundary_correct(ymax, yC, L1);
|
||||
periodic_boundary_correct(ymax, yD, L1);
|
||||
|
||||
double zmax = std::max({zA, zB, zC, zD});
|
||||
periodic_boundary_correct(zmax, zA, L2);
|
||||
periodic_boundary_correct(zmax, zB, L2);
|
||||
periodic_boundary_correct(zmax, zC, L2);
|
||||
periodic_boundary_correct(zmax, zD, L2);
|
||||
|
||||
TetrahedronCoords[0] = xA;
|
||||
TetrahedronCoords[1] = yA;
|
||||
TetrahedronCoords[2] = zA;
|
||||
TetrahedronCoords[3] = xB;
|
||||
TetrahedronCoords[4] = yB;
|
||||
TetrahedronCoords[5] = zB;
|
||||
TetrahedronCoords[6] = xC;
|
||||
TetrahedronCoords[7] = yC;
|
||||
TetrahedronCoords[8] = zC;
|
||||
TetrahedronCoords[9] = xD;
|
||||
TetrahedronCoords[10] = yD;
|
||||
TetrahedronCoords[11] = zD;
|
||||
} //get_tetrahedron_coords
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
/** @fn get_tetrahedron_volume
|
||||
* Get volume of a tetrahedron
|
||||
* @param TetrahedronCoords input tetrahedron vertices positions
|
||||
* @return volume in UnitLength**3 (typically (Mpc/h)**3)
|
||||
*/
|
||||
static inline double
|
||||
get_tetrahedron_volume(const double *TetrahedronCoords) {
|
||||
double xA, yA, zA, xB, yB, zB, xC, yC, zC, xD, yD, zD;
|
||||
xA = TetrahedronCoords[0];
|
||||
yA = TetrahedronCoords[1];
|
||||
zA = TetrahedronCoords[2];
|
||||
xB = TetrahedronCoords[3];
|
||||
yB = TetrahedronCoords[4];
|
||||
zB = TetrahedronCoords[5];
|
||||
xC = TetrahedronCoords[6];
|
||||
yC = TetrahedronCoords[7];
|
||||
zC = TetrahedronCoords[8];
|
||||
xD = TetrahedronCoords[9];
|
||||
yD = TetrahedronCoords[10];
|
||||
zD = TetrahedronCoords[11];
|
||||
|
||||
// triple scalar product of the vectors
|
||||
// a factor of 6 because the cube is tessellated into 6 tetrahedra
|
||||
// (section 2.2 in Abel, Hahn & Kaehler 2012)
|
||||
Eigen::Matrix3d M;
|
||||
M << xB - xA, xC - xA, xD - xA,
|
||||
yB - yA, yC - yA, yD - yA,
|
||||
zB - zA, zC - zA, zD - zA;
|
||||
return (double)M.determinant() / 6.;
|
||||
|
||||
} //get_tetrahedron_volume
|
||||
|
||||
///-------------------------------------------------------------------------------------
|
||||
/** @fn isInTetrahedron
|
||||
* Check if a spatial position is inside a tetrahedron
|
||||
* @param TetrahedronCoords input tetrahedron vertices coordinates
|
||||
* @param xP position x
|
||||
* @param yP position y
|
||||
* @param zP position z
|
||||
*/
|
||||
static bool isInTetrahedron(
|
||||
const double *TetrahedronCoords, const double D0, const double xP,
|
||||
const double yP, const double zP) {
|
||||
double xA, yA, zA, xB, yB, zB, xC, yC, zC, xD, yD, zD;
|
||||
xA = TetrahedronCoords[0];
|
||||
yA = TetrahedronCoords[1];
|
||||
zA = TetrahedronCoords[2];
|
||||
xB = TetrahedronCoords[3];
|
||||
yB = TetrahedronCoords[4];
|
||||
zB = TetrahedronCoords[5];
|
||||
xC = TetrahedronCoords[6];
|
||||
yC = TetrahedronCoords[7];
|
||||
zC = TetrahedronCoords[8];
|
||||
xD = TetrahedronCoords[9];
|
||||
yD = TetrahedronCoords[10];
|
||||
zD = TetrahedronCoords[11];
|
||||
|
||||
Eigen::Matrix4d M1, M2, M3, M4;
|
||||
|
||||
// As a consistency check, D0 should be D1+D2+D3+D4
|
||||
M1 << xP, yP, zP, 1., xB, yB, zB, 1., xC, yC, zC, 1., xD, yD, zD, 1.;
|
||||
double D1 = M1.determinant();
|
||||
if (!sameSign(D1, D0))
|
||||
return false;
|
||||
|
||||
M2 << xA, yA, zA, 1., xP, yP, zP, 1., xC, yC, zC, 1., xD, yD, zD, 1.;
|
||||
double D2 = M2.determinant();
|
||||
if (!sameSign(D2, D0))
|
||||
return false;
|
||||
|
||||
M3 << xA, yA, zA, 1., xB, yB, zB, 1., xP, yP, zP, 1., xD, yD, zD, 1.;
|
||||
double D3 = M3.determinant();
|
||||
if (!sameSign(D3, D0))
|
||||
return false;
|
||||
|
||||
M4 << xA, yA, zA, 1., xB, yB, zB, 1., xC, yC, zC, 1., xP, yP, zP, 1.;
|
||||
double D4 = M4.determinant();
|
||||
if (!sameSign(D4, D0))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} //isInTetrahedron
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
/** @fn aux_get_masstracer_coords
|
||||
* Subroutine of get_masstracer_coords
|
||||
*/
|
||||
static void aux_get_masstracer_coords(
|
||||
const double xS, const double yS, const double zS, const double xM,
|
||||
const double yM, const double zM, double *MassTracerCoords) {
|
||||
// Matches the monopole and quadrupole moments
|
||||
// of the mass distribution of the homogeneous tetrahedron
|
||||
// (section 2.2 in Hahn, Abel & Kaehler 2013)
|
||||
MassTracerCoords[0] = INV_SQRT_5 * xS + ONE_MINUS_INV_SQRT_5 * xM;
|
||||
MassTracerCoords[1] = INV_SQRT_5 * yS + ONE_MINUS_INV_SQRT_5 * yM;
|
||||
MassTracerCoords[2] = INV_SQRT_5 * zS + ONE_MINUS_INV_SQRT_5 * zM;
|
||||
} //aux_get_masstracer_coords
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
/** @fn get_masstracer_coords
|
||||
* Get coordinates of the mass tracer for one side of a tetrahedron
|
||||
* @param TetrahedronCoords input tetrahedron vertices coordinates
|
||||
* @param iside the id of the tetrahedron side (0 to 4)
|
||||
* @param MassTracerCoords output coordinates of the mass tracer
|
||||
*/
|
||||
static void get_masstracer_coords(
|
||||
const double *TetrahedronCoords, const int iside,
|
||||
double *MassTracerCoords) {
|
||||
double xA, yA, zA, xB, yB, zB, xC, yC, zC, xD, yD, zD, xM, yM, zM;
|
||||
xA = TetrahedronCoords[0];
|
||||
yA = TetrahedronCoords[1];
|
||||
zA = TetrahedronCoords[2];
|
||||
xB = TetrahedronCoords[3];
|
||||
yB = TetrahedronCoords[4];
|
||||
zB = TetrahedronCoords[5];
|
||||
xC = TetrahedronCoords[6];
|
||||
yC = TetrahedronCoords[7];
|
||||
zC = TetrahedronCoords[8];
|
||||
xD = TetrahedronCoords[9];
|
||||
yD = TetrahedronCoords[10];
|
||||
zD = TetrahedronCoords[11];
|
||||
xM = (xA + xB + xC + xD) / 4;
|
||||
yM = (yA + yB + yC + yD) / 4;
|
||||
zM = (zA + zB + zC + zD) / 4;
|
||||
|
||||
switch (iside) {
|
||||
case 0:
|
||||
aux_get_masstracer_coords(xA, yA, zA, xM, yM, zM, MassTracerCoords);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
aux_get_masstracer_coords(xB, yB, zB, xM, yM, zM, MassTracerCoords);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
aux_get_masstracer_coords(xC, yC, zC, xM, yM, zM, MassTracerCoords);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
aux_get_masstracer_coords(xD, yD, zD, xM, yM, zM, MassTracerCoords);
|
||||
break;
|
||||
}
|
||||
} //get_masstracer_coords
|
||||
|
||||
} // namespace DM_Sheet
|
||||
} // namespace LibLSS
|
||||
|
||||
#endif
|
||||
// ARES TAG: authors_num = 2
|
||||
// ARES TAG: name(0) = Florent Leclercq
|
||||
// ARES TAG: year(0) = 2016-2018
|
||||
// ARES TAG: email(0) = florent.leclercq@polytechnique.org
|
||||
// ARES TAG: name(1) = Guilhem Lavaux
|
||||
// ARES TAG: year(1) = 2018
|
||||
// ARES TAG: email(1) = guilhem.lavaux@iap.fr
|
58
extra/dm_sheet/libLSS/physics/dm_sheet/tools.hpp
Normal file
58
extra/dm_sheet/libLSS/physics/dm_sheet/tools.hpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./extra/dm_sheet/libLSS/physics/dm_sheet/tools.hpp
|
||||
Copyright (C) 2016-2018 Florent Leclercq <florent.leclercq@polytechnique.org>
|
||||
Copyright (C) 2018 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_DMSHEET_TOOLS_HPP
|
||||
# define __LIBLSS_DMSHEET_TOOLS_HPP
|
||||
|
||||
# include <cmath>
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
namespace DM_Sheet {
|
||||
|
||||
///-------------------------------------------------------------------------------------
|
||||
/** @fn p_mod
|
||||
* Replaces function modulo, treats differently negative values
|
||||
* @param x
|
||||
* @param y should be positive, else replaced by -y
|
||||
* @return value between 0 and y
|
||||
*/
|
||||
template <typename T>
|
||||
inline T p_mod(const T x, const T y) {
|
||||
if (y == 0)
|
||||
return 0;
|
||||
T yy = std::abs(y);
|
||||
|
||||
return std::fmod(x + yy, yy);
|
||||
} //p_mod
|
||||
|
||||
static bool sameSign(double x, double y) {
|
||||
double xy = x*y;
|
||||
return xy >= 0.;
|
||||
} //sameSign
|
||||
|
||||
static void
|
||||
periodic_boundary_correct(const double xmax, double &xA, const double L0) {
|
||||
if ((xmax - xA) > (L0 - xmax) + xA)
|
||||
xA += L0;
|
||||
} //periodic_boundary_correct
|
||||
|
||||
} // namespace DM_Sheet
|
||||
|
||||
} // namespace LibLSS
|
||||
|
||||
#endif
|
||||
|
||||
// ARES TAG: authors_num = 2
|
||||
// ARES TAG: name(0) = Florent Leclercq
|
||||
// ARES TAG: year(0) = 2016-2018
|
||||
// ARES TAG: email(0) = florent.leclercq@polytechnique.org
|
||||
// ARES TAG: name(1) = Guilhem Lavaux
|
||||
// ARES TAG: year(1) = 2018
|
||||
// ARES TAG: email(1) = guilhem.lavaux@iap.fr
|
198
extra/dm_sheet/libLSS/physics/velocity/velocity_sic.cpp
Normal file
198
extra/dm_sheet/libLSS/physics/velocity/velocity_sic.cpp
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./extra/dm_sheet/libLSS/physics/velocity/velocity_sic.cpp
|
||||
Copyright (C) 2019-2020 Florent Leclercq <florent.leclercq@polytechnique.org>
|
||||
Copyright (C) 2019-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#include "libLSS/mpi/generic_mpi.hpp"
|
||||
#include "libLSS/physics/velocity/velocity_sic.hpp"
|
||||
#include "libLSS/physics/dm_sheet/dm_sheet.hpp"
|
||||
|
||||
using namespace LibLSS;
|
||||
using namespace LibLSS::VelocityModel;
|
||||
|
||||
typedef U_Array<double, 4> U_VFieldType;
|
||||
typedef U_Array<double, 1> U_ParticleBasedScalar;
|
||||
typedef U_Array<double, 2> U_ParticleBasedArray;
|
||||
|
||||
typedef ParticleBasedForwardModel::PhaseSubArray::index_range range;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* This computes the velocity field by CiC projection of particles
|
||||
*
|
||||
* @param VelocityField
|
||||
*/
|
||||
void SICModel::getVelocityField(arrayVelocityField_t VelocityField) {
|
||||
boost::multi_array_types::index_gen i_gen;
|
||||
typedef boost::multi_array_types::index_range range;
|
||||
|
||||
LibLSS::ConsoleContext<LOG_DEBUG> ctx("SICModel::getVelocityField");
|
||||
|
||||
// get particles' positions and velocities from the forward model
|
||||
auto ids = p_model->getLagrangianIdentifiers();
|
||||
auto positions = p_model->getParticlePositions();
|
||||
auto velocities = p_model->getParticleVelocities();
|
||||
unsigned int srate = p_model->getSupersamplingRate();
|
||||
|
||||
// get number of particles, box specifications, FFTW manager and MPI communicator from forward model
|
||||
size_t numParticles = p_model->getNumberOfParticles();
|
||||
BoxModel model_box = model->get_box_model();
|
||||
BoxModel box = outputBox;
|
||||
MPI_Communication *comm = model->communicator();
|
||||
size_t startN0 = mgr.startN0;
|
||||
size_t endN0 = startN0 + mgr.localN0;
|
||||
size_t N1 = mgr.N1;
|
||||
size_t N2 = mgr.N2;
|
||||
typedef std::unique_ptr<U_Array<double, 3>> U_3d;
|
||||
typedef std::unique_ptr<U_Array<double, 4>> U_4d;
|
||||
|
||||
// initialize VelocityField and MassField to zero
|
||||
fwrap(VelocityField) = 0;
|
||||
|
||||
size_t thread_max = smp_get_max_threads();
|
||||
std::unique_ptr<U_3d[]> threaded_density_array(new U_3d[thread_max]);
|
||||
std::unique_ptr<U_4d[]> threaded_velocity_array(new U_4d[thread_max]);
|
||||
|
||||
ctx.format("Allocating temporary output array, max_threads = %d", thread_max);
|
||||
for (size_t i = 0; i < thread_max; i++) {
|
||||
threaded_density_array[i] =
|
||||
U_3d(new U_3d::element_type(boost::extents[box.N0][box.N1][box.N2]));
|
||||
threaded_velocity_array[i] =
|
||||
U_4d(new U_4d::element_type(boost::extents[box.N0][box.N1][box.N2][3]));
|
||||
}
|
||||
|
||||
ctx.print("Go parallel and compute velocity/density");
|
||||
|
||||
#pragma omp parallel
|
||||
{
|
||||
size_t tid = smp_get_thread_id();
|
||||
size_t id_min = tid * numParticles / smp_get_num_threads();
|
||||
size_t id_max = (tid + 1) * numParticles / smp_get_num_threads();
|
||||
|
||||
fwrap(*threaded_density_array[tid]) = 0;
|
||||
fwrap(*threaded_velocity_array[tid]) = 0;
|
||||
|
||||
DM_Sheet::get_mass_and_momenta_tetrahedra(
|
||||
ids[i_gen[range(id_min, id_max)]], positions, velocities, model_box.L0,
|
||||
model_box.L1, model_box.L2, srate * model_box.N0, srate * model_box.N1,
|
||||
srate * model_box.N2, box.N0, box.N1, box.N2,
|
||||
threaded_density_array[tid]->get_array(),
|
||||
threaded_velocity_array[tid]->get_array());
|
||||
}
|
||||
|
||||
// divide momenta by density and normalize to get the velocity field
|
||||
|
||||
ctx.print("Final reduction");
|
||||
for (size_t i = 0; i < thread_max; i++) {
|
||||
if (i > 0) {
|
||||
auto out_w = fwrap(threaded_density_array[0]->get_array());
|
||||
out_w = out_w + fwrap(threaded_density_array[i]->get_array());
|
||||
}
|
||||
for (int k = 0; k < 3; k++) {
|
||||
auto out_v = fwrap(VelocityField[k]);
|
||||
out_v =
|
||||
out_v + fwrap(threaded_velocity_array[i]
|
||||
->get_array()[i_gen[range()][range()][range()][k]]);
|
||||
}
|
||||
}
|
||||
|
||||
auto out = fwrap(threaded_density_array[0]->get_array());
|
||||
for (unsigned int k = 0; k < 3; k++) {
|
||||
auto v = fwrap(VelocityField[i_gen[k][range()][range()][range()]]);
|
||||
v = p_model->getVelocityMultiplier() * v / out;
|
||||
}
|
||||
|
||||
} //getVelocityField
|
||||
|
||||
void SICModel::computeAdjointModel(arrayVelocityField_view_t AGVelocityField) {
|
||||
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
|
||||
|
||||
} //computeAdjointModel
|
||||
|
||||
void LibLSS::computeSICVelocityField(
|
||||
DM_Sheet::arrayID_t const &identifiers,
|
||||
DM_Sheet::arrayPosition_t const &pos, DM_Sheet::arrayVelocity_t const &vels,
|
||||
double L, int N, int Ng, boost::multi_array_ref<double, 3> &DensityField,
|
||||
VelocityModel::ParticleBasedModel::arrayVelocityField_t &VelocityField) {
|
||||
boost::multi_array_types::index_gen i_gen;
|
||||
typedef boost::multi_array_types::index_range range;
|
||||
|
||||
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
|
||||
|
||||
// get particles' positions and velocities from the forward model
|
||||
auto ids = identifiers[i_gen[range()]];
|
||||
auto positions = pos[i_gen[range()][range()]];
|
||||
auto velocities = vels[i_gen[range()][range()]];
|
||||
|
||||
long numParticles = ids.shape()[0];
|
||||
|
||||
typedef std::unique_ptr<U_Array<double, 3>> U_3d;
|
||||
typedef std::unique_ptr<U_Array<double, 4>> U_4d;
|
||||
|
||||
// initialize VelocityField and MassField to zero
|
||||
fwrap(VelocityField) = 0;
|
||||
|
||||
size_t thread_max = smp_get_max_threads();
|
||||
std::unique_ptr<U_3d[]> threaded_density_array(new U_3d[thread_max]);
|
||||
std::unique_ptr<U_4d[]> threaded_velocity_array(new U_4d[thread_max]);
|
||||
|
||||
ctx.format("Allocating temporary output array, max_threads = %d", thread_max);
|
||||
for (size_t i = 0; i < thread_max; i++) {
|
||||
threaded_density_array[i] =
|
||||
U_3d(new U_3d::element_type(boost::extents[Ng][Ng][Ng]));
|
||||
threaded_velocity_array[i] =
|
||||
U_4d(new U_4d::element_type(boost::extents[Ng][Ng][Ng][3]));
|
||||
}
|
||||
|
||||
ctx.print("Go parallel and compute velocity/density");
|
||||
|
||||
#pragma omp parallel
|
||||
{
|
||||
size_t tid = smp_get_thread_id();
|
||||
size_t id_min = tid * numParticles / smp_get_num_threads();
|
||||
size_t id_max = (tid + 1) * numParticles / smp_get_num_threads();
|
||||
|
||||
fwrap(*threaded_density_array[tid]) = 0;
|
||||
fwrap(*threaded_velocity_array[tid]) = 0;
|
||||
|
||||
DM_Sheet::get_mass_and_momenta_tetrahedra(
|
||||
ids[i_gen[range(id_min, id_max)]], positions, velocities, L, L, L, N, N,
|
||||
N, Ng, Ng, Ng, threaded_density_array[tid]->get_array(),
|
||||
threaded_velocity_array[tid]->get_array());
|
||||
}
|
||||
|
||||
// divide momenta by density and normalize to get the velocity field
|
||||
|
||||
ctx.print("Final reduction");
|
||||
auto out_w = fwrap(threaded_density_array[0]->get_array());
|
||||
for (size_t i = 0; i < thread_max; i++) {
|
||||
if (i > 0) {
|
||||
out_w = out_w + fwrap(threaded_density_array[i]->get_array());
|
||||
}
|
||||
for (int k = 0; k < 3; k++) {
|
||||
auto out_v = fwrap(VelocityField[k]);
|
||||
out_v =
|
||||
out_v + fwrap(threaded_velocity_array[i]
|
||||
->get_array()[i_gen[range()][range()][range()][k]]);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int k = 0; k < 3; k++) {
|
||||
auto v = fwrap(VelocityField[i_gen[k][range()][range()][range()]]);
|
||||
v = v / out_w;
|
||||
}
|
||||
fwrap(DensityField) = out_w;
|
||||
}
|
||||
|
||||
// ARES TAG: authors_num = 2
|
||||
// ARES TAG: name(0) = Florent Leclercq
|
||||
// ARES TAG: year(0) = 2019-2020
|
||||
// ARES TAG: email(0) = florent.leclercq@polytechnique.org
|
||||
// ARES TAG: name(1) = Guilhem Lavaux
|
||||
// ARES TAG: year(1) = 2019-2020
|
||||
// ARES TAG: email(1) = guilhem.lavaux@iap.fr
|
81
extra/dm_sheet/libLSS/physics/velocity/velocity_sic.hpp
Normal file
81
extra/dm_sheet/libLSS/physics/velocity/velocity_sic.hpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./extra/dm_sheet/libLSS/physics/velocity/velocity_sic.hpp
|
||||
Copyright (C) 2019-2020 Florent Leclercq <florent.leclercq@polytechnique.org>
|
||||
Copyright (C) 2019-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#pragma once
|
||||
#ifndef __LIBLSS_PHYSICS_VELOCITY_SIC
|
||||
# define __LIBLSS_PHYSICS_VELOCITY_SIC
|
||||
|
||||
# include <boost/multi_array.hpp>
|
||||
|
||||
# include "libLSS/physics/velocity/velocity.hpp"
|
||||
# include "libLSS/physics/dm_sheet/dm_sheet.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
void computeSICVelocityField(
|
||||
DM_Sheet::arrayID_t const &identifiers,
|
||||
DM_Sheet::arrayPosition_t const &pos,
|
||||
DM_Sheet::arrayVelocity_t const &vels, double L, int N, int Ng,
|
||||
boost::multi_array_ref<double, 3> &DensityField,
|
||||
VelocityModel::ParticleBasedModel::arrayVelocityField_t &VelocityField);
|
||||
|
||||
namespace VelocityModel {
|
||||
|
||||
/**
|
||||
* @brief Simplex-In-Cell velocity field model from BORGForwardModel
|
||||
*
|
||||
*/
|
||||
class SICModel : public ParticleBasedModel {
|
||||
protected:
|
||||
LibLSS::FFTW_Manager<double, 3> mgr;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new SICModel object
|
||||
*
|
||||
* @param box_out_
|
||||
* @param model_
|
||||
*/
|
||||
SICModel(BoxModel box_out_, particleForwardModel_t model_)
|
||||
: ParticleBasedModel(box_out_, model_),
|
||||
mgr(box_out_.N0, box_out_.N1, box_out_.N2, model_->communicator()) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the Mgr object
|
||||
*
|
||||
* @return LibLSS::FFTW_Manager<double, 3> const&
|
||||
*/
|
||||
LibLSS::FFTW_Manager<double, 3> const &getMgr() const { return mgr; }
|
||||
|
||||
void queryLocalExtents(std::array<ssize_t, 6> &e) override {
|
||||
e[0] = mgr.startN0;
|
||||
e[1] = mgr.startN0 + mgr.localN0;
|
||||
e[2] = 0;
|
||||
e[3] = mgr.N1;
|
||||
e[4] = 0;
|
||||
e[5] = mgr.N2;
|
||||
}
|
||||
|
||||
void getVelocityField(arrayVelocityField_t VelocityField) override;
|
||||
void
|
||||
computeAdjointModel(arrayVelocityField_view_t AGVelocityField) override;
|
||||
};
|
||||
} // namespace VelocityModel
|
||||
}; // namespace LibLSS
|
||||
|
||||
#endif
|
||||
|
||||
// ARES TAG: authors_num = 2
|
||||
// ARES TAG: name(0) = Florent Leclercq
|
||||
// ARES TAG: year(0) = 2019-2020
|
||||
// ARES TAG: email(0) = florent.leclercq@polytechnique.org
|
||||
// ARES TAG: name(1) = Guilhem Lavaux
|
||||
// ARES TAG: year(1) = 2019-2020
|
||||
// ARES TAG: email(1) = guilhem.lavaux@iap.fr
|
Loading…
Add table
Add a link
Reference in a new issue