Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
293 changes: 152 additions & 141 deletions src/archetypes/spatial_dist.h
Original file line number Diff line number Diff line change
@@ -1,141 +1,152 @@
/**
* @file archetypes/spatial_dist.hpp
* @brief Spatial distribution class passed to injectors
* @implements
* - arch::SpatialDistribution<>
* - arch::Uniform<> : arch::SpatialDistribution<>
* - arch::Replenish<> : arch::SpatialDistribution<>
* - arch::ReplenishUniform<> : arch::SpatialDistribution<>
* @namespace
* - arch::
* @note
* Instances of these functors take coordinate position in code units
* and return a number between 0 and 1 that represents the spatial distribution
*/

#ifndef ARCHETYPES_SPATIAL_DIST_HPP
#define ARCHETYPES_SPATIAL_DIST_HPP

#include "enums.h"
#include "global.h"

#include "arch/kokkos_aliases.h"
#include "utils/error.h"
#include "utils/numeric.h"

namespace arch {
using namespace ntt;

template <SimEngine::type S, class M>
struct SpatialDistribution {
static constexpr bool is_spatial_dist { true };
static_assert(M::is_metric, "M must be a metric class");

SpatialDistribution(const M& metric) : metric { metric } {}

protected:
const M metric;
};

template <SimEngine::type S, class M>
struct Uniform : public SpatialDistribution<S, M> {
Uniform(const M& metric) : SpatialDistribution<S, M> { metric } {}

Inline auto operator()(const coord_t<M::Dim>&) const -> real_t {
return ONE;
}
};

template <SimEngine::type S, class M, int N, class T>
struct Replenish : public SpatialDistribution<S, M> {
using SpatialDistribution<S, M>::metric;
const ndfield_t<M::Dim, N> density;
const idx_t idx;

const T target_density;
const real_t target_max_density;

Replenish(const M& metric,
const ndfield_t<M::Dim, N>& density,
idx_t idx,
const T& target_density,
real_t target_max_density)
: SpatialDistribution<S, M> { metric }
, density { density }
, idx { idx }
, target_density { target_density }
, target_max_density { target_max_density } {}

Inline auto operator()(const coord_t<M::Dim>& x_Ph) const -> real_t {
coord_t<M::Dim> x_Cd { ZERO };
metric.template convert<Crd::Ph, Crd::Cd>(x_Ph, x_Cd);
real_t dens { ZERO };
if constexpr (M::Dim == Dim::_1D) {
dens = density(static_cast<ncells_t>(x_Cd[0]) + N_GHOSTS, idx);
} else if constexpr (M::Dim == Dim::_2D) {
dens = density(static_cast<ncells_t>(x_Cd[0]) + N_GHOSTS,
static_cast<ncells_t>(x_Cd[1]) + N_GHOSTS,
idx);
} else if constexpr (M::Dim == Dim::_3D) {
dens = density(static_cast<ncells_t>(x_Cd[0]) + N_GHOSTS,
static_cast<ncells_t>(x_Cd[1]) + N_GHOSTS,
static_cast<ncells_t>(x_Cd[2]) + N_GHOSTS,
idx);
} else {
raise::KernelError(HERE, "Invalid dimension");
}
const auto target = target_density(x_Ph);
if (0.9 * target > dens) {
return (target - dens) / target_max_density;
} else {
return ZERO;
}
}
};

template <SimEngine::type S, class M, int N>
struct ReplenishUniform : public SpatialDistribution<S, M> {
using SpatialDistribution<S, M>::metric;
const ndfield_t<M::Dim, N> density;
const idx_t idx;

const real_t target_density;

ReplenishUniform(const M& metric,
const ndfield_t<M::Dim, N>& density,
idx_t idx,
real_t target_density)
: SpatialDistribution<S, M> { metric }
, density { density }
, idx { idx }
, target_density { target_density } {}

Inline auto operator()(const coord_t<M::Dim>& x_Ph) const -> real_t {
coord_t<M::Dim> x_Cd { ZERO };
metric.template convert<Crd::Ph, Crd::Cd>(x_Ph, x_Cd);
real_t dens { ZERO };
if constexpr (M::Dim == Dim::_1D) {
dens = density(static_cast<ncells_t>(x_Cd[0]) + N_GHOSTS, idx);
} else if constexpr (M::Dim == Dim::_2D) {
dens = density(static_cast<ncells_t>(x_Cd[0]) + N_GHOSTS,
static_cast<ncells_t>(x_Cd[1]) + N_GHOSTS,
idx);
} else if constexpr (M::Dim == Dim::_3D) {
dens = density(static_cast<ncells_t>(x_Cd[0]) + N_GHOSTS,
static_cast<ncells_t>(x_Cd[1]) + N_GHOSTS,
static_cast<ncells_t>(x_Cd[2]) + N_GHOSTS,
idx);
} else {
raise::KernelError(HERE, "Invalid dimension");
}
if (0.9 * target_density > dens) {
return (target_density - dens) / target_density;
} else {
return ZERO;
}
}
};

} // namespace arch

