Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move external field parameters out of WarpX class #4441

9 changes: 5 additions & 4 deletions Source/Initialization/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ foreach(D IN LISTS WarpX_DIMS)
warpx_set_suffix_dims(SD ${D})
target_sources(lib_${SD}
PRIVATE
WarpXAMReXInit.cpp
ExternalField.cpp
GetTemperature.cpp
GetVelocity.cpp
InjectorDensity.cpp
InjectorMomentum.cpp
PlasmaInjector.cpp
WarpXInitData.cpp
TemperatureProperties.cpp
VelocityProperties.cpp
GetTemperature.cpp
GetVelocity.cpp
WarpXAMReXInit.cpp
WarpXInitData.cpp
)
endforeach()
69 changes: 69 additions & 0 deletions Source/Initialization/ExternalField.H
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/* Copyright 2023 Luca Fedeli
*
*
* This file is part of WarpX.
*
* License: BSD-3-Clause-LBNL
*/
#ifndef EXTERNAL_FIELD_H_
#define EXTERNAL_FIELD_H_

#include "ExternalField_fwd.H"

#include <AMReX_Array.H>
#include <AMReX_ParmParse.H>
#include <AMReX_Parser.H>
#include <AMReX_REAL.H>

#include <memory>
#include <string>

enum class ExternalFieldType
{
default_zero,
constant,
parse_ext_grid_function,
read_from_file
};

/**
* \brief Struct to store data related to external electromagnetic fields
* (flags, field values, and field parsers)
*/
struct ExternalFieldParams
{

/**
* \brief The constructor reads and stores the parameters related to the external fields.
* "pp_warpx" must point at the "warpx" parameter group in the inputfile.
*/
ExternalFieldParams(const amrex::ParmParse& pp_warpx);

//! Initial electric field on the grid
amrex::GpuArray<amrex::Real,3> E_external_grid = {0,0,0};
//! Initial magnetic field on the grid
amrex::GpuArray<amrex::Real,3> B_external_grid = {0,0,0};

//! Initialization type for external magnetic field on the grid
ExternalFieldType B_ext_grid_type = ExternalFieldType::default_zero;
//! Initialization type for external electric field on the grid
ExternalFieldType E_ext_grid_type = ExternalFieldType::default_zero;

//! User-defined parser to initialize x-component of the magnetic field on the grid
std::unique_ptr<amrex::Parser> Bxfield_parser;
//! User-defined parser to initialize y-component of the magnetic field on the grid
std::unique_ptr<amrex::Parser> Byfield_parser;
//! User-defined parser to initialize z-component of the magnetic field on the grid
std::unique_ptr<amrex::Parser> Bzfield_parser;
//! User-defined parser to initialize x-component of the electric field on the grid
std::unique_ptr<amrex::Parser> Exfield_parser;
//! User-defined parser to initialize y-component of the electric field on the grid
std::unique_ptr<amrex::Parser> Eyfield_parser;
//! User-defined parser to initialize z-component of the electric field on the grid
std::unique_ptr<amrex::Parser> Ezfield_parser;

//! Path of the file where external fields are stored
std::string external_fields_path;
};

#endif //EXTERNAL_FIELD_H_
175 changes: 175 additions & 0 deletions Source/Initialization/ExternalField.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/* Copyright 2023 Luca Fedeli
*
*
* This file is part of WarpX.
*
* License: BSD-3-Clause-LBNL
*/

#include "ExternalField.H"

#include "Utils/TextMsg.H"
#include "Utils/Parser/ParserUtils.H"

#include <ablastr/warn_manager/WarnManager.H>

#include <algorithm>
#include <vector>

