Skip to content

Commit 841d7ee

Browse files
authored
General parser function for external fields (#5349)
This feature replaces the InitializeExternalFieldsOnGridUsingParser with a more general function ComputeExternalFieldOnGridUsingParser. The new function takes parsed functions with four dimensions (x,y,z,t), so that it can be used to evaluate functions throughout the simulation, for example time-dependent external fields. The function ComputeExternalFieldOnGridUsingParser has optional edge length and face areas. --------- Co-authored-by: Kristoffer Lindvall <[email protected]>
1 parent 6757b4c commit 841d7ee

File tree

8 files changed

+144
-298
lines changed

8 files changed

+144
-298
lines changed

Source/FieldSolver/FiniteDifferenceSolver/HybridPICModel/HybridPICModel.H

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,7 @@ public:
5353
* external current multifab. Note the external current can be a function
5454
* of time and therefore this should be re-evaluated at every step.
5555
*/
56-
void GetCurrentExternal (
57-
ablastr::fields::MultiLevelVectorField const& edge_lengths
58-
);
59-
void GetCurrentExternal (
60-
ablastr::fields::VectorField const& edge_lengths,
61-
int lev
62-
);
56+
void GetCurrentExternal ();
6357

6458
/**
6559
* \brief

Source/FieldSolver/FiniteDifferenceSolver/HybridPICModel/HybridPICModel.cpp

Lines changed: 17 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -221,167 +221,32 @@ void HybridPICModel::InitData ()
221221
// if the current is time dependent which is what needs to be done to
222222
// write time independent fields on the first step.
223223
for (int lev = 0; lev <= warpx.finestLevel(); ++lev) {
224-
auto edge_lengths = std::array<std::unique_ptr<amrex::MultiFab>, 3>();
225-
#ifdef AMREX_USE_EB
226-
if (EB::enabled()) {
227-
using ablastr::fields::Direction;
228-
auto const & edge_lengths_x = *warpx.m_fields.get(FieldType::edge_lengths, Direction{0}, lev);
229-
auto const & edge_lengths_y = *warpx.m_fields.get(FieldType::edge_lengths, Direction{1}, lev);
230-
auto const & edge_lengths_z = *warpx.m_fields.get(FieldType::edge_lengths, Direction{2}, lev);
231-
232-
edge_lengths = std::array< std::unique_ptr<amrex::MultiFab>, 3 >{
233-
std::make_unique<amrex::MultiFab>(
234-
edge_lengths_x, amrex::make_alias, 0, edge_lengths_x.nComp()),
235-
std::make_unique<amrex::MultiFab>(
236-
edge_lengths_y, amrex::make_alias, 0, edge_lengths_y.nComp()),
237-
std::make_unique<amrex::MultiFab>(
238-
edge_lengths_z, amrex::make_alias, 0, edge_lengths_z.nComp())
239-
};
240-
}
241-
#endif
242-
GetCurrentExternal(ablastr::fields::a2m(edge_lengths), lev);
224+
warpx.ComputeExternalFieldOnGridUsingParser(
225+
FieldType::hybrid_current_fp_external,
226+
m_J_external[0],
227+
m_J_external[1],
228+
m_J_external[2],
229+
lev, PatchType::fine, 'e',
230+
warpx.m_fields.get_alldirs(FieldType::edge_lengths, lev),
231+
warpx.m_fields.get_alldirs(FieldType::face_areas, lev));
243232
}
244233
}
245234

246-
void HybridPICModel::GetCurrentExternal (
247-
ablastr::fields::MultiLevelVectorField const& edge_lengths)
235+
void HybridPICModel::GetCurrentExternal ()
248236
{
249237
if (!m_external_field_has_time_dependence) { return; }
250238

251239
auto& warpx = WarpX::GetInstance();
252240
for (int lev = 0; lev <= warpx.finestLevel(); ++lev)
253241
{
254-
GetCurrentExternal(edge_lengths[lev], lev);
255-
}
256-
}
257-
258-
259-
void HybridPICModel::GetCurrentExternal (
260-
ablastr::fields::VectorField const& edge_lengths,
261-
int lev)
262-
{
263-
// This logic matches closely to WarpX::InitializeExternalFieldsOnGridUsingParser
264-
// except that the parsers include time dependence.
265-
auto & warpx = WarpX::GetInstance();
266-
267-
auto t = warpx.gett_new(lev);
268-
269-
auto dx_lev = warpx.Geom(lev).CellSizeArray();
270-
const RealBox& real_box = warpx.Geom(lev).ProbDomain();
271-
272-
using ablastr::fields::Direction;
273-
amrex::MultiFab * mfx = warpx.m_fields.get(FieldType::hybrid_current_fp_external, Direction{0}, lev);
274-
amrex::MultiFab * mfy = warpx.m_fields.get(FieldType::hybrid_current_fp_external, Direction{1}, lev);
275-
amrex::MultiFab * mfz = warpx.m_fields.get(FieldType::hybrid_current_fp_external, Direction{2}, lev);
276-
277-
const amrex::IntVect x_nodal_flag = mfx->ixType().toIntVect();
278-
const amrex::IntVect y_nodal_flag = mfy->ixType().toIntVect();
279-
const amrex::IntVect z_nodal_flag = mfz->ixType().toIntVect();
280-
281-
// avoid implicit lambda capture
282-
auto Jx_external = m_J_external[0];
283-
auto Jy_external = m_J_external[1];
284-
auto Jz_external = m_J_external[2];
285-
286-
for ( MFIter mfi(*mfx, TilingIfNotGPU()); mfi.isValid(); ++mfi)
287-
{
288-
const amrex::Box& tbx = mfi.tilebox( x_nodal_flag, mfx->nGrowVect() );
289-
const amrex::Box& tby = mfi.tilebox( y_nodal_flag, mfy->nGrowVect() );
290-
const amrex::Box& tbz = mfi.tilebox( z_nodal_flag, mfz->nGrowVect() );
291-
292-
auto const& mfxfab = mfx->array(mfi);
293-
auto const& mfyfab = mfy->array(mfi);
294-
auto const& mfzfab = mfz->array(mfi);
295-
296-
amrex::Array4<amrex::Real> lx, ly, lz;
297-
if (EB::enabled()) {
298-
lx = edge_lengths[0]->array(mfi);
299-
ly = edge_lengths[1]->array(mfi);
300-
lz = edge_lengths[2]->array(mfi);
301-
}
302-
303-
amrex::ParallelFor (tbx, tby, tbz,
304-
[=] AMREX_GPU_DEVICE (int i, int j, int k) {
305-
// skip if node is covered by an embedded boundary
306-
if (lx && lx(i, j, k) <= 0) { return; }
307-
308-
// Shift required in the x-, y-, or z- position
309-
// depending on the index type of the multifab
310-
#if defined(WARPX_DIM_1D_Z)
311-
const amrex::Real x = 0._rt;
312-
const amrex::Real y = 0._rt;
313-
const amrex::Real fac_z = (1._rt - x_nodal_flag[0]) * dx_lev[0] * 0.5_rt;
314-
const amrex::Real z = j*dx_lev[0] + real_box.lo(0) + fac_z;
315-
#elif defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ)
316-
const amrex::Real fac_x = (1._rt - x_nodal_flag[0]) * dx_lev[0] * 0.5_rt;
317-
const amrex::Real x = i*dx_lev[0] + real_box.lo(0) + fac_x;
318-
const amrex::Real y = 0._rt;
319-
const amrex::Real fac_z = (1._rt - x_nodal_flag[1]) * dx_lev[1] * 0.5_rt;
320-
const amrex::Real z = j*dx_lev[1] + real_box.lo(1) + fac_z;
321-
#else
322-
const amrex::Real fac_x = (1._rt - x_nodal_flag[0]) * dx_lev[0] * 0.5_rt;
323-
const amrex::Real x = i*dx_lev[0] + real_box.lo(0) + fac_x;
324-
const amrex::Real fac_y = (1._rt - x_nodal_flag[1]) * dx_lev[1] * 0.5_rt;
325-
const amrex::Real y = j*dx_lev[1] + real_box.lo(1) + fac_y;
326-
const amrex::Real fac_z = (1._rt - x_nodal_flag[2]) * dx_lev[2] * 0.5_rt;
327-
const amrex::Real z = k*dx_lev[2] + real_box.lo(2) + fac_z;
328-
#endif
329-
// Initialize the x-component of the field.
330-
mfxfab(i,j,k) = Jx_external(x,y,z,t);
331-
},
332-
[=] AMREX_GPU_DEVICE (int i, int j, int k) {
333-
// skip if node is covered by an embedded boundary
334-
if (ly && ly(i, j, k) <= 0) { return; }
335-
336-
#if defined(WARPX_DIM_1D_Z)
337-
const amrex::Real x = 0._rt;
338-
const amrex::Real y = 0._rt;
339-
const amrex::Real fac_z = (1._rt - y_nodal_flag[0]) * dx_lev[0] * 0.5_rt;
340-
const amrex::Real z = j*dx_lev[0] + real_box.lo(0) + fac_z;
341-
#elif defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ)
342-
const amrex::Real fac_x = (1._rt - y_nodal_flag[0]) * dx_lev[0] * 0.5_rt;
343-
const amrex::Real x = i*dx_lev[0] + real_box.lo(0) + fac_x;
344-
const amrex::Real y = 0._rt;
345-
const amrex::Real fac_z = (1._rt - y_nodal_flag[1]) * dx_lev[1] * 0.5_rt;
346-
const amrex::Real z = j*dx_lev[1] + real_box.lo(1) + fac_z;
347-
#elif defined(WARPX_DIM_3D)
348-
const amrex::Real fac_x = (1._rt - y_nodal_flag[0]) * dx_lev[0] * 0.5_rt;
349-
const amrex::Real x = i*dx_lev[0] + real_box.lo(0) + fac_x;
350-
const amrex::Real fac_y = (1._rt - y_nodal_flag[1]) * dx_lev[1] * 0.5_rt;
351-
const amrex::Real y = j*dx_lev[1] + real_box.lo(1) + fac_y;
352-
const amrex::Real fac_z = (1._rt - y_nodal_flag[2]) * dx_lev[2] * 0.5_rt;
353-
const amrex::Real z = k*dx_lev[2] + real_box.lo(2) + fac_z;
354-
#endif
355-
// Initialize the y-component of the field.
356-
mfyfab(i,j,k) = Jy_external(x,y,z,t);
357-
},
358-
[=] AMREX_GPU_DEVICE (int i, int j, int k) {
359-
// skip if node is covered by an embedded boundary
360-
if (lz && lz(i, j, k) <= 0) { return; }
361-
362-
#if defined(WARPX_DIM_1D_Z)
363-
const amrex::Real x = 0._rt;
364-
const amrex::Real y = 0._rt;
365-
const amrex::Real fac_z = (1._rt - z_nodal_flag[0]) * dx_lev[0] * 0.5_rt;
366-
const amrex::Real z = j*dx_lev[0] + real_box.lo(0) + fac_z;
367-
#elif defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ)
368-
const amrex::Real fac_x = (1._rt - z_nodal_flag[0]) * dx_lev[0] * 0.5_rt;
369-
const amrex::Real x = i*dx_lev[0] + real_box.lo(0) + fac_x;
370-
const amrex::Real y = 0._rt;
371-
const amrex::Real fac_z = (1._rt - z_nodal_flag[1]) * dx_lev[1] * 0.5_rt;
372-
const amrex::Real z = j*dx_lev[1] + real_box.lo(1) + fac_z;
373-
#elif defined(WARPX_DIM_3D)
374-
const amrex::Real fac_x = (1._rt - z_nodal_flag[0]) * dx_lev[0] * 0.5_rt;
375-
const amrex::Real x = i*dx_lev[0] + real_box.lo(0) + fac_x;
376-
const amrex::Real fac_y = (1._rt - z_nodal_flag[1]) * dx_lev[1] * 0.5_rt;
377-
const amrex::Real y = j*dx_lev[1] + real_box.lo(1) + fac_y;
378-
const amrex::Real fac_z = (1._rt - z_nodal_flag[2]) * dx_lev[2] * 0.5_rt;
379-
const amrex::Real z = k*dx_lev[2] + real_box.lo(2) + fac_z;
380-
#endif
381-
// Initialize the z-component of the field.
382-
mfzfab(i,j,k) = Jz_external(x,y,z,t);
383-
}
384-
);
242+
warpx.ComputeExternalFieldOnGridUsingParser(
243+
FieldType::hybrid_current_fp_external,
244+
m_J_external[0],
245+
m_J_external[1],
246+
m_J_external[2],
247+
lev, PatchType::fine, 'e',
248+
warpx.m_fields.get_alldirs(FieldType::edge_lengths, lev),
249+
warpx.m_fields.get_alldirs(FieldType::face_areas, lev));
385250
}
386251
}
387252

Source/FieldSolver/WarpXPushFieldsHybridPIC.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ void WarpX::HybridPICEvolveFields ()
6868
const int sub_steps = m_hybrid_pic_model->m_substeps;
6969

7070
// Get the external current
71-
m_hybrid_pic_model->GetCurrentExternal(
72-
m_fields.get_mr_levels_alldirs(FieldType::edge_lengths, finest_level));
71+
m_hybrid_pic_model->GetCurrentExternal();
7372

7473
// Reference hybrid-PIC multifabs
7574
ablastr::fields::MultiLevelScalarField rho_fp_temp = m_fields.get_mr_levels(FieldType::hybrid_rho_fp_temp, finest_level);

Source/Fluids/WarpXFluidContainer.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,24 +1010,23 @@ void WarpXFluidContainer::GatherAndPush (
10101010
// External field parsers
10111011
external_e_fields = (m_E_ext_s == "parse_e_ext_function");
10121012
external_b_fields = (m_B_ext_s == "parse_b_ext_function");
1013+
10131014
amrex::ParserExecutor<4> Exfield_parser;
10141015
amrex::ParserExecutor<4> Eyfield_parser;
10151016
amrex::ParserExecutor<4> Ezfield_parser;
10161017
amrex::ParserExecutor<4> Bxfield_parser;
10171018
amrex::ParserExecutor<4> Byfield_parser;
10181019
amrex::ParserExecutor<4> Bzfield_parser;
1020+
10191021
if (external_e_fields){
1020-
constexpr int num_arguments = 4; //x,y,z,t
1021-
Exfield_parser = m_Ex_parser->compile<num_arguments>();
1022-
Eyfield_parser = m_Ey_parser->compile<num_arguments>();
1023-
Ezfield_parser = m_Ez_parser->compile<num_arguments>();
1022+
Exfield_parser = m_Ex_parser->compile<4>();
1023+
Eyfield_parser = m_Ey_parser->compile<4>();
1024+
Ezfield_parser = m_Ez_parser->compile<4>();
10241025
}
1025-
10261026
if (external_b_fields){
1027-
constexpr int num_arguments = 4; //x,y,z,t
1028-
Bxfield_parser = m_Bx_parser->compile<num_arguments>();
1029-
Byfield_parser = m_By_parser->compile<num_arguments>();
1030-
Bzfield_parser = m_Bz_parser->compile<num_arguments>();
1027+
Bxfield_parser = m_Bx_parser->compile<4>();
1028+
Byfield_parser = m_By_parser->compile<4>();
1029+
Bzfield_parser = m_Bz_parser->compile<4>();
10311030
}
10321031

10331032

Source/Initialization/ExternalField.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,11 @@ ExternalFieldParams::ExternalFieldParams(const amrex::ParmParse& pp_warpx)
127127
str_Bz_ext_grid_function);
128128

129129
Bxfield_parser = std::make_unique<amrex::Parser>(
130-
utils::parser::makeParser(str_Bx_ext_grid_function,{"x","y","z"}));
130+
utils::parser::makeParser(str_Bx_ext_grid_function,{"x","y","z","t"}));
131131
Byfield_parser = std::make_unique<amrex::Parser>(
132-
utils::parser::makeParser(str_By_ext_grid_function,{"x","y","z"}));
132+
utils::parser::makeParser(str_By_ext_grid_function,{"x","y","z","t"}));
133133
Bzfield_parser = std::make_unique<amrex::Parser>(
134-
utils::parser::makeParser(str_Bz_ext_grid_function,{"x","y","z"}));
134+
utils::parser::makeParser(str_Bz_ext_grid_function,{"x","y","z","t"}));
135135
}
136136
//___________________________________________________________________________
137137

@@ -163,11 +163,11 @@ ExternalFieldParams::ExternalFieldParams(const amrex::ParmParse& pp_warpx)
163163
str_Ez_ext_grid_function);
164164

165165
Exfield_parser = std::make_unique<amrex::Parser>(
166-
utils::parser::makeParser(str_Ex_ext_grid_function,{"x","y","z"}));
166+
utils::parser::makeParser(str_Ex_ext_grid_function,{"x","y","z","t"}));
167167
Eyfield_parser = std::make_unique<amrex::Parser>(
168-
utils::parser::makeParser(str_Ey_ext_grid_function,{"x","y","z"}));
168+
utils::parser::makeParser(str_Ey_ext_grid_function,{"x","y","z","t"}));
169169
Ezfield_parser = std::make_unique<amrex::Parser>(
170-
utils::parser::makeParser(str_Ez_ext_grid_function,{"x","y","z"}));
170+
utils::parser::makeParser(str_Ez_ext_grid_function,{"x","y","z","t"}));
171171
}
172172
//___________________________________________________________________________
173173

0 commit comments

Comments
 (0)