#endif // ARCHETYPES_SPATIAL_DIST_HPP
/**
* @file archetypes/spatial_dist.hpp
* @brief Spatial distribution class passed to injectors
* @implements
* - arch::SpatialDistribution<>
* - arch::Uniform<> : arch::SpatialDistribution<>
* - arch::Replenish<> : arch::SpatialDistribution<>
* - arch::ReplenishUniform<> : arch::SpatialDistribution<>
* @namespace
* - arch::
* @note
* Instances of these functors take coordinate position in code units
* and return a number between 0 and 1 that represents the spatial distribution
*/

#ifndef ARCHETYPES_SPATIAL_DIST_HPP
#define ARCHETYPES_SPATIAL_DIST_HPP

#include "enums.h"
#include "global.h"

#include "arch/kokkos_aliases.h"
#include "utils/error.h"
#include "utils/numeric.h"

namespace arch {
using namespace ntt;

template <SimEngine::type S, class M>
struct SpatialDistribution {
static constexpr bool is_spatial_dist { true };
static_assert(M::is_metric, "M must be a metric class");

SpatialDistribution(const M& metric) : metric { metric } {}

protected:
const M metric;
};

template <SimEngine::type S, class M>
struct Uniform : public SpatialDistribution<S, M> {
Uniform(const M& metric) : SpatialDistribution<S, M> { metric } {}

Inline auto operator()(const coord_t<M::Dim>&,
real_t& nppc_distribution,
real_t& weight_distribution) const {
nppc_distribution = ONE;
weight_distribution = ONE;
}
};

template <SimEngine::type S, class M, int N, class T>
struct Replenish : public SpatialDistribution<S, M> {
using SpatialDistribution<S, M>::metric;
const ndfield_t<M::Dim, N> density;
const idx_t idx;

const T target_density;
const real_t target_max_density;

Replenish(const M& metric,
const ndfield_t<M::Dim, N>& density,
idx_t idx,
const T& target_density,
real_t target_max_density)
: SpatialDistribution<S, M> { metric }
, density { density }
, idx { idx }
, target_density { target_density }
, target_max_density { target_max_density } {}

Inline auto operator()(const coord_t<M::Dim>& x_Ph,
real_t& nppc_distribution,
real_t& weight_distribution) const {
coord_t<M::Dim> x_Cd { ZERO };
metric.template convert<Crd::Ph, Crd::Cd>(x_Ph, x_Cd);
real_t dens { ZERO };
if constexpr (M::Dim == Dim::_1D) {
dens = density(static_cast<ncells_t>(x_Cd[0]) + N_GHOSTS, idx);
} else if constexpr (M::Dim == Dim::_2D) {
dens = density(static_cast<ncells_t>(x_Cd[0]) + N_GHOSTS,
static_cast<ncells_t>(x_Cd[1]) + N_GHOSTS,
idx);
} else if constexpr (M::Dim == Dim::_3D) {
dens = density(static_cast<ncells_t>(x_Cd[0]) + N_GHOSTS,
static_cast<ncells_t>(x_Cd[1]) + N_GHOSTS,
static_cast<ncells_t>(x_Cd[2]) + N_GHOSTS,
idx);
} else {
raise::KernelError(HERE, "Invalid dimension");
}
const auto target = target_density(x_Ph);
if (0.9 * target > dens) {
nppc_distribution = (target - dens) / target_max_density;
weight_distribution = ONE;
} else {
nppc_distribution = ZERO;
weight_distribution = ONE;
}
}
};

template <SimEngine::type S, class M, int N>
struct ReplenishUniform : public SpatialDistribution<S, M> {
using SpatialDistribution<S, M>::metric;
const ndfield_t<M::Dim, N> density;
const idx_t idx;

const real_t target_density;

ReplenishUniform(const M& metric,
const ndfield_t<M::Dim, N>& density,
idx_t idx,
real_t target_density)
: SpatialDistribution<S, M> { metric }
, density { density }
, idx { idx }
, target_density { target_density } {}

Inline auto operator()(const coord_t<M::Dim>& x_Ph,
real_t& nppc_distribution,
real_t& weight_distribution) const {
coord_t<M::Dim> x_Cd { ZERO };
metric.template convert<Crd::Ph, Crd::Cd>(x_Ph, x_Cd);
real_t dens { ZERO };
if constexpr (M::Dim == Dim::_1D) {
dens = density(static_cast<ncells_t>(x_Cd[0]) + N_GHOSTS, idx);
} else if constexpr (M::Dim == Dim::_2D) {
dens = density(static_cast<ncells_t>(x_Cd[0]) + N_GHOSTS,
static_cast<ncells_t>(x_Cd[1]) + N_GHOSTS,
idx);
} else if constexpr (M::Dim == Dim::_3D) {
dens = density(static_cast<ncells_t>(x_Cd[0]) + N_GHOSTS,
static_cast<ncells_t>(x_Cd[1]) + N_GHOSTS,
static_cast<ncells_t>(x_Cd[2]) + N_GHOSTS,
idx);
} else {
raise::KernelError(HERE, "Invalid dimension");
}
if (0.9 * target_density > dens) {
nppc_distribution = (target_density - dens) / target_density;
weight_distribution = ONE;
} else {
nppc_distribution = ZERO;
weight_distribution = ONE;
}
}
};

} // namespace arch

#endif // ARCHETYPES_SPATIAL_DIST_HPP
Loading