namespace
{

enum class EMFieldType{E, B};

template <EMFieldType T>
ExternalFieldType string_to_external_field_type(std::string s)
{
std::transform(s.begin(), s.end(), s.begin(), ::tolower);

if ( s.empty() || s == "default")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has been suggested as a standard to always use curly braces and not have single line if blocks.

Copy link
Member Author

@lucafedeli88 lucafedeli88 Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure that we follow this rule systematically in WarpX, but it is certainly a good practice! I've added the curly braces.

return ExternalFieldType::default_zero;
else if ( s == "constant")
return ExternalFieldType::constant;
else if ( s == "parse_b_ext_grid_function" || s == "parse_e_ext_grid_function")
return ExternalFieldType::parse_ext_grid_function;
else if ( s == "read_from_file")
return ExternalFieldType::read_from_file;
else
WARPX_ABORT_WITH_MESSAGE(
"'" + s + "' is an unknown external field type!");

if constexpr (T == EMFieldType::E){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic here doesn't look correct. Since the above if blocks call return, it will only get here when s is an unknown field type. Should these checks go in the if block at line 34 above?

Copy link
Member Author

@lucafedeli88 lucafedeli88 Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved the check before this block. As you remarked, the logic was wrong and the second if block was ignored.

WARPX_ALWAYS_ASSERT_WITH_MESSAGE(s != "parse_b_ext_grid_function",
"parse_B_ext_grid_function can be used only for B_ext_grid_init_style");
}
else{
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(s != "parse_e_ext_grid_function",
"parse_E_ext_grid_function can be used only for E_ext_grid_init_style");
}

return ExternalFieldType::default_zero;
}
}

