aboutsummaryrefslogtreecommitdiff
path: root/Source/Initialization
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Initialization')
-rw-r--r--Source/Initialization/InjectorFlux.H146
-rw-r--r--Source/Initialization/PlasmaInjector.H9
-rw-r--r--Source/Initialization/PlasmaInjector.cpp45
3 files changed, 199 insertions, 1 deletions
diff --git a/Source/Initialization/InjectorFlux.H b/Source/Initialization/InjectorFlux.H
new file mode 100644
index 000000000..adfe75b3e
--- /dev/null
+++ b/Source/Initialization/InjectorFlux.H
@@ -0,0 +1,146 @@
+/* Copyright 2023 Remi Lehe
+ *
+ * This file is part of WarpX.
+ *
+ * License: BSD-3-Clause-LBNL
+ */
+#ifndef INJECTOR_FLUX_H_
+#define INJECTOR_FLUX_H_
+
+#include "Utils/WarpXConst.H"
+
+#include <AMReX.H>
+#include <AMReX_Array.H>
+#include <AMReX_GpuQualifiers.H>
+#include <AMReX_Math.H>
+#include <AMReX_Parser.H>
+#include <AMReX_REAL.H>
+
+#include <cmath>
+#include <string>
+
+// struct whose getFlux returns constant flux.
+struct InjectorFluxConstant
+{
+ InjectorFluxConstant (amrex::Real a_flux) noexcept : m_flux(a_flux) {}
+
+ AMREX_GPU_HOST_DEVICE
+ amrex::Real
+ getFlux (amrex::Real, amrex::Real, amrex::Real, amrex::Real) const noexcept
+ {
+ return m_flux;
+ }
+
+private:
+ amrex::Real m_flux;
+};
+
+// struct whose getFlux returns local flux computed from parser.
+struct InjectorFluxParser
+{
+ InjectorFluxParser (amrex::ParserExecutor<4> const& a_parser) noexcept
+ : m_parser(a_parser) {}
+
+ AMREX_GPU_HOST_DEVICE
+ amrex::Real
+ getFlux (amrex::Real x, amrex::Real y, amrex::Real z, amrex::Real t) const noexcept
+ {
+ return m_parser(x,y,z,t);
+ }
+
+ amrex::ParserExecutor<4> m_parser;
+};
+
+// Base struct for flux injector.
+// InjectorFlux contains a union (called Object) that holds any one
+// instance of:
+// - InjectorFluxConstant : to generate constant flux;
+// - InjectorFluxParser : to generate flux from parser;
+// The choice is made at runtime, depending in the constructor called.
+// This mimics virtual functions.
+struct InjectorFlux
+{
+ // This constructor stores a InjectorFluxConstant in union object.
+ InjectorFlux (InjectorFluxConstant* t, amrex::Real a_flux)
+ : type(Type::constant),
+ object(t,a_flux)
+ { }
+
+ // This constructor stores a InjectorFluxParser in union object.
+ InjectorFlux (InjectorFluxParser* t, amrex::ParserExecutor<4> const& a_parser)
+ : type(Type::parser),
+ object(t,a_parser)
+ { }
+
+ // Explicitly prevent the compiler from generating copy constructors
+ // and copy assignment operators.
+ InjectorFlux (InjectorFlux const&) = delete;
+ InjectorFlux (InjectorFlux&&) = delete;
+ void operator= (InjectorFlux const&) = delete;
+ void operator= (InjectorFlux &&) = delete;
+
+ void clear ()
+ {
+ switch (type)
+ {
+ case Type::constant:
+ case Type::parser:
+ {
+ break;
+ }
+ }
+ }
+
+ // call getFlux from the object stored in the union
+ // (the union is called Object, and the instance is called object).
+ AMREX_GPU_HOST_DEVICE
+ amrex::Real
+ getFlux (amrex::Real x, amrex::Real y, amrex::Real z, amrex::Real t) const noexcept
+ {
+ switch (type)
+ {
+ case Type::parser:
+ {
+ return object.parser.getFlux(x,y,z,t);
+ }
+ case Type::constant:
+ {
+ return object.constant.getFlux(x,y,z,t);
+ }
+ default:
+ {
+ amrex::Abort("InjectorFlux: unknown type");
+ return 0.0;
+ }
+ }
+ }
+
+private:
+ enum struct Type { constant, parser };
+ Type type;
+
+ // An instance of union Object constructs and stores any one of
+ // the objects declared (constant or parser).
+ union Object {
+ Object (InjectorFluxConstant*, amrex::Real a_flux) noexcept
+ : constant(a_flux) {}
+ Object (InjectorFluxParser*, amrex::ParserExecutor<4> const& a_parser) noexcept
+ : parser(a_parser) {}
+ InjectorFluxConstant constant;
+ InjectorFluxParser parser;
+ };
+ Object object;
+};
+
+// In order for InjectorFlux to be trivially copyable, its destructor
+// must be trivial. So we have to rely on a custom deleter for unique_ptr.
+struct InjectorFluxDeleter {
+ void operator () (InjectorFlux* p) const {
+ if (p) {
+ p->clear();
+ delete p;
+ }
+ }
+};
+
+#endif
diff --git a/Source/Initialization/PlasmaInjector.H b/Source/Initialization/PlasmaInjector.H
index c841b6f86..0f33aa062 100644
--- a/Source/Initialization/PlasmaInjector.H
+++ b/Source/Initialization/PlasmaInjector.H
@@ -10,6 +10,7 @@
#define PLASMA_INJECTOR_H_
#include "InjectorDensity.H"
+#include "InjectorFlux.H"
#include "InjectorMomentum.H"
#include "TemperatureProperties.H"
#include "VelocityProperties.H"
@@ -119,6 +120,7 @@ public:
bool radially_weighted = true;
std::string str_density_function;
+ std::string str_flux_function;
std::string str_momentum_function_ux;
std::string str_momentum_function_uy;
std::string str_momentum_function_uz;
@@ -131,6 +133,7 @@ public:
InjectorPosition* getInjectorPosition ();
InjectorDensity* getInjectorDensity ();
+ InjectorFlux* getInjectorFlux ();
InjectorMomentum* getInjectorMomentum ();
protected:
@@ -140,6 +143,7 @@ protected:
PhysicalSpecies physical_species = PhysicalSpecies::unspecified;
amrex::Real density;
+ amrex::Real flux;
int species_id;
std::string species_name;
@@ -151,6 +155,10 @@ protected:
InjectorDensity* d_inj_rho = nullptr;
std::unique_ptr<amrex::Parser> density_parser;
+ std::unique_ptr<InjectorFlux,InjectorFluxDeleter> h_inj_flux;
+ InjectorFlux* d_inj_flux = nullptr;
+ std::unique_ptr<amrex::Parser> flux_parser;
+
std::unique_ptr<InjectorMomentum,InjectorMomentumDeleter> h_inj_mom;
InjectorMomentum* d_inj_mom = nullptr;
std::unique_ptr<amrex::Parser> ux_parser;
@@ -163,6 +171,7 @@ protected:
std::unique_ptr<VelocityProperties> h_mom_vel;
void parseDensity (const amrex::ParmParse& pp);
+ void parseFlux (const amrex::ParmParse& pp);
void parseMomentum (const amrex::ParmParse& pp);
};
diff --git a/Source/Initialization/PlasmaInjector.cpp b/Source/Initialization/PlasmaInjector.cpp
index 22c72f580..865e531e7 100644
--- a/Source/Initialization/PlasmaInjector.cpp
+++ b/Source/Initialization/PlasmaInjector.cpp
@@ -342,7 +342,7 @@ PlasmaInjector::PlasmaInjector (int ispecies, const std::string& name)
(InjectorPositionRandomPlane*)nullptr,
xmin, xmax, ymin, ymax, zmin, zmax,
flux_normal_axis);
- parseDensity(pp_species_name);
+ parseFlux(pp_species_name);
parseMomentum(pp_species_name);
} else if (injection_style == "nuniformpercell") {
// Note that for RZ, three numbers are expected, r, theta, and z.
@@ -504,6 +504,16 @@ PlasmaInjector::PlasmaInjector (int ispecies, const std::string& name)
#endif
}
+ if (h_inj_flux) {
+#ifdef AMREX_USE_GPU
+ d_inj_flux = static_cast<InjectorFlux*>
+ (amrex::The_Arena()->alloc(sizeof(InjectorFlux)));
+ amrex::Gpu::htod_memcpy_async(d_inj_flux, h_inj_flux.get(), sizeof(InjectorFlux));
+#else
+ d_inj_flux = h_inj_flux.get();
+#endif
+ }
+
if (h_inj_mom) {
#ifdef AMREX_USE_GPU
d_inj_mom = static_cast<InjectorMomentum*>
@@ -569,6 +579,33 @@ void PlasmaInjector::parseDensity (const amrex::ParmParse& pp)
}
}
+// Depending on injection type at runtime, initialize inj_flux
+// so that inj_flux->getFlux calls
+// InjectorFlux[Constant or Parser or etc.].getFlux.
+void PlasmaInjector::parseFlux (const amrex::ParmParse& pp)
+{
+ // parse flux information
+ std::string flux_prof_s;
+ pp.get("flux_profile", flux_prof_s);
+ std::transform(flux_prof_s.begin(), flux_prof_s.end(),
+ flux_prof_s.begin(), ::tolower);
+ if (flux_prof_s == "constant") {
+ utils::parser::getWithParser(pp, "flux", flux);
+ // Construct InjectorFlux with InjectorFluxConstant.
+ h_inj_flux.reset(new InjectorFlux((InjectorFluxConstant*)nullptr, flux));
+ } else if (flux_prof_s == "parse_flux_function") {
+ utils::parser::Store_parserString(
+ pp, "flux_function(x,y,z,t)", str_flux_function);
+ // Construct InjectorFlux with InjectorFluxParser.
+ flux_parser = std::make_unique<amrex::Parser>(
+ utils::parser::makeParser(str_flux_function,{"x","y","z","t"}));
+ h_inj_flux.reset(new InjectorFlux((InjectorFluxParser*)nullptr,
+ flux_parser->compile<4>()));
+ } else {
+ StringParseAbortMessage("Flux profile type", flux_prof_s);
+ }
+}
+
// Depending on injection type at runtime, initialize inj_mom
// so that inj_mom->getMomentum calls
// InjectorMomentum[Constant or Gaussian or etc.].getMomentum.
@@ -731,6 +768,12 @@ PlasmaInjector::getInjectorDensity ()
return d_inj_rho;
}
+InjectorFlux*
+PlasmaInjector::getInjectorFlux ()
+{
+ return d_inj_flux;
+}
+
InjectorMomentum*
PlasmaInjector::getInjectorMomentum ()
{