aboutsummaryrefslogtreecommitdiff
path: root/Source/Initialization/WarpXInitData.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Initialization/WarpXInitData.cpp')
-rw-r--r--Source/Initialization/WarpXInitData.cpp356
1 files changed, 349 insertions, 7 deletions
diff --git a/Source/Initialization/WarpXInitData.cpp b/Source/Initialization/WarpXInitData.cpp
index 29c9a8955..2166adbe2 100644
--- a/Source/Initialization/WarpXInitData.cpp
+++ b/Source/Initialization/WarpXInitData.cpp
@@ -10,6 +10,8 @@
#ifdef BL_USE_SENSEI_INSITU
#include <AMReX_AmrMeshInSituBridge.H>
#endif
+#include <GpuParser.H>
+
using namespace amrex;
@@ -231,23 +233,228 @@ WarpX::PostRestart ()
mypc->PostRestart();
}
+
+namespace {
+WarpXParser makeParser (std::string const& parse_function)
+{
+ WarpXParser parser(parse_function);
+ parser.registerVariables({"x","y","z"});
+ ParmParse pp("my_constants");
+ std::set<std::string> symbols = parser.symbols();
+ symbols.erase("x");
+ symbols.erase("y");
+ symbols.erase("z");
+ for (auto it = symbols.begin(); it != symbols.end(); ) {
+ Real v;
+ if (pp.query(it->c_str(), v)) {
+ parser.setConstant(*it, v);
+ it = symbols.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ for (auto const& s : symbols) {
+ amrex::Abort(" ExternalEBFieldOnGrid::makeParser::Unknown symbol "+s);
+ }
+ return parser;
+}
+}
+
+
+
+
+/* \brief
+ * This function initializes E, B, rho, and F, at all the levels
+ * of the multifab. rho and F are initialized with 0.
+ * The E and B fields are initialized using user-defined inputs.
+ * The initialization type is set using "B_ext_grid_init_style"
+ * and "E_ext_grid_init_style". The initialization style is set to "default"
+ * if not explicitly defined by the user, and the E and B fields are
+ * initialized with E_external_grid and B_external_grid, respectively, each with
+ * a default value of 0.
+ * If the initialization type for the E and B field is "constant",
+ * then, the E and B fields at all the levels are initialized with
+ * user-defined values for E_external_grid and B_external_grid.
+ * If the initialization type for B-field is set to
+ * "parse_B_ext_grid_function", then, the parser is used to read
+ * Bx_external_grid_function(x,y,z), By_external_grid_function(x,y,z),
+ * and Bz_external_grid_function(x,y,z).
+ * Similarly, if the E-field initialization type is set to
+ * "parse_E_ext_grid_function", then, the parser is used to read
+ * Ex_external_grid_function(x,y,z), Ey_external_grid_function(x,y,z),
+ * and Ex_external_grid_function(x,y,z). The parser for the E and B
+ * initialization assumes that the function has three independent
+ * variables, at max, namely, x, y, z. However, any number of constants
+ * can be used in the function used to define the E and B fields on the grid.
+ */
+
void
WarpX::InitLevelData (int lev, Real time)
{
+
+ ParmParse pp("warpx");
+
+ // default values of E_external_grid and B_external_grid
+ // are used to set the E and B field when "constant" or
+ // "parser" is not explicitly used in the input.
+ pp.query("B_ext_grid_init_style", B_ext_grid_s);
+ std::transform(B_ext_grid_s.begin(),
+ B_ext_grid_s.end(),
+ B_ext_grid_s.begin(),
+ ::tolower);
+
+ pp.query("E_ext_grid_init_style", E_ext_grid_s);
+ std::transform(E_ext_grid_s.begin(),
+ E_ext_grid_s.end(),
+ E_ext_grid_s.begin(),
+ ::tolower);
+
+ // if the input string is "constant", the values for the
+ // external grid must be provided in the input.
+ if (B_ext_grid_s == "constant")
+ pp.getarr("B_external_grid", B_external_grid);
+
+ // if the input string is "constant", the values for the
+ // external grid must be provided in the input.
+ if (E_ext_grid_s == "constant")
+ pp.getarr("E_external_grid", E_external_grid);
+
for (int i = 0; i < 3; ++i) {
current_fp[lev][i]->setVal(0.0);
- Efield_fp[lev][i]->setVal(E_external_grid[i]);
- Bfield_fp[lev][i]->setVal(B_external_grid[i]);
+ if (B_ext_grid_s == "constant" || B_ext_grid_s == "default")
+ Bfield_fp[lev][i]->setVal(B_external_grid[i]);
+ if (E_ext_grid_s == "constant" || E_ext_grid_s == "default")
+ Efield_fp[lev][i]->setVal(E_external_grid[i]);
+ }
+
+ if (B_ext_grid_s == "parse_b_ext_grid_function") {
+
+ std::vector<std::string> f;
+ // Parse Bx_external_grid_function
+ pp.getarr("Bx_external_grid_function(x,y,z)", f);
+ str_Bx_ext_grid_function.clear();
+ for (auto const& s : f) {
+ str_Bx_ext_grid_function += s;
+ }
+ f.clear();
+
+ // Parse By_external_grid_function
+ pp.getarr("By_external_grid_function(x,y,z)", f);
+ str_By_ext_grid_function.clear();
+ for (auto const& s : f) {
+ str_By_ext_grid_function += s;
+ }
+ f.clear();
+
+ // Parse Bz_external_grid_function
+ pp.getarr("Bz_external_grid_function(x,y,z)", f);
+ str_Bz_ext_grid_function.clear();
+ for (auto const& s : f) {
+ str_Bz_ext_grid_function += s;
+ }
+ f.clear();
+
+ // Initialize Bfield_fp with external function
+ MultiFab *Bx, *By, *Bz;
+ Bx = Bfield_fp[lev][0].get();
+ By = Bfield_fp[lev][1].get();
+ Bz = Bfield_fp[lev][2].get();
+
+ bool B_flag = 1;
+ InitializeExternalFieldsOnGridUsingParser(Bx, By, Bz, lev, B_flag);
+ }
+
+ if (E_ext_grid_s == "parse_e_ext_grid_function") {
+
+ std::vector<std::string> f;
+ // Parse Ex_external_grid_function
+ pp.getarr("Ex_external_grid_function(x,y,z)", f);
+ str_Ex_ext_grid_function.clear();
+ for (auto const& s : f) {
+ str_Ex_ext_grid_function += s;
+ }
+ f.clear();
+
+ // Parse Ey_external_grid_function
+ pp.getarr("Ey_external_grid_function(x,y,z)", f);
+ str_Ey_ext_grid_function.clear();
+ for (auto const& s : f) {
+ str_Ey_ext_grid_function += s;
+ }
+ f.clear();
+
+ // Parse Ez_external_grid_function
+ pp.getarr("Ez_external_grid_function(x,y,z)", f);
+ str_Ez_ext_grid_function.clear();
+ for (auto const& s : f) {
+ str_Ez_ext_grid_function += s;
+ }
+ f.clear();
+
+ // Initialize Efield_fp with external function
+ MultiFab *Ex, *Ey, *Ez;
+ Ex = Efield_fp[lev][0].get();
+ Ey = Efield_fp[lev][1].get();
+ Ez = Efield_fp[lev][2].get();
+
+ bool B_flag = 0;
+ InitializeExternalFieldsOnGridUsingParser(Ex, Ey, Ez, lev, B_flag);
+
}
if (lev > 0) {
for (int i = 0; i < 3; ++i) {
- Efield_aux[lev][i]->setVal(E_external_grid[i]);
- Bfield_aux[lev][i]->setVal(B_external_grid[i]);
-
current_cp[lev][i]->setVal(0.0);
- Efield_cp[lev][i]->setVal(E_external_grid[i]);
- Bfield_cp[lev][i]->setVal(B_external_grid[i]);
+ if (B_ext_grid_s == "constant" || B_ext_grid_s == "default") {
+ Bfield_aux[lev][i]->setVal(B_external_grid[i]);
+ Bfield_cp[lev][i]->setVal(B_external_grid[i]);
+ }
+ if (E_ext_grid_s == "constant" || E_ext_grid_s == "default") {
+ Efield_aux[lev][i]->setVal(E_external_grid[i]);
+ Efield_cp[lev][i]->setVal(E_external_grid[i]);
+ }
+ }
+ if (B_ext_grid_s == "parse_b_ext_grid_function") {
+ MultiFab *Bx_aux, *By_aux, *Bz_aux;
+ Bx_aux = Bfield_aux[lev][0].get();
+ By_aux = Bfield_aux[lev][1].get();
+ Bz_aux = Bfield_aux[lev][2].get();
+
+ // Setting b_flag to 1 since we are initializing
+ // B_external on the grid.
+ bool B_flag = 1;
+ InitializeExternalFieldsOnGridUsingParser(Bx_aux, By_aux,
+ Bz_aux, lev, B_flag);
+
+ MultiFab *Bx_cp, *By_cp, *Bz_cp;
+ Bx_cp = Bfield_cp[lev][0].get();
+ By_cp = Bfield_cp[lev][1].get();
+ Bz_cp = Bfield_cp[lev][2].get();
+
+ InitializeExternalFieldsOnGridUsingParser(Bx_cp, By_cp,
+ Bz_cp, lev, B_flag);
+
+ }
+ if (E_ext_grid_s == "parse_e_ext_grid_function") {
+
+ MultiFab *Ex_aux, *Ey_aux, *Ez_aux;
+ Ex_aux = Efield_aux[lev][0].get();
+ Ey_aux = Efield_aux[lev][1].get();
+ Ez_aux = Efield_aux[lev][2].get();
+ // Setting b_flag to zero since we are initializing
+ // E_external on the grid here.
+ bool B_flag = 0;
+ InitializeExternalFieldsOnGridUsingParser(Ex_aux, Ey_aux,
+ Ez_aux, lev, B_flag);
+
+ MultiFab *Ex_cp, *Ey_cp, *Ez_cp;
+ Ex_cp = Efield_cp[lev][0].get();
+ Ey_cp = Efield_cp[lev][1].get();
+ Ez_cp = Efield_cp[lev][2].get();
+
+ InitializeExternalFieldsOnGridUsingParser(Ex_cp, Ey_cp,
+ Ez_cp, lev, B_flag);
+
}
}
@@ -306,3 +513,138 @@ WarpX::InitLevelDataFFT (int lev, Real time)
}
#endif
+
+/* \brief
+ * This function initializes the E and B fields on each level
+ * using the parser and the user-defined function for the external fields.
+ * Depending on the bool value of the B_flag, the subroutine will parse
+ * the Bx_/By_/Bz_external_grid_function (if B_flag==1)
+ * or parse the Ex_/Ey_/Ez_external_grid_function (if B_flag==0).
+ * Then, the B or E multifab is initialized based on the (x,y,z) position
+ * on the staggered yee-grid or cell-centered grid.
+ */
+
+void
+WarpX::InitializeExternalFieldsOnGridUsingParser (
+ MultiFab *mfx, MultiFab *mfy, MultiFab *mfz,
+ const int lev, const bool B_flag)
+{
+ std::unique_ptr<ParserWrapper> xfield_parsewrap;
+ std::unique_ptr<ParserWrapper> yfield_parsewrap;
+ std::unique_ptr<ParserWrapper> zfield_parsewrap;
+
+ if (B_flag == 1) {
+ xfield_parsewrap.reset(new ParserWrapper
+ (makeParser(str_Bx_ext_grid_function)));
+ yfield_parsewrap.reset(new ParserWrapper
+ (makeParser(str_By_ext_grid_function)));
+ zfield_parsewrap.reset(new ParserWrapper
+ (makeParser(str_Bz_ext_grid_function)));
+ } else {
+ xfield_parsewrap.reset(new ParserWrapper
+ (makeParser(str_Ex_ext_grid_function)));
+ yfield_parsewrap.reset(new ParserWrapper
+ (makeParser(str_Ey_ext_grid_function)));
+ zfield_parsewrap.reset(new ParserWrapper
+ (makeParser(str_Ez_ext_grid_function)));
+ }
+
+ ParserWrapper *xfield_wrap = xfield_parsewrap.get();
+ ParserWrapper *yfield_wrap = yfield_parsewrap.get();
+ ParserWrapper *zfield_wrap = zfield_parsewrap.get();
+
+ const auto dx_lev = geom[lev].CellSizeArray();
+ const RealBox& real_box = geom[lev].ProbDomain();
+ for ( MFIter mfi(*mfx, TilingIfNotGPU()); mfi.isValid(); ++mfi)
+ {
+ IntVect x_nodal_flag, y_nodal_flag, z_nodal_flag;
+ if (B_flag == 1) {
+ x_nodal_flag = Bx_nodal_flag;
+ y_nodal_flag = By_nodal_flag;
+ z_nodal_flag = Bz_nodal_flag;
+ } else {
+ x_nodal_flag = Ex_nodal_flag;
+ y_nodal_flag = Ey_nodal_flag;
+ z_nodal_flag = Ez_nodal_flag;
+ }
+ const Box& tbx = mfi.tilebox(x_nodal_flag);
+ const Box& tby = mfi.tilebox(y_nodal_flag);
+ const Box& tbz = mfi.tilebox(z_nodal_flag);
+
+ auto const& mfxfab = mfx->array(mfi);
+ auto const& mfyfab = mfy->array(mfi);
+ auto const& mfzfab = mfz->array(mfi);
+
+ auto const& mfx_IndexType = (*mfx).ixType();
+ auto const& mfy_IndexType = (*mfy).ixType();
+ auto const& mfz_IndexType = (*mfz).ixType();
+
+ // Initialize IntVect based on the index type of multiFab
+ // 0 if cell-centered, 1 if node-centered.
+ IntVect mfx_type(AMREX_D_DECL(0,0,0));
+ IntVect mfy_type(AMREX_D_DECL(0,0,0));
+ IntVect mfz_type(AMREX_D_DECL(0,0,0));
+
+ for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
+ mfx_type[idim] = mfx_IndexType.nodeCentered(idim);
+ mfy_type[idim] = mfy_IndexType.nodeCentered(idim);
+ mfz_type[idim] = mfz_IndexType.nodeCentered(idim);
+ }
+
+ amrex::ParallelFor (tbx, tby, tbz,
+ [=] AMREX_GPU_DEVICE (int i, int j, int k) {
+ // Shift required in the x-, y-, or z- position
+ // depending on the index type of the multifab
+ Real fac_x = (1.0 - mfx_type[0]) * dx_lev[0]*0.5;
+ Real x = i*dx_lev[0] + real_box.lo(0) + fac_x;
+#if (AMREX_SPACEDIM==2)
+ Real y = 0.0;
+ Real fac_z = (1.0 - mfx_type[1]) * dx_lev[1]*0.5;
+ Real z = j*dx_lev[1] + real_box.lo(1) + fac_z;
+#else
+ Real fac_y = (1.0 - mfx_type[1]) * dx_lev[1]*0.5;
+ Real y = j*dx_lev[1] + real_box.lo(1) + fac_y;
+ Real fac_z = (1.0 - mfx_type[2]) * dx_lev[2]*0.5;
+ Real z = k*dx_lev[2] + real_box.lo(2) + fac_z;
+#endif
+ // Initialize the x-component of the field.
+ mfxfab(i,j,k) = xfield_wrap->getField(x,y,z);
+ },
+ [=] AMREX_GPU_DEVICE (int i, int j, int k) {
+ Real fac_x = (1.0 - mfy_type[0]) * dx_lev[0]*0.5;
+ Real x = i*dx_lev[0] + real_box.lo(0) + fac_x;
+#if (AMREX_SPACEDIM==2)
+ Real y = 0.0;
+ Real fac_z = (1.0 - mfx_type[1]) * dx_lev[1]*0.5;
+ Real z = j*dx_lev[1] + real_box.lo(1) + fac_z;
+#elif (AMREX_SPACEDIM==3)
+ Real fac_y = (1.0 - mfx_type[1]) * dx_lev[1]*0.5;
+ Real y = j*dx_lev[1] + real_box.lo(1) + fac_y;
+ Real fac_z = (1.0 - mfx_type[2]) * dx_lev[2]*0.5;
+ Real z = k*dx_lev[2] + real_box.lo(2) + fac_z;
+#endif
+ // Initialize the y-component of the field.
+ mfyfab(i,j,k) = yfield_wrap->getField(x,y,z);
+ },
+ [=] AMREX_GPU_DEVICE (int i, int j, int k) {
+ Real fac_x = (1.0 - mfz_type[0]) * dx_lev[0]*0.5;
+ Real x = i*dx_lev[0] + real_box.lo(0) + fac_x;
+#if (AMREX_SPACEDIM==2)
+ Real y = 0.0;
+ Real fac_z = (1.0 - mfx_type[1]) * dx_lev[1]*0.5;
+ Real z = j*dx_lev[1] + real_box.lo(1) + fac_z;
+#elif (AMREX_SPACEDIM==3)
+ Real fac_y = (1.0 - mfx_type[1]) * dx_lev[1]*0.5;
+ Real y = j*dx_lev[1] + real_box.lo(1) + fac_y;
+ Real fac_z = (1.0 - mfz_type[2]) * dx_lev[2]*0.5;
+ Real z = k*dx_lev[2] + real_box.lo(2) + fac_z;
+#endif
+ // Initialize the z-component of the field.
+ mfzfab(i,j,k) = zfield_wrap->getField(x,y,z);
+ },
+ amrex::Gpu::numThreadsPerBlockParallelFor() * sizeof(double) * 3
+ );
+
+ }
+
+}