ExternalFieldParams::ExternalFieldParams(const amrex::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.
std::string B_ext_grid_s;
pp_warpx.query("B_ext_grid_init_style", B_ext_grid_s);
B_ext_grid_type = string_to_external_field_type<EMFieldType::B>(B_ext_grid_s);

std::string E_ext_grid_s;
pp_warpx.query("E_ext_grid_init_style", E_ext_grid_s);
E_ext_grid_type = string_to_external_field_type<EMFieldType::E>(E_ext_grid_s);

//
// Constant external field
//

// if the input string is "constant", the values for the
// external grid must be provided in the input.
auto v_B = std::vector<amrex::Real>(3);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for the temporary vector, instead of doing
utils::parser::getArrWithParser(pp_warpx, "B_external_grid", p_external_field->B_external_grid);

Copy link
Member Author

@lucafedeli88 lucafedeli88 Nov 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The reason is that getArrWithParser requires a std::vector as an argument, while I want to store the field value into a GpuArray.

if (B_ext_grid_type == ExternalFieldType::constant)
utils::parser::getArrWithParser(pp_warpx, "B_external_grid", v_B);
std::copy(v_B.begin(), v_B.end(), B_external_grid.begin());

// if the input string is "constant", the values for the
// external grid must be provided in the input.
auto v_E = std::vector<amrex::Real>(3);
if (E_ext_grid_type == ExternalFieldType::constant)
utils::parser::getArrWithParser(pp_warpx, "E_external_grid", v_E);
std::copy(v_E.begin(), v_E.end(), E_external_grid.begin());
//___________________________________________________________________________


//
// External E field with parser
//

// if the input string for the B-field is "parse_b_ext_grid_function",
// then the analytical expression or function must be
// provided in the input file.
if (B_ext_grid_type == ExternalFieldType::parse_ext_grid_function) {

//! Strings storing parser function to initialize the components of the magnetic field on the grid
std::string str_Bx_ext_grid_function;
std::string str_By_ext_grid_function;
std::string str_Bz_ext_grid_function;

#ifdef WARPX_DIM_RZ
std::stringstream warnMsg;
warnMsg << "Parser for external B (r and theta) fields does not work with RZ\n"
<< "The initial Br and Bt fields are currently hardcoded to 0.\n"
<< "The initial Bz field should only be a function of z.\n";
ablastr::warn_manager::WMRecordWarning(
"Inputs", warnMsg.str(), ablastr::warn_manager::WarnPriority::high);
str_Bx_ext_grid_function = "0";
str_By_ext_grid_function = "0";
#else
utils::parser::Store_parserString(pp_warpx, "Bx_external_grid_function(x,y,z)",
str_Bx_ext_grid_function);
utils::parser::Store_parserString(pp_warpx, "By_external_grid_function(x,y,z)",
str_By_ext_grid_function);
#endif
utils::parser::Store_parserString(pp_warpx, "Bz_external_grid_function(x,y,z)",
str_Bz_ext_grid_function);

Bxfield_parser = std::make_unique<amrex::Parser>(
utils::parser::makeParser(str_Bx_ext_grid_function,{"x","y","z"}));
Byfield_parser = std::make_unique<amrex::Parser>(
utils::parser::makeParser(str_By_ext_grid_function,{"x","y","z"}));
Bzfield_parser = std::make_unique<amrex::Parser>(
utils::parser::makeParser(str_Bz_ext_grid_function,{"x","y","z"}));
}
//___________________________________________________________________________


//
// External B field with parser
//

// if the input string for the E-field is "parse_e_ext_grid_function",
// then the analytical expression or function must be
// provided in the input file.
if (E_ext_grid_type == ExternalFieldType::parse_ext_grid_function) {

#ifdef WARPX_DIM_RZ
WARPX_ABORT_WITH_MESSAGE(
"E parser for external fields does not work with RZ -- TO DO");
#endif

//! Strings storing parser function to initialize the components of the electric field on the grid
std::string str_Ex_ext_grid_function;
std::string str_Ey_ext_grid_function;
std::string str_Ez_ext_grid_function;

utils::parser::Store_parserString(pp_warpx, "Ex_external_grid_function(x,y,z)",
str_Ex_ext_grid_function);
utils::parser::Store_parserString(pp_warpx, "Ey_external_grid_function(x,y,z)",
str_Ey_ext_grid_function);
utils::parser::Store_parserString(pp_warpx, "Ez_external_grid_function(x,y,z)",
str_Ez_ext_grid_function);

Exfield_parser = std::make_unique<amrex::Parser>(
utils::parser::makeParser(str_Ex_ext_grid_function,{"x","y","z"}));
Eyfield_parser = std::make_unique<amrex::Parser>(
utils::parser::makeParser(str_Ey_ext_grid_function,{"x","y","z"}));
Ezfield_parser = std::make_unique<amrex::Parser>(
utils::parser::makeParser(str_Ez_ext_grid_function,{"x","y","z"}));
}
//___________________________________________________________________________


//
// External fields from file
//

if (E_ext_grid_type == ExternalFieldType::read_from_file ||
B_ext_grid_type == ExternalFieldType::read_from_file){
std::string read_fields_from_path="./";
pp_warpx.query("read_fields_from_path", external_fields_path);
}
//___________________________________________________________________________
}
13 changes: 13 additions & 0 deletions Source/Initialization/ExternalField_fwd.H
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* Copyright 2023 Luca Fedeli
*
*
* This file is part of WarpX.
*
* License: BSD-3-Clause-LBNL
*/
#ifndef EXTERNAL_FIELD_FWD_H_
#define EXTERNAL_FIELD_FWD_H_

struct ExternalFieldParams;

#endif //EXTERNAL_FIELD_FWD_H_
11 changes: 6 additions & 5 deletions Source/Initialization/Make.package
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
CEXE_sources += WarpXAMReXInit.cpp
CEXE_sources += WarpXInitData.cpp
CEXE_sources += PlasmaInjector.cpp
CEXE_sources += ExternalField.cpp
CEXE_sources += GetTemperature.cpp
CEXE_sources += GetVelocity.cpp
CEXE_sources += InjectorDensity.cpp
CEXE_sources += InjectorMomentum.cpp
CEXE_sources += PlasmaInjector.cpp
CEXE_sources += TemperatureProperties.cpp
CEXE_sources += GetTemperature.cpp
CEXE_sources += VelocityProperties.cpp
CEXE_sources += GetVelocity.cpp
CEXE_sources += WarpXAMReXInit.cpp
CEXE_sources += WarpXInitData.cpp

VPATH_LOCATIONS += $(WARPX_HOME)/Source/Initialization
Loading