11#ifndef PHOTONSCONTAINER_HXX
12#define PHOTONSCONTAINER_HXX
17#include "AMReX_Array.H"
18#include "AMReX_CTOParallelForImpl.H"
19#include "AMReX_ParallelDescriptor.H"
23#include "cctk_Types.h"
25#include <AMReX_AmrParticles.H>
26#include <AMReX_MultiFab.H>
27#include <AMReX_MultiFabUtil.H>
28#include <AMReX_Particles.H>
29#include <AMReX_REAL.H>
31#include <cctk_Arguments.h>
32#include <cctk_Parameters.h>
51template <
typename StructType>
73 void evolve(
const amrex::MultiFab &lapse,
const amrex::MultiFab &shift,
74 const amrex::MultiFab &metric,
const amrex::MultiFab &curv,
75 const CCTK_REAL &dt,
const int &lev)
override;
78 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE CCTK_ATTRIBUTE_ALWAYS_INLINE
79 amrex::GpuArray<CCTK_REAL, 7>
80 compute_rhs(
const amrex::GpuArray<CCTK_REAL, 7> &u,
const CCTK_REAL &t,
81 amrex::Array4<CCTK_REAL const>
const &lapse,
82 amrex::Array4<CCTK_REAL const>
const &shift,
83 amrex::Array4<CCTK_REAL const>
const &metric,
84 amrex::Array4<CCTK_REAL const>
const &K,
const CCTK_REAL dt,
85 const amrex::GpuArray<double, 3> &dx,
const int lev,
86 const amrex::GpuArray<double, 3> &plo);
147template <
typename StructType>
148AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE CCTK_ATTRIBUTE_ALWAYS_INLINE
149 amrex::GpuArray<CCTK_REAL, 7>
151 const amrex::GpuArray<CCTK_REAL, 7> &u,
const CCTK_REAL &t,
152 amrex::Array4<CCTK_REAL const>
const &lapse,
153 const amrex::Array4<CCTK_REAL const> &shift,
154 const amrex::Array4<CCTK_REAL const> &metric,
155 const amrex::Array4<CCTK_REAL const> &curv,
const CCTK_REAL dt,
156 const amrex::GpuArray<double, 3> &dx,
const int lev,
157 const amrex::GpuArray<double, 3> &plo) {
159 amrex::GpuArray<CCTK_REAL, 7> rhs = {0., 0., 0., 0., 0., 0., 0.};
161 const long int i0 = amrex::Math::floor((u[0] - plo[0]) / dx[0]);
162 const long int j0 = amrex::Math::floor((u[1] - plo[1]) / dx[1]);
163 const long int k0 = amrex::Math::floor((u[2] - plo[2]) / dx[2]);
167 amrex::GpuArray<CCTK_REAL, 3> d_lapse_x;
168 d_interpolate_array<5>(lapse_x, d_lapse_x, lapse, i0, j0, k0, u[0], u[1],
172 amrex::GpuArray<CCTK_REAL, 3> shift_x;
173 amrex::GpuArray<amrex::GpuArray<CCTK_REAL, 3>, 3> d_shift_x;
174 d_interpolate_array<5>(shift_x, d_shift_x, shift, i0, j0, k0, u[0], u[1],
178 amrex::GpuArray<CCTK_REAL, 6> gamma_x;
179 amrex::GpuArray<amrex::GpuArray<CCTK_REAL, 6>, 3> d_gamma_x;
180 d_interpolate_array<5>(gamma_x, d_gamma_x, metric, i0, j0, k0, u[0], u[1],
184 amrex::GpuArray<CCTK_REAL, 6> curv_x;
185 interpolate_array<5>(curv_x, curv, i0, j0, k0, u[0], u[1], u[2], dx, plo);
188 const CCTK_REAL inv_det_gamma =
189 1.0 / (gamma_x[0] * gamma_x[3] * gamma_x[5] +
190 2. * gamma_x[1] * gamma_x[2] * gamma_x[4] -
191 gamma_x[2] * gamma_x[2] * gamma_x[3] -
192 gamma_x[4] * gamma_x[4] * gamma_x[0] -
193 gamma_x[1] * gamma_x[1] * gamma_x[5]);
195 const amrex::GpuArray<CCTK_REAL, 6> gamma_inv_x = {
196 (gamma_x[3] * gamma_x[5] - gamma_x[4] * gamma_x[4]) * inv_det_gamma,
197 (gamma_x[4] * gamma_x[2] - gamma_x[1] * gamma_x[5]) * inv_det_gamma,
198 (gamma_x[1] * gamma_x[4] - gamma_x[2] * gamma_x[3]) * inv_det_gamma,
199 (gamma_x[0] * gamma_x[5] - gamma_x[2] * gamma_x[2]) * inv_det_gamma,
200 (gamma_x[2] * gamma_x[1] - gamma_x[0] * gamma_x[4]) * inv_det_gamma,
201 (gamma_x[0] * gamma_x[3] - gamma_x[1] * gamma_x[1]) * inv_det_gamma};
203 const amrex::GpuArray<CCTK_REAL, 3> V_down = {u[3], u[4], u[5]};
206 const amrex::GpuArray<CCTK_REAL, 3> V_up = {
207 gamma_inv_x[0] * u[3] + gamma_inv_x[1] * u[4] + gamma_inv_x[2] * u[5],
208 gamma_inv_x[1] * u[3] + gamma_inv_x[3] * u[4] + gamma_inv_x[4] * u[5],
209 gamma_inv_x[2] * u[3] + gamma_inv_x[4] * u[4] + gamma_inv_x[5] * u[5]};
212 rhs[0] = lapse_x * V_up[0] - shift_x[0];
213 rhs[1] = lapse_x * V_up[1] - shift_x[1];
214 rhs[2] = lapse_x * V_up[2] - shift_x[2];
217 for (
int i = 0; i < 3; i++) {
228 rhs[3 + StructType::ln_E] =
265template <
typename StructType>
267 const amrex::MultiFab &shift,
268 const amrex::MultiFab &metric,
269 const amrex::MultiFab &curv,
270 const CCTK_REAL &dt,
const int &lev) {
272 const auto plo0 = this->Geom(0).ProbLoArray();
273 const auto phi0 = this->Geom(0).ProbHiArray();
275 const auto dx = this->Geom(lev).CellSizeArray();
276 const auto plo = this->Geom(lev).ProbLoArray();
278 const CCTK_REAL boundarie_hx = phi0[0] - 0.0 * dx[0];
279 const CCTK_REAL boundarie_lx = plo0[0] + 0.0 * dx[0];
280 const CCTK_REAL boundarie_hy = phi0[1] - 0.0 * dx[1];
281 const CCTK_REAL boundarie_ly = plo0[1] + 0.0 * dx[1];
282 const CCTK_REAL boundarie_hz = phi0[2] - 0.0 * dx[2];
283 const CCTK_REAL boundarie_lz = plo0[2] + 0.0 * dx[2];
288 const int np = pti.numParticles();
291 auto &attribs = pti.GetAttributes();
292 CCTK_REAL *AMREX_RESTRICT vels_x = attribs[StructType::vx].data();
293 CCTK_REAL *AMREX_RESTRICT vels_y = attribs[StructType::vy].data();
294 CCTK_REAL *AMREX_RESTRICT vels_z = attribs[StructType::vz].data();
295 CCTK_REAL *AMREX_RESTRICT ln_energy = attribs[StructType::ln_E].data();
296 auto *AMREX_RESTRICT particles = &(pti.GetArrayOfStructs()[0]);
299 auto const lapse_array = lapse.array(pti);
300 auto const shift_array = shift.array(pti);
301 auto const metric_array = metric.array(pti);
302 auto const curv_array = curv.array(pti);
307 amrex::ParallelFor(np, [=] AMREX_GPU_DEVICE(
int i)
noexcept {
308 const amrex::GpuArray<CCTK_REAL, 7> U = {
309 particles[i].pos(0), particles[i].pos(1), particles[i].pos(2),
310 vels_x[i], vels_y[i], vels_z[i],
313 bool out_of_bounds =
false;
315 amrex::GpuArray<CCTK_REAL, 7> U_tmp = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
319 self->compute_rhs(U, 0.0, lapse_array, shift_array, metric_array,
320 curv_array, dt, dx, lev, plo0);
322 U_tmp[0] = U[0] + 0.5 * dt * k_odd[0];
323 U_tmp[1] = U[1] + 0.5 * dt * k_odd[1];
324 U_tmp[2] = U[2] + 0.5 * dt * k_odd[2];
325 U_tmp[3] = U[3] + 0.5 * dt * k_odd[3];
326 U_tmp[4] = U[4] + 0.5 * dt * k_odd[4];
327 U_tmp[5] = U[5] + 0.5 * dt * k_odd[5];
328 U_tmp[6] = U[6] + 0.5 * dt * k_odd[6];
330 out_of_bounds |= (U_tmp[0] > boundarie_hx) || (U_tmp[0] < boundarie_lx);
331 out_of_bounds |= (U_tmp[1] > boundarie_hy) || (U_tmp[1] < boundarie_ly);
332 out_of_bounds |= (U_tmp[2] > boundarie_hz) || (U_tmp[2] < boundarie_lz);
335 particles[i].id() = -1;
341 self->compute_rhs(U_tmp, 0.5 * dt, lapse_array, shift_array,
342 metric_array, curv_array, dt, dx, lev, plo0);
345 U_tmp[0] = U[0] + 0.5 * dt * k_even[0];
346 U_tmp[1] = U[1] + 0.5 * dt * k_even[1];
347 U_tmp[2] = U[2] + 0.5 * dt * k_even[2];
348 U_tmp[3] = U[3] + 0.5 * dt * k_even[3];
349 U_tmp[4] = U[4] + 0.5 * dt * k_even[4];
350 U_tmp[5] = U[5] + 0.5 * dt * k_even[5];
351 U_tmp[6] = U[6] + 0.5 * dt * k_even[6];
353 particles[i].pos(0) += (1. / 6.) * dt * (k_odd[0] + 2. * k_even[0]);
354 particles[i].pos(1) += (1. / 6.) * dt * (k_odd[1] + 2. * k_even[1]);
355 particles[i].pos(2) += (1. / 6.) * dt * (k_odd[2] + 2. * k_even[2]);
356 vels_x[i] += (1. / 6.) * dt * (k_odd[3] + 2. * k_even[3]);
357 vels_y[i] += (1. / 6.) * dt * (k_odd[4] + 2. * k_even[4]);
358 vels_z[i] += (1. / 6.) * dt * (k_odd[5] + 2. * k_even[5]);
359 ln_energy[i] += (1. / 6.) * dt * (k_odd[6] + 2. * k_even[6]);
361 out_of_bounds |= (U_tmp[0] > boundarie_hx) || (U_tmp[0] < boundarie_lx);
362 out_of_bounds |= (U_tmp[1] > boundarie_hy) || (U_tmp[1] < boundarie_ly);
363 out_of_bounds |= (U_tmp[2] > boundarie_hz) || (U_tmp[2] < boundarie_lz);
366 particles[i].id() = -1;
371 k_odd = self->compute_rhs(U_tmp, 0.5 * dt, lapse_array, shift_array,
372 metric_array, curv_array, dt, dx, lev, plo0);
374 U_tmp[0] = U[0] + dt * k_odd[0];
375 U_tmp[1] = U[1] + dt * k_odd[1];
376 U_tmp[2] = U[2] + dt * k_odd[2];
377 U_tmp[3] = U[3] + dt * k_odd[3];
378 U_tmp[4] = U[4] + dt * k_odd[4];
379 U_tmp[5] = U[5] + dt * k_odd[5];
380 U_tmp[6] = U[6] + dt * k_odd[6];
382 out_of_bounds |= (U_tmp[0] > boundarie_hx) || (U_tmp[0] < boundarie_lx);
383 out_of_bounds |= (U_tmp[1] > boundarie_hy) || (U_tmp[1] < boundarie_ly);
384 out_of_bounds |= (U_tmp[2] > boundarie_hz) || (U_tmp[2] < boundarie_lz);
387 particles[i].id() = -1;
392 k_even = self->compute_rhs(U_tmp, dt, lapse_array, shift_array,
393 metric_array, curv_array, dt, dx, lev, plo0);
396 particles[i].pos(0) += (1. / 6.) * dt * (2. * k_odd[0] + k_even[0]);
397 particles[i].pos(1) += (1. / 6.) * dt * (2. * k_odd[1] + k_even[1]);
398 particles[i].pos(2) += (1. / 6.) * dt * (2. * k_odd[2] + k_even[2]);
399 vels_x[i] += (1. / 6.) * dt * (2. * k_odd[3] + k_even[3]);
400 vels_y[i] += (1. / 6.) * dt * (2. * k_odd[4] + k_even[4]);
401 vels_z[i] += (1. / 6.) * dt * (2. * k_odd[5] + k_even[5]);
402 ln_energy[i] += (1. / 6.) * dt * (2. * k_odd[6] + k_even[6]);
404 out_of_bounds |= (particles[i].pos(0) > boundarie_hx) ||
405 (particles[i].pos(0) < boundarie_lx);
406 out_of_bounds |= (particles[i].pos(1) > boundarie_hy) ||
407 (particles[i].pos(1) < boundarie_ly);
408 out_of_bounds |= (particles[i].pos(2) > boundarie_hz) ||
409 (particles[i].pos(2) < boundarie_lz);
412 particles[i].id() = -1;
455template <
typename StructType>
457 const amrex::MultiFab &metric,
const int level) {
460 const auto dx = this->Geom(level).CellSizeArray();
462 const auto p_lo = this->Geom(level).ProbLoArray();
463 const auto p_hi = this->Geom(level).ProbHiArray();
465 for (amrex::MFIter mfi = this->MakeMFIter(level); mfi.isValid(); ++mfi) {
468 auto &particle_tile = this->DefineAndReturnParticleTile(level, mfi);
471 const auto current_size = particle_tile.GetArrayOfStructs().size();
475 auto *p_struct = particle_tile.GetArrayOfStructs()().data();
476 auto arrdata = particle_tile.GetStructOfArrays().realarray();
479 const auto metric_array = metric.array(mfi);
480 const CCTK_REAL m = this->mass;
482 amrex::ParallelFor(current_size, [=] AMREX_GPU_DEVICE(
int i)
noexcept {
484 const CCTK_REAL ratio[3] = {arrdata[StructType::vx][i],
485 arrdata[StructType::vy][i],
486 arrdata[StructType::vz][i]};
487 const CCTK_REAL E = std::exp(arrdata[StructType::ln_E][i]);
490 const auto &p = p_struct[i];
492 const int i0 = amrex::Math::floor((p.pos(0) - p_lo[0]) / dx[0]);
493 const int j0 = amrex::Math::floor((p.pos(1) - p_lo[1]) / dx[1]);
494 const int k0 = amrex::Math::floor((p.pos(2) - p_lo[2]) / dx[2]);
497 amrex::GpuArray<CCTK_REAL, 6> gamma_x;
498 interpolate_array<5>(gamma_x, metric_array, i0, j0, k0, p.pos(0),
499 p.pos(1), p.pos(2), dx, p_lo);
501 const CCTK_REAL inv_det_gamma =
502 1.0 / (gamma_x[0] * gamma_x[3] * gamma_x[5] +
503 2. * gamma_x[1] * gamma_x[2] * gamma_x[4] -
504 gamma_x[2] * gamma_x[2] * gamma_x[3] -
505 gamma_x[4] * gamma_x[4] * gamma_x[0] -
506 gamma_x[1] * gamma_x[1] * gamma_x[5]);
508 const amrex::GpuArray<CCTK_REAL, 6> gamma_inv_x = {
509 (gamma_x[3] * gamma_x[5] - gamma_x[4] * gamma_x[4]) * inv_det_gamma,
510 (gamma_x[4] * gamma_x[2] - gamma_x[1] * gamma_x[5]) * inv_det_gamma,
511 (gamma_x[1] * gamma_x[4] - gamma_x[2] * gamma_x[3]) * inv_det_gamma,
512 (gamma_x[0] * gamma_x[5] - gamma_x[2] * gamma_x[2]) * inv_det_gamma,
513 (gamma_x[2] * gamma_x[1] - gamma_x[0] * gamma_x[4]) * inv_det_gamma,
514 (gamma_x[0] * gamma_x[3] - gamma_x[1] * gamma_x[1]) * inv_det_gamma};
517 const CCTK_REAL v_squared = ratio[0] * ratio[0] * gamma_inv_x[0] +
518 ratio[1] * ratio[1] * gamma_inv_x[3] +
519 ratio[2] * ratio[2] * gamma_inv_x[5] +
520 2.0 * ratio[0] * ratio[1] * gamma_inv_x[1] +
521 2.0 * ratio[0] * ratio[2] * gamma_inv_x[2] +
522 2.0 * ratio[1] * ratio[2] * gamma_inv_x[4];
524 const CCTK_REAL v = std::sqrt(v_squared);
525 const CCTK_REAL alpha = std::sqrt(1. - m * m / (E * E));
527 arrdata[StructType::vx][i] = ratio[0] * alpha / v;
528 arrdata[StructType::vy][i] = ratio[1] * alpha / v;
529 arrdata[StructType::vz][i] = ratio[2] * alpha / v;
534template <
typename StructType>
536 CCTK_INFO(
"Redistributing particles");
It Contains the BaseParticlesContainer and ParticleIterator classes inside of the GInX namespace.
Barycentric Lagrange interpolation related functions definitions.
Code utilities such as matrix and vector multiplications.
AMREX_GPU_DEVICE AMREX_GPU_HOST AMREX_FORCE_INLINE CCTK_ATTRIBUTE_ALWAYS_INLINE amrex::GpuArray< CCTK_REAL, 3 > SMatVecMul(amrex::GpuArray< CCTK_REAL, 6 > A, amrex::GpuArray< CCTK_REAL, 3 > V)
Definition: Utilities.hxx:30
AMREX_GPU_DEVICE AMREX_GPU_HOST AMREX_FORCE_INLINE CCTK_ATTRIBUTE_ALWAYS_INLINE CCTK_REAL VecVecMul(amrex::GpuArray< CCTK_REAL, 3 > U, amrex::GpuArray< CCTK_REAL, 3 > V)
Definition: Utilities.hxx:51
BaseParticleContainer abstract class definition.
Definition: BaseParticleContainer.hxx:67
Definition: BaseParticleContainer.hxx:31
ParticlesContainer class definition.
Definition: ParticlesContainer.hxx:54
CCTK_REAL mass
Definition: ParticlesContainer.hxx:56
void normalize_velocity(const amrex::MultiFab &metric, const int level)
Normalize the velocity accordingly to the metric on each particle position.
Definition: ParticlesContainer.hxx:456
void evolve(const amrex::MultiFab &lapse, const amrex::MultiFab &shift, const amrex::MultiFab &metric, const amrex::MultiFab &curv, const CCTK_REAL &dt, const int &lev) override
Evolving using Runge-Kutta 4.
Definition: ParticlesContainer.hxx:266
~ParticlesContainer()=default
void redistribute_particles()
Definition: ParticlesContainer.hxx:535
ParticlesContainer(amrex::AmrCore *amr_core, const CCTK_REAL m)
Definition: ParticlesContainer.hxx:67
CCTK_INT get_mass()
Definition: ParticlesContainer.hxx:92
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE CCTK_ATTRIBUTE_ALWAYS_INLINE amrex::GpuArray< CCTK_REAL, 7 > compute_rhs(const amrex::GpuArray< CCTK_REAL, 7 > &u, const CCTK_REAL &t, amrex::Array4< CCTK_REAL const > const &lapse, amrex::Array4< CCTK_REAL const > const &shift, amrex::Array4< CCTK_REAL const > const &metric, amrex::Array4< CCTK_REAL const > const &K, const CCTK_REAL dt, const amrex::GpuArray< double, 3 > &dx, const int lev, const amrex::GpuArray< double, 3 > &plo)
Computes the right hand side of the geodesic differential equation.
Definition: ParticlesContainer.hxx:150
Interpolators namespace.
Definition: ParticlesContainer.hxx:39