diff --git a/pgens/accretion/pgen.hpp b/pgens/accretion/pgen.hpp index 2266f4e1..b88d8dfc 100644 --- a/pgens/accretion/pgen.hpp +++ b/pgens/accretion/pgen.hpp @@ -5,13 +5,13 @@ #include "global.h" #include "arch/kokkos_aliases.h" -#include "arch/traits.h" #include "utils/numeric.h" #include "archetypes/energy_dist.h" #include "archetypes/particle_injector.h" #include "archetypes/problem_generator.h" #include "archetypes/spatial_dist.h" +#include "archetypes/traits.h" #include "framework/domain/metadomain.h" #include "kernels/particle_moments.hpp" @@ -43,7 +43,8 @@ namespace user { TWO * metric.spin() * g_00); } - Inline auto bx1(const coord_t& x_Ph) const -> real_t { // at ( i , j + HALF ) + Inline auto bx1(const coord_t& x_Ph) const + -> real_t { // at ( i , j + HALF ) coord_t xi { ZERO }, x0m { ZERO }, x0p { ZERO }; metric.template convert(x_Ph, xi); @@ -61,7 +62,8 @@ namespace user { } } - Inline auto bx2(const coord_t& x_Ph) const -> real_t { // at ( i + HALF , j ) + Inline auto bx2(const coord_t& x_Ph) const + -> real_t { // at ( i + HALF , j ) coord_t xi { ZERO }, x0m { ZERO }, x0p { ZERO }; metric.template convert(x_Ph, xi); @@ -197,11 +199,17 @@ namespace user { template struct PGen : public arch::ProblemGenerator { // compatibility traits for the problem generator - static constexpr auto engines { traits::compatible_with::value }; + static constexpr auto engines { + arch::traits::pgen::compatible_with::value + }; static constexpr auto metrics { - traits::compatible_with::value + arch::traits::pgen::compatible_with::value + }; + static constexpr auto dimensions { + arch::traits::pgen::compatible_with::value }; - static constexpr auto dimensions { traits::compatible_with::value }; // for easy access to variables in the child class using arch::ProblemGenerator::D; diff --git a/pgens/magnetosphere/pgen.hpp b/pgens/magnetosphere/pgen.hpp index eab55ffb..706c3501 100644 --- a/pgens/magnetosphere/pgen.hpp +++ b/pgens/magnetosphere/pgen.hpp @@ -5,10 +5,10 @@ #include "global.h" #include "arch/kokkos_aliases.h" -#include "arch/traits.h" #include "utils/numeric.h" #include "archetypes/problem_generator.h" +#include "archetypes/traits.h" #include "framework/domain/metadomain.h" #include @@ -87,11 +87,15 @@ namespace user { template struct PGen : public arch::ProblemGenerator { // compatibility traits for the problem generator - static constexpr auto engines { traits::compatible_with::value }; + static constexpr auto engines { + arch::traits::pgen::compatible_with::value + }; static constexpr auto metrics { - traits::compatible_with::value + arch::traits::pgen::compatible_with::value + }; + static constexpr auto dimensions { + arch::traits::pgen::compatible_with::value }; - static constexpr auto dimensions { traits::compatible_with::value }; // for easy access to variables in the child class using arch::ProblemGenerator::D; diff --git a/pgens/pgen.hpp b/pgens/pgen.hpp index 78d8e648..d2d091eb 100644 --- a/pgens/pgen.hpp +++ b/pgens/pgen.hpp @@ -4,10 +4,10 @@ #include "enums.h" #include "global.h" -#include "arch/traits.h" #include "utils/formatting.h" #include "archetypes/problem_generator.h" +#include "archetypes/traits.h" #include "framework/domain/metadomain.h" #include @@ -19,18 +19,18 @@ namespace user { struct PGen : public arch::ProblemGenerator { // compatibility traits for the problem generator static constexpr auto engines { - traits::compatible_with::value + arch::traits::pgen::compatible_with::value }; static constexpr auto metrics { - traits::compatible_with::value + arch::traits::pgen::compatible_with::value }; static constexpr auto dimensions { - traits::compatible_with::value + arch::traits::pgen::compatible_with::value }; // for easy access to variables in the child class diff --git a/pgens/reconnection/pgen.hpp b/pgens/reconnection/pgen.hpp index b446c11f..a615451b 100644 --- a/pgens/reconnection/pgen.hpp +++ b/pgens/reconnection/pgen.hpp @@ -5,13 +5,13 @@ #include "global.h" #include "arch/kokkos_aliases.h" -#include "arch/traits.h" #include "utils/numeric.h" #include "archetypes/energy_dist.h" #include "archetypes/particle_injector.h" #include "archetypes/problem_generator.h" #include "archetypes/spatial_dist.h" +#include "archetypes/traits.h" #include "archetypes/utils.h" #include "framework/domain/metadomain.h" @@ -141,10 +141,14 @@ namespace user { template struct PGen : public arch::ProblemGenerator { // compatibility traits for the problem generator - static constexpr auto engines { traits::compatible_with::value }; - static constexpr auto metrics { traits::compatible_with::value }; + static constexpr auto engines { + arch::traits::pgen::compatible_with::value + }; + static constexpr auto metrics { + arch::traits::pgen::compatible_with::value + }; static constexpr auto dimensions { - traits::compatible_with::value + arch::traits::pgen::compatible_with::value }; // for easy access to variables in the child class diff --git a/pgens/streaming/pgen.hpp b/pgens/streaming/pgen.hpp index dca6cc31..9c87d7d9 100644 --- a/pgens/streaming/pgen.hpp +++ b/pgens/streaming/pgen.hpp @@ -5,11 +5,11 @@ #include "global.h" #include "arch/kokkos_aliases.h" -#include "arch/traits.h" #include "utils/error.h" #include "utils/numeric.h" #include "archetypes/problem_generator.h" +#include "archetypes/traits.h" #include "archetypes/utils.h" #include "framework/domain/domain.h" #include "framework/domain/metadomain.h" @@ -54,18 +54,20 @@ namespace user { struct PGen : public arch::ProblemGenerator { // compatibility traits for the problem generator - static constexpr auto engines = traits::compatible_with::value; - static constexpr auto metrics = traits::compatible_with::value; + static constexpr auto engines = + arch::traits::pgen::compatible_with::value; + static constexpr auto metrics = + arch::traits::pgen::compatible_with::value; static constexpr auto dimensions = - traits::compatible_with::value; + arch::traits::pgen::compatible_with::value; // for easy access to variables in the child class using arch::ProblemGenerator::D; using arch::ProblemGenerator::C; using arch::ProblemGenerator::params; - prmvec_t drifts_in_x, drifts_in_y, drifts_in_z; - prmvec_t densities, temperatures; + prmvec_t drifts_in_x, drifts_in_y, drifts_in_z; + prmvec_t densities, temperatures; // initial magnetic field real_t Btheta, Bphi, Bmag; InitFields init_flds; diff --git a/pgens/turbulence/pgen.hpp b/pgens/turbulence/pgen.hpp index e8001b09..c7579512 100644 --- a/pgens/turbulence/pgen.hpp +++ b/pgens/turbulence/pgen.hpp @@ -9,8 +9,8 @@ #include "utils/numeric.h" #include "archetypes/energy_dist.h" -#include "archetypes/particle_injector.h" #include "archetypes/problem_generator.h" +#include "archetypes/traits.h" #include "archetypes/utils.h" #include "framework/domain/domain.h" #include "framework/domain/metadomain.h" @@ -293,9 +293,12 @@ namespace user { struct PGen : public arch::ProblemGenerator { // compatibility traits for the problem generator - static constexpr auto engines = traits::compatible_with::value; - static constexpr auto metrics = traits::compatible_with::value; - static constexpr auto dimensions = traits::compatible_with::value; + static constexpr auto engines = + arch::traits::pgen::compatible_with::value; + static constexpr auto metrics = + arch::traits::pgen::compatible_with::value; + static constexpr auto dimensions = + arch::traits::pgen::compatible_with::value; // for easy access to variables in the child class using arch::ProblemGenerator::D; diff --git a/pgens/wald/pgen.hpp b/pgens/wald/pgen.hpp index 71ee905e..292f6f7f 100644 --- a/pgens/wald/pgen.hpp +++ b/pgens/wald/pgen.hpp @@ -5,21 +5,16 @@ #include "global.h" #include "arch/kokkos_aliases.h" -#include "arch/traits.h" #include "utils/comparators.h" #include "utils/error.h" #include "utils/formatting.h" -#include "utils/log.h" #include "utils/numeric.h" -#include "archetypes/energy_dist.h" -#include "archetypes/particle_injector.h" #include "archetypes/problem_generator.h" -#include "framework/domain/domain.h" +#include "archetypes/traits.h" #include "framework/domain/metadomain.h" #include -#include enum InitFieldGeometry { Wald, @@ -64,7 +59,8 @@ namespace user { TWO * metric.spin() * g_00); } - Inline auto bx1(const coord_t& x_Ph) const -> real_t { // at ( i , j + HALF ) + Inline auto bx1(const coord_t& x_Ph) const + -> real_t { // at ( i , j + HALF ) coord_t xi { ZERO }, x0m { ZERO }, x0p { ZERO }; metric.template convert(x_Ph, xi); @@ -82,7 +78,8 @@ namespace user { } } - Inline auto bx2(const coord_t& x_Ph) const -> real_t { // at ( i + HALF , j ) + Inline auto bx2(const coord_t& x_Ph) const + -> real_t { // at ( i + HALF , j ) coord_t xi { ZERO }, x0m { ZERO }, x0p { ZERO }; metric.template convert(x_Ph, xi); @@ -99,8 +96,8 @@ namespace user { } } - Inline auto bx3( - const coord_t& x_Ph) const -> real_t { // at ( i + HALF , j + HALF ) + Inline auto bx3(const coord_t& x_Ph) const + -> real_t { // at ( i + HALF , j + HALF ) if (field_geometry == InitFieldGeometry::Wald) { coord_t xi { ZERO }, x0m { ZERO }, x0p { ZERO }; metric.template convert(x_Ph, xi); @@ -120,7 +117,8 @@ namespace user { } } - Inline auto dx1(const coord_t& x_Ph) const -> real_t { // at ( i + HALF , j ) + Inline auto dx1(const coord_t& x_Ph) const + -> real_t { // at ( i + HALF , j ) if (field_geometry == InitFieldGeometry::Wald) { coord_t xi { ZERO }, x0m { ZERO }, x0p { ZERO }; metric.template convert(x_Ph, xi); @@ -158,7 +156,8 @@ namespace user { } } - Inline auto dx2(const coord_t& x_Ph) const -> real_t { // at ( i , j + HALF ) + Inline auto dx2(const coord_t& x_Ph) const + -> real_t { // at ( i , j + HALF ) if (field_geometry == InitFieldGeometry::Wald) { coord_t xi { ZERO }, x0m { ZERO }, x0p { ZERO }; metric.template convert(x_Ph, xi); @@ -232,11 +231,17 @@ namespace user { template struct PGen : public arch::ProblemGenerator { // compatibility traits for the problem generator - static constexpr auto engines { traits::compatible_with::value }; + static constexpr auto engines { + arch::traits::pgen::compatible_with::value + }; static constexpr auto metrics { - traits::compatible_with::value + arch::traits::pgen::compatible_with::value + }; + static constexpr auto dimensions { + arch::traits::pgen::compatible_with::value }; - static constexpr auto dimensions { traits::compatible_with::value }; // for easy access to variables in the child class using arch::ProblemGenerator::D; diff --git a/src/engines/CMakeLists.txt b/src/engines/CMakeLists.txt index 4cef1863..61295e43 100644 --- a/src/engines/CMakeLists.txt +++ b/src/engines/CMakeLists.txt @@ -4,10 +4,6 @@ # # @sources: # -# * engine_printer.cpp -# * engine_init.cpp -# * engine_run.cpp -# # @includes: # # * ../ @@ -31,10 +27,7 @@ # * mpi [optional] # ------------------------------ -set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(SOURCES ${SRC_DIR}/engine_printer.cpp ${SRC_DIR}/engine_init.cpp - ${SRC_DIR}/engine_run.cpp) -add_library(ntt_engines ${SOURCES}) +add_library(ntt_engines INTERFACE) set(libs ntt_global ntt_framework ntt_metrics ntt_archetypes ntt_kernels ntt_pgen) @@ -42,10 +35,9 @@ if(${output}) list(APPEND libs ntt_output) endif() add_dependencies(ntt_engines ${libs}) -target_link_libraries(ntt_engines PUBLIC ${libs}) -target_compile_definitions(ntt_engines PRIVATE PGEN=\"${PGEN}\") +target_link_libraries(ntt_engines INTERFACE ${libs}) +target_compile_definitions(ntt_engines INTERFACE PGEN=\"${PGEN}\") target_include_directories( ntt_engines - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../ INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/../) diff --git a/src/engines/engine.hpp b/src/engines/engine.hpp index 4b5c32f3..910d0cc0 100644 --- a/src/engines/engine.hpp +++ b/src/engines/engine.hpp @@ -3,9 +3,6 @@ * @brief Base simulation class which just initializes the metadomain * @implements * - ntt::Engine<> - * @cpp: - * - engine_init.cpp - * - engine_printer.cpp * @namespaces: * - ntt:: * @macros: @@ -21,20 +18,41 @@ #include "enums.h" #include "global.h" +#include "arch/directions.h" +#include "arch/mpi_aliases.h" +#include "utils/colors.h" +#include "utils/diag.h" +#include "utils/formatting.h" #include "utils/timer.h" #include "utils/toml.h" #include "metrics/traits.h" +#include "archetypes/field_setter.h" #include "archetypes/traits.h" #include "framework/containers/species.h" +#include "framework/domain/domain.h" #include "framework/domain/metadomain.h" #include "framework/parameters/parameters.h" #include "pgen.hpp" +#if defined(CUDA_ENABLED) + #include +#elif defined(HIP_ENABLED) + #include +#endif + +#if defined(OUTPUT_ENABLED) + #include +#endif + #include +#include +#include +#include + #if defined(OUTPUT_ENABLED) #include #include @@ -122,6 +140,652 @@ namespace ntt { void run(); }; + template + requires IsCompatibleWithEngine + void Engine::init() { + m_metadomain.InitStatsWriter(m_params, is_resuming); +#if defined(OUTPUT_ENABLED) + m_metadomain.InitWriter(&m_adios, m_params); + m_metadomain.InitCheckpointWriter(&m_adios, m_params); +#endif + logger::Checkpoint("Initializing Engine", HERE); + if (not is_resuming) { + // start a new simulation with initial conditions + logger::Checkpoint("Loading initial conditions", HERE); + if constexpr (arch::traits::pgen::HasInitFlds>) { + logger::Checkpoint("Initializing fields from problem generator", HERE); + m_metadomain.runOnLocalDomains([&](auto& loc_dom) { + Kokkos::parallel_for( + "InitFields", + loc_dom.mesh.rangeActiveCells(), + arch::SetEMFields_kernel { + loc_dom.fields.em, + m_pgen.init_flds, + loc_dom.mesh.metric }); + }); + } + if constexpr ( + arch::traits::pgen::HasInitPrtls, Domain>) { + logger::Checkpoint("Initializing particles from problem generator", HERE); + m_metadomain.runOnLocalDomains([&](auto& loc_dom) { + m_pgen.InitPrtls(loc_dom); + }); + } + } else { +#if defined(OUTPUT_ENABLED) + // read simulation data from the checkpoint + raise::ErrorIf( + m_params.template get("checkpoint.start_step") == 0, + "Resuming simulation from a checkpoint requires a valid start_step", + HERE); + logger::Checkpoint("Resuming simulation from a checkpoint", HERE); + m_metadomain.ContinueFromCheckpoint(&m_adios, m_params); +#else + raise::Error( + "Resuming simulation from a checkpoint requires -D output=ON", + HERE); +#endif + } + print_report(); + } + + namespace { + void add_header(std::string& report, + const std::vector& lines, + const std::vector& colors) { + report += fmt::format("%s╔%s╗%s\n", + color::BRIGHT_BLACK, + fmt::repeat("═", 58).c_str(), + color::RESET); + for (auto i { 0u }; i < lines.size(); ++i) { + report += fmt::format("%s║%s %s%s%s%s%s║%s\n", + color::BRIGHT_BLACK, + color::RESET, + colors[i], + lines[i].c_str(), + color::RESET, + fmt::repeat(" ", 57 - lines[i].size()).c_str(), + color::BRIGHT_BLACK, + color::RESET); + } + report += fmt::format("%s╚%s╝%s\n", + color::BRIGHT_BLACK, + fmt::repeat("═", 58).c_str(), + color::RESET); + } + + void add_category(std::string& report, unsigned short indent, const char* name) { + report += fmt::format("%s%s%s%s\n", + std::string(indent, ' ').c_str(), + color::BLUE, + name, + color::RESET); + } + + void add_subcategory(std::string& report, unsigned short indent, const char* name) { + report += fmt::format("%s%s-%s %s:\n", + std::string(indent, ' ').c_str(), + color::BRIGHT_BLACK, + color::RESET, + name); + } + + void add_label(std::string& report, unsigned short indent, const char* label) { + report += fmt::format("%s%s\n", std::string(indent, ' ').c_str(), label); + } + + template + void add_param(std::string& report, + unsigned short indent, + const char* name, + const char* format, + Args... args) { + report += fmt::format("%s%s-%s %s: %s%s%s\n", + std::string(indent, ' ').c_str(), + color::BRIGHT_BLACK, + color::RESET, + name, + color::BRIGHT_YELLOW, + fmt::format(format, args...).c_str(), + color::RESET); + } + + template + void add_unlabeled_param(std::string& report, + unsigned short indent, + const char* name, + const char* format, + Args... args) { + report += fmt::format("%s%s: %s%s%s\n", + std::string(indent, ' ').c_str(), + name, + color::BRIGHT_YELLOW, + fmt::format(format, args...).c_str(), + color::RESET); + } + + auto bytes_to_human_readable(std::size_t bytes) + -> std::pair { + const std::vector units { "B", "KB", "MB", "GB", "TB" }; + idx_t unit_idx = 0; + auto size = static_cast(bytes); + while ((size >= 1024.0) and (unit_idx < units.size() - 1)) { + size /= 1024.0; + ++unit_idx; + } + return { size, units[unit_idx] }; + } + } // namespace + + template + requires IsCompatibleWithEngine + void Engine::print_report() const { + const auto colored_stdout = m_params.template get( + "diagnostics.colored_stdout"); + std::string report = ""; + CallOnce( + [&](auto& metadomain, auto& params) { +#if defined(MPI_ENABLED) + int mpi_v, mpi_subv; + MPI_Get_version(&mpi_v, &mpi_subv); + const std::string mpi_version = fmt::format("%d.%d", mpi_v, mpi_subv); +#else // not MPI_ENABLED + const std::string mpi_version = "OFF"; +#endif // MPI_ENABLED + + const auto entity_version = "Entity v" + std::string(ENTITY_VERSION); + const auto hash = std::string(ENTITY_GIT_HASH); + const auto pgen = std::string(PGEN); + const auto nspec = metadomain.species_params().size(); + const auto precision = (sizeof(real_t) == 4) ? "single" : "double"; + +#if defined(__clang__) + const std::string ccx = "Clang/LLVM " __clang_version__; +#elif defined(__ICC) || defined(__INTEL_COMPILER) + const std::string ccx = "Intel ICC/ICPC " __VERSION__; +#elif defined(__GNUC__) || defined(__GNUG__) + const std::string ccx = "GNU GCC/G++ " __VERSION__; +#elif defined(__HP_cc) || defined(__HP_aCC) + const std::string ccx = "Hewlett-Packard C/aC++ " __HP_aCC; +#elif defined(__IBMC__) || defined(__IBMCPP__) + const std::string ccx = "IBM XL C/C++ " __IBMCPP__; +#elif defined(_MSC_VER) + const std::string ccx = "Microsoft Visual Studio " _MSC_VER; +#else + const std::string ccx = "Unknown compiler"; +#endif + std::string cpp_standard; + if (__cplusplus == 202101L) { + cpp_standard = "C++23"; + } else if (__cplusplus == 202002L) { + cpp_standard = "C++20"; + } else if (__cplusplus == 201703L) { + cpp_standard = "C++17"; + } else if (__cplusplus == 201402L) { + cpp_standard = "C++14"; + } else if (__cplusplus == 201103L) { + cpp_standard = "C++11"; + } else if (__cplusplus == 199711L) { + cpp_standard = "C++98"; + } else { + cpp_standard = "pre-standard " + std::to_string(__cplusplus); + } + +#if defined(CUDA_ENABLED) + int cuda_v; + cudaRuntimeGetVersion(&cuda_v); + const auto major { cuda_v / 1000 }; + const auto minor { cuda_v % 1000 / 10 }; + const auto patch { cuda_v % 10 }; + const auto cuda_version = fmt::format("%d.%d.%d", major, minor, patch); +#elif defined(HIP_ENABLED) + int hip_v; + auto status = hipDriverGetVersion(&hip_v); + raise::ErrorIf(status != hipSuccess, + "hipDriverGetVersion failed with error code %d", + HERE); + const auto major { hip_v / 10000000 }; + const auto minor { (hip_v % 10000000) / 100000 }; + const auto patch { hip_v % 100000 }; + const auto hip_version = fmt::format("%d.%d.%d", major, minor, patch); +#endif + + const auto kokkos_version = fmt::format("%d.%d.%d", + KOKKOS_VERSION / 10000, + KOKKOS_VERSION / 100 % 100, + KOKKOS_VERSION % 100); + +#if defined(OUTPUT_ENABLED) + const std::string adios2_version = fmt::format("%d.%d.%d", + ADIOS2_VERSION / 10000, + ADIOS2_VERSION / 100 % 100, + ADIOS2_VERSION % 100); +#else // not OUTPUT_ENABLED + const std::string adios2_version = "OFF"; +#endif + +#if defined(DEBUG) + const std::string dbg = "ON"; +#else // not DEBUG + const std::string dbg = "OFF"; +#endif + + report += "\n\n"; + add_header(report, { entity_version }, { color::BRIGHT_GREEN }); + report += "\n"; + + /* + * Backend + */ + add_category(report, 4, "Backend"); + add_param(report, 4, "Build hash", "%s", hash.c_str()); + add_param(report, 4, "CXX", "%s [%s]", ccx.c_str(), cpp_standard.c_str()); +#if defined(CUDA_ENABLED) + add_param(report, 4, "CUDA", "%s", cuda_version.c_str()); +#elif defined(HIP_VERSION) + add_param(report, 4, "HIP", "%s", hip_version.c_str()); +#endif + add_param(report, 4, "MPI", "%s", mpi_version.c_str()); +#if defined(MPI_ENABLED) && defined(DEVICE_ENABLED) + #if defined(GPU_AWARE_MPI) + const std::string gpu_aware_mpi = "ON"; + #else + const std::string gpu_aware_mpi = "OFF"; + #endif + add_param(report, 4, "GPU-aware MPI", "%s", gpu_aware_mpi.c_str()); +#endif + add_param(report, 4, "Kokkos", "%s", kokkos_version.c_str()); + add_param(report, 4, "ADIOS2", "%s", adios2_version.c_str()); + add_param(report, 4, "Precision", "%s", precision); + add_param(report, 4, "Debug", "%s", dbg.c_str()); + report += "\n"; + + /* + * Compilation flags + */ + add_category(report, 4, "Compilation flags"); +#if defined(SINGLE_PRECISION) + add_param(report, 4, "SINGLE_PRECISION", "%s", "ON"); +#else + add_param(report, 4, "SINGLE_PRECISION", "%s", "OFF"); +#endif + +#if defined(OUTPUT_ENABLED) + add_param(report, 4, "OUTPUT_ENABLED", "%s", "ON"); +#else + add_param(report, 4, "OUTPUT_ENABLED", "%s", "OFF"); +#endif + +#if defined(DEBUG) + add_param(report, 4, "DEBUG", "%s", "ON"); +#else + add_param(report, 4, "DEBUG", "%s", "OFF"); +#endif + +#if defined(CUDA_ENABLED) + add_param(report, 4, "CUDA_ENABLED", "%s", "ON"); +#else + add_param(report, 4, "CUDA_ENABLED", "%s", "OFF"); +#endif + +#if defined(HIP_ENABLED) + add_param(report, 4, "HIP_ENABLED", "%s", "ON"); +#else + add_param(report, 4, "HIP_ENABLED", "%s", "OFF"); +#endif + +#if defined(DEVICE_ENABLED) + add_param(report, 4, "DEVICE_ENABLED", "%s", "ON"); +#else + add_param(report, 4, "DEVICE_ENABLED", "%s", "OFF"); +#endif + +#if defined(MPI_ENABLED) + add_param(report, 4, "MPI_ENABLED", "%s", "ON"); +#else + add_param(report, 4, "MPI_ENABLED", "%s", "OFF"); +#endif + +#if defined(GPU_AWARE_MPI) + add_param(report, 4, "GPU_AWARE_MPI", "%s", "ON"); +#else + add_param(report, 4, "GPU_AWARE_MPI", "%s", "OFF"); +#endif + report += "\n"; + + /* + * Simulation configs + */ + add_category(report, 4, "Configuration"); + add_param(report, + 4, + "Name", + "%s", + params.template get("simulation.name").c_str()); + add_param(report, 4, "Problem generator", "%s", pgen.c_str()); + add_param(report, 4, "Engine", "%s", SimEngine(S).to_string()); + add_param(report, 4, "Metric", "%s", Metric(M::MetricType).to_string()); +#if SHAPE_ORDER == 0 + add_param(report, 4, "Deposit", "%s", "zigzag"); +#else + add_param(report, 4, "Deposit", "%s", "esirkepov"); + add_param(report, 4, "Interpolation order", "%i", SHAPE_ORDER); +#endif + add_param(report, 4, "Timestep [dt]", "%.3e", dt); + add_param(report, 4, "Runtime", "%.3e [%d steps]", runtime, max_steps); + report += "\n"; + add_category(report, 4, "Global domain"); + add_param(report, + 4, + "Resolution", + "%s", + params.template stringize("grid.resolution").c_str()); + add_param(report, + 4, + "Extent", + "%s", + params.template stringize("grid.extent").c_str()); + add_param(report, + 4, + "Fiducial cell size [dx0]", + "%.3e", + params.template get("scales.dx0")); + add_subcategory(report, 4, "Boundary conditions"); + add_param( + report, + 6, + "Fields", + "%s", + params.template stringize("grid.boundaries.fields").c_str()); + add_param( + report, + 6, + "Particles", + "%s", + params.template stringize("grid.boundaries.particles").c_str()); + add_param(report, + 4, + "Domain decomposition", + "%s [%d total]", + fmt::formatVector(m_metadomain.ndomains_per_dim()).c_str(), + m_metadomain.ndomains()); + report += "\n"; + add_category(report, 4, "Fiducial parameters"); + add_param(report, + 4, + "Particles per cell [ppc0]", + "%.1f", + params.template get("particles.ppc0")); + add_param(report, + 4, + "Larmor radius [larmor0]", + "%.3e [%.3f dx0]", + params.template get("scales.larmor0"), + params.template get("scales.larmor0") / + params.template get("scales.dx0")); + add_param(report, + 4, + "Larmor frequency [omegaB0 * dt]", + "%.3e", + params.template get("scales.omegaB0") * + params.template get("algorithms.timestep.dt")); + add_param(report, + 4, + "Skin depth [skindepth0]", + "%.3e [%.3f dx0]", + params.template get("scales.skindepth0"), + params.template get("scales.skindepth0") / + params.template get("scales.dx0")); + add_param(report, + 4, + "Plasma frequency [omp0 * dt]", + "%.3e", + params.template get("algorithms.timestep.dt") / + params.template get("scales.skindepth0")); + add_param(report, + 4, + "Magnetization [sigma0]", + "%.3e", + params.template get("scales.sigma0")); + + if (nspec > 0) { + report += "\n"; + add_category(report, 4, "Particles"); + } + for (const auto& species : metadomain.species_params()) { + add_subcategory(report, + 4, + fmt::format("Species #%d", species.index()).c_str()); + add_param(report, 6, "Label", "%s", species.label().c_str()); + add_param(report, 6, "Mass", "%.1f", species.mass()); + add_param(report, 6, "Charge", "%.1f", species.charge()); + add_param(report, 6, "Max #", "%d [per domain]", species.maxnpart()); + add_param(report, + 6, + "Pusher", + "%s", + ParticlePusher::to_string(species.pusher()).c_str()); + add_param( + report, + 6, + "Radiative drag", + "%s", + RadiativeDrag::to_string(species.radiative_drag_flags()).c_str()); + add_param(report, 6, "# of real-value payloads", "%d", species.npld_r()); + add_param(report, 6, "# of integer-value payloads", "%d", species.npld_i()); + } + report.pop_back(); + }, + m_metadomain, + m_params); + info::Print(report, colored_stdout); + + report = "\n"; + CallOnce([&]() { + add_category(report, 4, "Domains"); + report.pop_back(); + }); + info::Print(report, colored_stdout); + + for (unsigned int idx { 0 }; idx < m_metadomain.ndomains(); ++idx) { + auto is_local = false; + for (const auto& lidx : m_metadomain.l_subdomain_indices()) { + is_local |= (idx == lidx); + } + if (is_local) { + report = ""; + const auto& domain = m_metadomain.subdomain(idx); + add_subcategory(report, + 4, + fmt::format("Domain #%d", domain.index()).c_str()); +#if defined(MPI_ENABLED) + add_param(report, 6, "Rank", "%d", domain.mpi_rank()); +#endif + add_param(report, + 6, + "Resolution", + "%s", + fmt::formatVector(domain.mesh.n_active()).c_str()); + add_param(report, + 6, + "Extent", + "%s", + fmt::formatVector(domain.mesh.extent()).c_str()); + add_subcategory(report, 6, "Boundary conditions"); + + add_label( + report, + 8 + 2 + 2 * M::Dim, + fmt::format("%-10s %-10s %-10s", "[flds]", "[prtl]", "[neighbor]").c_str()); + for (auto& direction : dir::Directions::all) { + const auto flds_bc = domain.mesh.flds_bc_in(direction); + const auto prtl_bc = domain.mesh.prtl_bc_in(direction); + bool has_sync = false; + auto neighbor_idx = domain.neighbor_idx_in(direction); + if (flds_bc == FldsBC::SYNC || prtl_bc == PrtlBC::SYNC) { + has_sync = true; + } + add_unlabeled_param(report, + 8, + direction.to_string().c_str(), + "%-10s %-10s %-10s", + flds_bc.to_string(), + prtl_bc.to_string(), + has_sync ? std::to_string(neighbor_idx).c_str() + : "."); + } + add_subcategory(report, 6, "Memory footprint"); + auto flds_footprint = domain.fields.memory_footprint(); + auto [flds_size, flds_unit] = bytes_to_human_readable(flds_footprint); + add_param(report, 8, "Fields", "%.2f %s", flds_size, flds_unit.c_str()); + if (domain.species.size() > 0) { + add_subcategory(report, 8, "Particles"); + } + for (auto& species : domain.species) { + const auto str = fmt::format("Species #%d (%s)", + species.index(), + species.label().c_str()); + auto [size, unit] = bytes_to_human_readable(species.memory_footprint()); + add_param(report, 10, str.c_str(), "%.2f %s", size, unit.c_str()); + } + report.pop_back(); + if (idx == m_metadomain.ndomains() - 1) { + report += "\n\n"; + } + info::Print(report, colored_stdout, true, false); + } +#if defined(MPI_ENABLED) + MPI_Barrier(MPI_COMM_WORLD); +#endif + } + } + + template + requires IsCompatibleWithEngine + void Engine::run() { + init(); + + auto timers = timer::Timers { + { "FieldSolver", + "CurrentFiltering", "CurrentDeposit", + "ParticlePusher", "FieldBoundaries", + "ParticleBoundaries", "Communications", + "Injector", "Custom", + "PrtlClear", "Output", + "Checkpoint" }, + []() { + Kokkos::fence(); + }, + m_params.get("diagnostics.blocking_timers") + }; + const auto diag_interval = m_params.template get( + "diagnostics.interval"); + + auto time_history = pbar::DurationHistory { 1000 }; + const auto clear_interval = m_params.template get( + "particles.clear_interval"); + + // main algorithm loop + while (step < max_steps) { + // run the engine-dependent algorithm step + m_metadomain.runOnLocalDomains([&timers, this](auto& dom) { + step_forward(timers, dom); + }); + // poststep (if defined) + if constexpr ( + arch::traits::pgen::HasCustomPostStep>) { + timers.start("Custom"); + m_metadomain.runOnLocalDomains([&timers, this](auto& dom) { + m_pgen.CustomPostStep(step, time, dom); + }); + timers.stop("Custom"); + } + auto print_prtl_clear = (clear_interval > 0 and + step % clear_interval == 0 and step > 0); + + // advance time & step + time += dt; + ++step; + + auto print_output = false; + auto print_checkpoint = false; +#if defined(OUTPUT_ENABLED) + timers.start("Output"); + if constexpr ( + arch::traits::pgen::HasCustomFieldOutput>) { + auto lambda_custom_field_output = [&](const std::string& name, + ndfield_t& buff, + index_t idx, + timestep_t step, + simtime_t time, + const Domain& dom) { + m_pgen.CustomFieldOutput(name, buff, idx, step, time, dom); + }; + print_output &= m_metadomain.Write(m_params, + step, + step - 1, + time, + time - dt, + lambda_custom_field_output); + } else { + print_output &= m_metadomain.Write(m_params, step, step - 1, time, time - dt); + } + if constexpr ( + arch::traits::pgen::HasCustomStatOutput>) { + auto lambda_custom_stat = [&](const std::string& name, + timestep_t step, + simtime_t time, + const Domain& dom) -> real_t { + return m_pgen.CustomStat(name, step, time, dom); + }; + print_output &= m_metadomain.WriteStats(m_params, + step, + step - 1, + time, + time - dt, + lambda_custom_stat); + } else { + print_output &= m_metadomain.WriteStats(m_params, + step, + step - 1, + time, + time - dt); + } + timers.stop("Output"); + + timers.start("Checkpoint"); + print_checkpoint = m_metadomain.WriteCheckpoint(m_params, + step, + step - 1, + time, + time - dt); + timers.stop("Checkpoint"); +#endif + + // advance time_history + time_history.tick(); + // print timestep report + if (diag_interval > 0 and step % diag_interval == 0) { + diag::printDiagnostics( + step - 1, + max_steps, + time - dt, + dt, + timers, + time_history, + m_metadomain.l_ncells(), + m_metadomain.species_labels(), + m_metadomain.l_npart_perspec(), + m_metadomain.l_maxnpart_perspec(), + print_prtl_clear, + print_output, + print_checkpoint, + m_params.get("diagnostics.colored_stdout")); + } + timers.resetAll(); + } + } + } // namespace ntt #endif // ENGINES_ENGINE_H diff --git a/src/engines/engine_init.cpp b/src/engines/engine_init.cpp deleted file mode 100644 index 560114e8..00000000 --- a/src/engines/engine_init.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "enums.h" -#include "global.h" - -#include "archetypes/field_setter.h" -#include "archetypes/traits.h" -#include "framework/specialization_registry.h" - -#include "engines/engine.hpp" - -#include - -#include - -namespace ntt { - - template - requires IsCompatibleWithEngine - void Engine::init() { - m_metadomain.InitStatsWriter(m_params, is_resuming); -#if defined(OUTPUT_ENABLED) - m_metadomain.InitWriter(&m_adios, m_params); - m_metadomain.InitCheckpointWriter(&m_adios, m_params); -#endif - logger::Checkpoint("Initializing Engine", HERE); - if (not is_resuming) { - // start a new simulation with initial conditions - logger::Checkpoint("Loading initial conditions", HERE); - if constexpr (arch::traits::pgen::HasInitFlds>) { - logger::Checkpoint("Initializing fields from problem generator", HERE); - m_metadomain.runOnLocalDomains([&](auto& loc_dom) { - Kokkos::parallel_for( - "InitFields", - loc_dom.mesh.rangeActiveCells(), - arch::SetEMFields_kernel { - loc_dom.fields.em, - m_pgen.init_flds, - loc_dom.mesh.metric }); - }); - } - if constexpr ( - arch::traits::pgen::HasInitPrtls, Domain>) { - logger::Checkpoint("Initializing particles from problem generator", HERE); - m_metadomain.runOnLocalDomains([&](auto& loc_dom) { - m_pgen.InitPrtls(loc_dom); - }); - } - } else { -#if defined(OUTPUT_ENABLED) - // read simulation data from the checkpoint - raise::ErrorIf( - m_params.template get("checkpoint.start_step") == 0, - "Resuming simulation from a checkpoint requires a valid start_step", - HERE); - logger::Checkpoint("Resuming simulation from a checkpoint", HERE); - m_metadomain.ContinueFromCheckpoint(&m_adios, m_params); -#else - raise::Error( - "Resuming simulation from a checkpoint requires -D output=ON", - HERE); -#endif - } - print_report(); - } - -#define ENGINE_INIT(S, M, D) template class Engine>; - - NTT_FOREACH_SPECIALIZATION(ENGINE_INIT) - -#undef ENGINE_INIT - -} // namespace ntt diff --git a/src/engines/engine_printer.cpp b/src/engines/engine_printer.cpp deleted file mode 100644 index fb88f4fe..00000000 --- a/src/engines/engine_printer.cpp +++ /dev/null @@ -1,507 +0,0 @@ -#include "enums.h" -#include "global.h" - -#include "arch/directions.h" -#include "arch/mpi_aliases.h" -#include "utils/colors.h" -#include "utils/formatting.h" - -#include "framework/specialization_registry.h" - -#include "engines/engine.hpp" - -#if defined(CUDA_ENABLED) - #include -#elif defined(HIP_ENABLED) - #include -#endif - -#if defined(OUTPUT_ENABLED) - #include -#endif - -#include -#include -#include - -namespace ntt { - - namespace { - void add_header(std::string& report, - const std::vector& lines, - const std::vector& colors) { - report += fmt::format("%s╔%s╗%s\n", - color::BRIGHT_BLACK, - fmt::repeat("═", 58).c_str(), - color::RESET); - for (auto i { 0u }; i < lines.size(); ++i) { - report += fmt::format("%s║%s %s%s%s%s%s║%s\n", - color::BRIGHT_BLACK, - color::RESET, - colors[i], - lines[i].c_str(), - color::RESET, - fmt::repeat(" ", 57 - lines[i].size()).c_str(), - color::BRIGHT_BLACK, - color::RESET); - } - report += fmt::format("%s╚%s╝%s\n", - color::BRIGHT_BLACK, - fmt::repeat("═", 58).c_str(), - color::RESET); - } - - void add_category(std::string& report, unsigned short indent, const char* name) { - report += fmt::format("%s%s%s%s\n", - std::string(indent, ' ').c_str(), - color::BLUE, - name, - color::RESET); - } - - void add_subcategory(std::string& report, unsigned short indent, const char* name) { - report += fmt::format("%s%s-%s %s:\n", - std::string(indent, ' ').c_str(), - color::BRIGHT_BLACK, - color::RESET, - name); - } - - void add_label(std::string& report, unsigned short indent, const char* label) { - report += fmt::format("%s%s\n", std::string(indent, ' ').c_str(), label); - } - - template - void add_param(std::string& report, - unsigned short indent, - const char* name, - const char* format, - Args... args) { - report += fmt::format("%s%s-%s %s: %s%s%s\n", - std::string(indent, ' ').c_str(), - color::BRIGHT_BLACK, - color::RESET, - name, - color::BRIGHT_YELLOW, - fmt::format(format, args...).c_str(), - color::RESET); - } - - template - void add_unlabeled_param(std::string& report, - unsigned short indent, - const char* name, - const char* format, - Args... args) { - report += fmt::format("%s%s: %s%s%s\n", - std::string(indent, ' ').c_str(), - name, - color::BRIGHT_YELLOW, - fmt::format(format, args...).c_str(), - color::RESET); - } - - auto bytes_to_human_readable(std::size_t bytes) - -> std::pair { - const std::vector units { "B", "KB", "MB", "GB", "TB" }; - idx_t unit_idx = 0; - auto size = static_cast(bytes); - while ((size >= 1024.0) and (unit_idx < units.size() - 1)) { - size /= 1024.0; - ++unit_idx; - } - return { size, units[unit_idx] }; - } - } // namespace - - template - requires IsCompatibleWithEngine - void Engine::print_report() const { - const auto colored_stdout = m_params.template get( - "diagnostics.colored_stdout"); - std::string report = ""; - CallOnce( - [&](auto& metadomain, auto& params) { -#if defined(MPI_ENABLED) - int mpi_v, mpi_subv; - MPI_Get_version(&mpi_v, &mpi_subv); - const std::string mpi_version = fmt::format("%d.%d", mpi_v, mpi_subv); -#else // not MPI_ENABLED - const std::string mpi_version = "OFF"; -#endif // MPI_ENABLED - - const auto entity_version = "Entity v" + std::string(ENTITY_VERSION); - const auto hash = std::string(ENTITY_GIT_HASH); - const auto pgen = std::string(PGEN); - const auto nspec = metadomain.species_params().size(); - const auto precision = (sizeof(real_t) == 4) ? "single" : "double"; - -#if defined(__clang__) - const std::string ccx = "Clang/LLVM " __clang_version__; -#elif defined(__ICC) || defined(__INTEL_COMPILER) - const std::string ccx = "Intel ICC/ICPC " __VERSION__; -#elif defined(__GNUC__) || defined(__GNUG__) - const std::string ccx = "GNU GCC/G++ " __VERSION__; -#elif defined(__HP_cc) || defined(__HP_aCC) - const std::string ccx = "Hewlett-Packard C/aC++ " __HP_aCC; -#elif defined(__IBMC__) || defined(__IBMCPP__) - const std::string ccx = "IBM XL C/C++ " __IBMCPP__; -#elif defined(_MSC_VER) - const std::string ccx = "Microsoft Visual Studio " _MSC_VER; -#else - const std::string ccx = "Unknown compiler"; -#endif - std::string cpp_standard; - if (__cplusplus == 202101L) { - cpp_standard = "C++23"; - } else if (__cplusplus == 202002L) { - cpp_standard = "C++20"; - } else if (__cplusplus == 201703L) { - cpp_standard = "C++17"; - } else if (__cplusplus == 201402L) { - cpp_standard = "C++14"; - } else if (__cplusplus == 201103L) { - cpp_standard = "C++11"; - } else if (__cplusplus == 199711L) { - cpp_standard = "C++98"; - } else { - cpp_standard = "pre-standard " + std::to_string(__cplusplus); - } - -#if defined(CUDA_ENABLED) - int cuda_v; - cudaRuntimeGetVersion(&cuda_v); - const auto major { cuda_v / 1000 }; - const auto minor { cuda_v % 1000 / 10 }; - const auto patch { cuda_v % 10 }; - const auto cuda_version = fmt::format("%d.%d.%d", major, minor, patch); -#elif defined(HIP_ENABLED) - int hip_v; - auto status = hipDriverGetVersion(&hip_v); - raise::ErrorIf(status != hipSuccess, - "hipDriverGetVersion failed with error code %d", - HERE); - const auto major { hip_v / 10000000 }; - const auto minor { (hip_v % 10000000) / 100000 }; - const auto patch { hip_v % 100000 }; - const auto hip_version = fmt::format("%d.%d.%d", major, minor, patch); -#endif - - const auto kokkos_version = fmt::format("%d.%d.%d", - KOKKOS_VERSION / 10000, - KOKKOS_VERSION / 100 % 100, - KOKKOS_VERSION % 100); - -#if defined(OUTPUT_ENABLED) - const std::string adios2_version = fmt::format("%d.%d.%d", - ADIOS2_VERSION / 10000, - ADIOS2_VERSION / 100 % 100, - ADIOS2_VERSION % 100); -#else // not OUTPUT_ENABLED - const std::string adios2_version = "OFF"; -#endif - -#if defined(DEBUG) - const std::string dbg = "ON"; -#else // not DEBUG - const std::string dbg = "OFF"; -#endif - - report += "\n\n"; - add_header(report, { entity_version }, { color::BRIGHT_GREEN }); - report += "\n"; - - /* - * Backend - */ - add_category(report, 4, "Backend"); - add_param(report, 4, "Build hash", "%s", hash.c_str()); - add_param(report, 4, "CXX", "%s [%s]", ccx.c_str(), cpp_standard.c_str()); -#if defined(CUDA_ENABLED) - add_param(report, 4, "CUDA", "%s", cuda_version.c_str()); -#elif defined(HIP_VERSION) - add_param(report, 4, "HIP", "%s", hip_version.c_str()); -#endif - add_param(report, 4, "MPI", "%s", mpi_version.c_str()); -#if defined(MPI_ENABLED) && defined(DEVICE_ENABLED) - #if defined(GPU_AWARE_MPI) - const std::string gpu_aware_mpi = "ON"; - #else - const std::string gpu_aware_mpi = "OFF"; - #endif - add_param(report, 4, "GPU-aware MPI", "%s", gpu_aware_mpi.c_str()); -#endif - add_param(report, 4, "Kokkos", "%s", kokkos_version.c_str()); - add_param(report, 4, "ADIOS2", "%s", adios2_version.c_str()); - add_param(report, 4, "Precision", "%s", precision); - add_param(report, 4, "Debug", "%s", dbg.c_str()); - report += "\n"; - - /* - * Compilation flags - */ - add_category(report, 4, "Compilation flags"); -#if defined(SINGLE_PRECISION) - add_param(report, 4, "SINGLE_PRECISION", "%s", "ON"); -#else - add_param(report, 4, "SINGLE_PRECISION", "%s", "OFF"); -#endif - -#if defined(OUTPUT_ENABLED) - add_param(report, 4, "OUTPUT_ENABLED", "%s", "ON"); -#else - add_param(report, 4, "OUTPUT_ENABLED", "%s", "OFF"); -#endif - -#if defined(DEBUG) - add_param(report, 4, "DEBUG", "%s", "ON"); -#else - add_param(report, 4, "DEBUG", "%s", "OFF"); -#endif - -#if defined(CUDA_ENABLED) - add_param(report, 4, "CUDA_ENABLED", "%s", "ON"); -#else - add_param(report, 4, "CUDA_ENABLED", "%s", "OFF"); -#endif - -#if defined(HIP_ENABLED) - add_param(report, 4, "HIP_ENABLED", "%s", "ON"); -#else - add_param(report, 4, "HIP_ENABLED", "%s", "OFF"); -#endif - -#if defined(DEVICE_ENABLED) - add_param(report, 4, "DEVICE_ENABLED", "%s", "ON"); -#else - add_param(report, 4, "DEVICE_ENABLED", "%s", "OFF"); -#endif - -#if defined(MPI_ENABLED) - add_param(report, 4, "MPI_ENABLED", "%s", "ON"); -#else - add_param(report, 4, "MPI_ENABLED", "%s", "OFF"); -#endif - -#if defined(GPU_AWARE_MPI) - add_param(report, 4, "GPU_AWARE_MPI", "%s", "ON"); -#else - add_param(report, 4, "GPU_AWARE_MPI", "%s", "OFF"); -#endif - report += "\n"; - - /* - * Simulation configs - */ - add_category(report, 4, "Configuration"); - add_param(report, - 4, - "Name", - "%s", - params.template get("simulation.name").c_str()); - add_param(report, 4, "Problem generator", "%s", pgen.c_str()); - add_param(report, 4, "Engine", "%s", SimEngine(S).to_string()); - add_param(report, 4, "Metric", "%s", Metric(M::MetricType).to_string()); -#if SHAPE_ORDER == 0 - add_param(report, 4, "Deposit", "%s", "zigzag"); -#else - add_param(report, 4, "Deposit", "%s", "esirkepov"); - add_param(report, 4, "Interpolation order", "%i", SHAPE_ORDER); -#endif - add_param(report, 4, "Timestep [dt]", "%.3e", dt); - add_param(report, 4, "Runtime", "%.3e [%d steps]", runtime, max_steps); - report += "\n"; - add_category(report, 4, "Global domain"); - add_param(report, - 4, - "Resolution", - "%s", - params.template stringize("grid.resolution").c_str()); - add_param(report, - 4, - "Extent", - "%s", - params.template stringize("grid.extent").c_str()); - add_param(report, - 4, - "Fiducial cell size [dx0]", - "%.3e", - params.template get("scales.dx0")); - add_subcategory(report, 4, "Boundary conditions"); - add_param( - report, - 6, - "Fields", - "%s", - params.template stringize("grid.boundaries.fields").c_str()); - add_param( - report, - 6, - "Particles", - "%s", - params.template stringize("grid.boundaries.particles").c_str()); - add_param(report, - 4, - "Domain decomposition", - "%s [%d total]", - fmt::formatVector(m_metadomain.ndomains_per_dim()).c_str(), - m_metadomain.ndomains()); - report += "\n"; - add_category(report, 4, "Fiducial parameters"); - add_param(report, - 4, - "Particles per cell [ppc0]", - "%.1f", - params.template get("particles.ppc0")); - add_param(report, - 4, - "Larmor radius [larmor0]", - "%.3e [%.3f dx0]", - params.template get("scales.larmor0"), - params.template get("scales.larmor0") / - params.template get("scales.dx0")); - add_param(report, - 4, - "Larmor frequency [omegaB0 * dt]", - "%.3e", - params.template get("scales.omegaB0") * - params.template get("algorithms.timestep.dt")); - add_param(report, - 4, - "Skin depth [skindepth0]", - "%.3e [%.3f dx0]", - params.template get("scales.skindepth0"), - params.template get("scales.skindepth0") / - params.template get("scales.dx0")); - add_param(report, - 4, - "Plasma frequency [omp0 * dt]", - "%.3e", - params.template get("algorithms.timestep.dt") / - params.template get("scales.skindepth0")); - add_param(report, - 4, - "Magnetization [sigma0]", - "%.3e", - params.template get("scales.sigma0")); - - if (nspec > 0) { - report += "\n"; - add_category(report, 4, "Particles"); - } - for (const auto& species : metadomain.species_params()) { - add_subcategory(report, - 4, - fmt::format("Species #%d", species.index()).c_str()); - add_param(report, 6, "Label", "%s", species.label().c_str()); - add_param(report, 6, "Mass", "%.1f", species.mass()); - add_param(report, 6, "Charge", "%.1f", species.charge()); - add_param(report, 6, "Max #", "%d [per domain]", species.maxnpart()); - add_param(report, - 6, - "Pusher", - "%s", - ParticlePusher::to_string(species.pusher()).c_str()); - add_param( - report, - 6, - "Radiative drag", - "%s", - RadiativeDrag::to_string(species.radiative_drag_flags()).c_str()); - add_param(report, 6, "# of real-value payloads", "%d", species.npld_r()); - add_param(report, 6, "# of integer-value payloads", "%d", species.npld_i()); - } - report.pop_back(); - }, - m_metadomain, - m_params); - info::Print(report, colored_stdout); - - report = "\n"; - CallOnce([&]() { - add_category(report, 4, "Domains"); - report.pop_back(); - }); - info::Print(report, colored_stdout); - - for (unsigned int idx { 0 }; idx < m_metadomain.ndomains(); ++idx) { - auto is_local = false; - for (const auto& lidx : m_metadomain.l_subdomain_indices()) { - is_local |= (idx == lidx); - } - if (is_local) { - report = ""; - const auto& domain = m_metadomain.subdomain(idx); - add_subcategory(report, - 4, - fmt::format("Domain #%d", domain.index()).c_str()); -#if defined(MPI_ENABLED) - add_param(report, 6, "Rank", "%d", domain.mpi_rank()); -#endif - add_param(report, - 6, - "Resolution", - "%s", - fmt::formatVector(domain.mesh.n_active()).c_str()); - add_param(report, - 6, - "Extent", - "%s", - fmt::formatVector(domain.mesh.extent()).c_str()); - add_subcategory(report, 6, "Boundary conditions"); - - add_label( - report, - 8 + 2 + 2 * M::Dim, - fmt::format("%-10s %-10s %-10s", "[flds]", "[prtl]", "[neighbor]").c_str()); - for (auto& direction : dir::Directions::all) { - const auto flds_bc = domain.mesh.flds_bc_in(direction); - const auto prtl_bc = domain.mesh.prtl_bc_in(direction); - bool has_sync = false; - auto neighbor_idx = domain.neighbor_idx_in(direction); - if (flds_bc == FldsBC::SYNC || prtl_bc == PrtlBC::SYNC) { - has_sync = true; - } - add_unlabeled_param(report, - 8, - direction.to_string().c_str(), - "%-10s %-10s %-10s", - flds_bc.to_string(), - prtl_bc.to_string(), - has_sync ? std::to_string(neighbor_idx).c_str() - : "."); - } - add_subcategory(report, 6, "Memory footprint"); - auto flds_footprint = domain.fields.memory_footprint(); - auto [flds_size, flds_unit] = bytes_to_human_readable(flds_footprint); - add_param(report, 8, "Fields", "%.2f %s", flds_size, flds_unit.c_str()); - if (domain.species.size() > 0) { - add_subcategory(report, 8, "Particles"); - } - for (auto& species : domain.species) { - const auto str = fmt::format("Species #%d (%s)", - species.index(), - species.label().c_str()); - auto [size, unit] = bytes_to_human_readable(species.memory_footprint()); - add_param(report, 10, str.c_str(), "%.2f %s", size, unit.c_str()); - } - report.pop_back(); - if (idx == m_metadomain.ndomains() - 1) { - report += "\n\n"; - } - info::Print(report, colored_stdout, true, false); - } -#if defined(MPI_ENABLED) - MPI_Barrier(MPI_COMM_WORLD); -#endif - } - } - -#define ENGINE_PRINTER(S, M, D) \ - template void Engine>::print_report() const; - - NTT_FOREACH_SPECIALIZATION(ENGINE_PRINTER) - -#undef ENGINE_PRINTER - -} // namespace ntt diff --git a/src/engines/engine_run.cpp b/src/engines/engine_run.cpp deleted file mode 100644 index 498bef97..00000000 --- a/src/engines/engine_run.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "enums.h" - -#include "utils/diag.h" - -#include "archetypes/traits.h" -#include "framework/domain/domain.h" -#include "framework/specialization_registry.h" - -#include "engines/engine.hpp" - -namespace ntt { - - template - requires IsCompatibleWithEngine - void Engine::run() { - init(); - - auto timers = timer::Timers { - { "FieldSolver", - "CurrentFiltering", "CurrentDeposit", - "ParticlePusher", "FieldBoundaries", - "ParticleBoundaries", "Communications", - "Injector", "Custom", - "PrtlClear", "Output", - "Checkpoint" }, - []() { - Kokkos::fence(); - }, - m_params.get("diagnostics.blocking_timers") - }; - const auto diag_interval = m_params.template get( - "diagnostics.interval"); - - auto time_history = pbar::DurationHistory { 1000 }; - const auto clear_interval = m_params.template get( - "particles.clear_interval"); - - // main algorithm loop - while (step < max_steps) { - // run the engine-dependent algorithm step - m_metadomain.runOnLocalDomains([&timers, this](auto& dom) { - step_forward(timers, dom); - }); - // poststep (if defined) - if constexpr ( - arch::traits::pgen::HasCustomPostStep>) { - timers.start("Custom"); - m_metadomain.runOnLocalDomains([&timers, this](auto& dom) { - m_pgen.CustomPostStep(step, time, dom); - }); - timers.stop("Custom"); - } - auto print_prtl_clear = (clear_interval > 0 and - step % clear_interval == 0 and step > 0); - - // advance time & step - time += dt; - ++step; - - auto print_output = false; - auto print_checkpoint = false; -#if defined(OUTPUT_ENABLED) - timers.start("Output"); - if constexpr ( - arch::traits::pgen::HasCustomFieldOutput>) { - auto lambda_custom_field_output = [&](const std::string& name, - ndfield_t& buff, - index_t idx, - timestep_t step, - simtime_t time, - const Domain& dom) { - m_pgen.CustomFieldOutput(name, buff, idx, step, time, dom); - }; - print_output &= m_metadomain.Write(m_params, - step, - step - 1, - time, - time - dt, - lambda_custom_field_output); - } else { - print_output &= m_metadomain.Write(m_params, step, step - 1, time, time - dt); - } - if constexpr ( - arch::traits::pgen::HasCustomStatOutput>) { - auto lambda_custom_stat = [&](const std::string& name, - timestep_t step, - simtime_t time, - const Domain& dom) -> real_t { - return m_pgen.CustomStat(name, step, time, dom); - }; - print_output &= m_metadomain.WriteStats(m_params, - step, - step - 1, - time, - time - dt, - lambda_custom_stat); - } else { - print_output &= m_metadomain.WriteStats(m_params, - step, - step - 1, - time, - time - dt); - } - timers.stop("Output"); - - timers.start("Checkpoint"); - print_checkpoint = m_metadomain.WriteCheckpoint(m_params, - step, - step - 1, - time, - time - dt); - timers.stop("Checkpoint"); -#endif - - // advance time_history - time_history.tick(); - // print timestep report - if (diag_interval > 0 and step % diag_interval == 0) { - diag::printDiagnostics( - step - 1, - max_steps, - time - dt, - dt, - timers, - time_history, - m_metadomain.l_ncells(), - m_metadomain.species_labels(), - m_metadomain.l_npart_perspec(), - m_metadomain.l_maxnpart_perspec(), - print_prtl_clear, - print_output, - print_checkpoint, - m_params.get("diagnostics.colored_stdout")); - } - timers.resetAll(); - } - } - -#define ENGINE_RUN(S, M, D) template void Engine>::run(); - - NTT_FOREACH_SPECIALIZATION(ENGINE_RUN) - -#undef ENGINE_RUN - -} // namespace ntt diff --git a/src/engines/srpic.hpp b/src/engines/srpic.hpp index 4b1a8784..006a3412 100644 --- a/src/engines/srpic.hpp +++ b/src/engines/srpic.hpp @@ -383,7 +383,8 @@ namespace ntt { if constexpr (arch::traits::pgen::HasExtForce) { has_extforce = true; // toggle to indicate whether the ext force applies to current species - if (traits::has_member::value) { + if ( + ::traits::has_member<::traits::species_t, decltype(pgen_t::ext_force)>::value) { has_extforce &= std::find(m_pgen.ext_force.species.begin(), m_pgen.ext_force.species.end(), species.index()) != diff --git a/src/kernels/fields_bcs.hpp b/src/kernels/fields_bcs.hpp index fb8bd9cb..9deb9716 100644 --- a/src/kernels/fields_bcs.hpp +++ b/src/kernels/fields_bcs.hpp @@ -44,18 +44,20 @@ namespace kernel::bc { metric::traits::HasConvert && ((S == SimEngine::SRPIC && metric::traits::HasTransform_i) || S == SimEngine::GRPIC) && - (S == SimEngine::SRPIC && (traits::fieldsetter::HasEx1 || - traits::fieldsetter::HasEx2 || - traits::fieldsetter::HasEx3 || - traits::fieldsetter::HasBx1 || - traits::fieldsetter::HasBx2 || - traits::fieldsetter::HasBx3) || - (S == SimEngine::GRPIC && (traits::fieldsetter::HasDx1 || - traits::fieldsetter::HasDx2 || - traits::fieldsetter::HasDx3) || - traits::fieldsetter::HasBx1 || - traits::fieldsetter::HasBx2 || - traits::fieldsetter::HasBx3)) + (S == SimEngine::SRPIC && + (::traits::fieldsetter::HasEx1 || + ::traits::fieldsetter::HasEx2 || + ::traits::fieldsetter::HasEx3 || + ::traits::fieldsetter::HasBx1 || + ::traits::fieldsetter::HasBx2 || + ::traits::fieldsetter::HasBx3) || + (S == SimEngine::GRPIC && + (::traits::fieldsetter::HasDx1 || + ::traits::fieldsetter::HasDx2 || + ::traits::fieldsetter::HasDx3) || + ::traits::fieldsetter::HasBx1 || + ::traits::fieldsetter::HasBx2 || + ::traits::fieldsetter::HasBx3)) struct MatchBoundaries_kernel { static_assert(static_cast(o) < static_cast(M::Dim), "Invalid component index"); @@ -123,12 +125,12 @@ namespace kernel::bc { metric.template convert({ i1_ }, x_Ph_0); metric.template convert({ i1_ + HALF }, x_Ph_H); - if constexpr (traits::fieldsetter::HasEx1 or - traits::fieldsetter::HasBx2 or - traits::fieldsetter::HasBx3) { + if constexpr (::traits::fieldsetter::HasEx1 or + ::traits::fieldsetter::HasBx2 or + ::traits::fieldsetter::HasBx3) { const auto s = shape(math::abs( metric.template convert(i1_ + HALF) - xg_edge)); - if constexpr (traits::fieldsetter::HasEx1) { + if constexpr (::traits::fieldsetter::HasEx1) { if (tags & BC::E) { Fld(i1, em::ex1) = s * Fld(i1, em::ex1) + (ONE - s) * @@ -138,17 +140,17 @@ namespace kernel::bc { } } // if constexpr (defines_bx2 or defines_bx3) { - if constexpr (traits::fieldsetter::HasBx2 or - traits::fieldsetter::HasBx3) { + if constexpr (::traits::fieldsetter::HasBx2 or + ::traits::fieldsetter::HasBx3) { if (tags & BC::B) { - if constexpr (traits::fieldsetter::HasBx2) { + if constexpr (::traits::fieldsetter::HasBx2) { Fld(i1, em::bx2) = s * Fld(i1, em::bx2) + (ONE - s) * metric.template transform<2, Idx::T, Idx::U>( { i1_ + HALF }, fset.bx2(x_Ph_H)); } - if constexpr (traits::fieldsetter::HasBx3) { + if constexpr (::traits::fieldsetter::HasBx3) { Fld(i1, em::bx3) = s * Fld(i1, em::bx3) + (ONE - s) * metric.template transform<3, Idx::T, Idx::U>( @@ -158,12 +160,12 @@ namespace kernel::bc { } } } - if constexpr (traits::fieldsetter::HasBx1 or - traits::fieldsetter::HasEx2 or - traits::fieldsetter::HasEx3) { + if constexpr (::traits::fieldsetter::HasBx1 or + ::traits::fieldsetter::HasEx2 or + ::traits::fieldsetter::HasEx3) { const auto s = shape(math::abs( metric.template convert(i1_) - xg_edge)); - if constexpr (traits::fieldsetter::HasBx1) { + if constexpr (::traits::fieldsetter::HasBx1) { if (tags & BC::B) { Fld(i1, em::bx1) = s * Fld(i1, em::bx1) + (ONE - s) * @@ -173,17 +175,17 @@ namespace kernel::bc { } } // if constexpr (defines_ex2 or defines_ex3) { - if constexpr (traits::fieldsetter::HasEx2 or - traits::fieldsetter::HasEx3) { + if constexpr (::traits::fieldsetter::HasEx2 or + ::traits::fieldsetter::HasEx3) { if (tags & BC::E) { - if constexpr (traits::fieldsetter::HasEx2) { + if constexpr (::traits::fieldsetter::HasEx2) { Fld(i1, em::ex2) = s * Fld(i1, em::ex2) + (ONE - s) * metric.template transform<2, Idx::T, Idx::U>( { i1_ }, fset.ex2(x_Ph_0)); } - if constexpr (traits::fieldsetter::HasEx3) { + if constexpr (::traits::fieldsetter::HasEx3) { Fld(i1, em::ex3) = s * Fld(i1, em::ex3) + (ONE - s) * metric.template transform<3, Idx::T, Idx::U>( @@ -210,9 +212,9 @@ namespace kernel::bc { const auto i2_ = COORD(i2); // SRPIC - if constexpr (traits::fieldsetter::HasEx1 or - traits::fieldsetter::HasDx1 or - traits::fieldsetter::HasBx2) { + if constexpr (::traits::fieldsetter::HasEx1 or + ::traits::fieldsetter::HasDx1 or + ::traits::fieldsetter::HasBx2) { // i1 + 1/2, i2 real_t xi_Cd; if constexpr (o == in::x1) { @@ -227,17 +229,17 @@ namespace kernel::bc { coord_t x_Ph_H0 { ZERO }; metric.template convert({ i1_ + HALF, i2_ }, x_Ph_H0); - if constexpr (traits::fieldsetter::HasEx1 or - traits::fieldsetter::HasDx1) { + if constexpr (::traits::fieldsetter::HasEx1 or + ::traits::fieldsetter::HasDx1) { if ((tags & BC::E) or (tags & BC::D)) { - if constexpr (traits::fieldsetter::HasEx1 and + if constexpr (::traits::fieldsetter::HasEx1 and S == SimEngine::SRPIC) { Fld(i1, i2, em::ex1) = s * Fld(i1, i2, em::ex1) + (ONE - s) * metric.template transform<1, Idx::T, Idx::U>( { i1_ + HALF, i2_ }, fset.ex1(x_Ph_H0)); - } else if constexpr (traits::fieldsetter::HasDx1 and + } else if constexpr (::traits::fieldsetter::HasDx1 and S == SimEngine::GRPIC) { Fld(i1, i2, em::dx1) = s * Fld(i1, i2, em::dx1) + (ONE - s) * fset.dx1(x_Ph_H0); @@ -245,7 +247,7 @@ namespace kernel::bc { } } - if constexpr (traits::fieldsetter::HasBx2) { + if constexpr (::traits::fieldsetter::HasBx2) { if (tags & BC::B) { if constexpr (S == SimEngine::SRPIC) { Fld(i1, i2, em::bx2) = s * Fld(i1, i2, em::bx2) + @@ -261,9 +263,9 @@ namespace kernel::bc { } } - if constexpr (traits::fieldsetter::HasEx2 or - traits::fieldsetter::HasDx2 or - traits::fieldsetter::HasBx1) { + if constexpr (::traits::fieldsetter::HasEx2 or + ::traits::fieldsetter::HasDx2 or + ::traits::fieldsetter::HasBx1) { // i1, i2 + 1/2 real_t xi_Cd; if constexpr (o == in::x1) { @@ -278,17 +280,17 @@ namespace kernel::bc { coord_t x_Ph_0H { ZERO }; metric.template convert({ i1_, i2_ + HALF }, x_Ph_0H); - if constexpr (traits::fieldsetter::HasEx2 or - traits::fieldsetter::HasDx2) { + if constexpr (::traits::fieldsetter::HasEx2 or + ::traits::fieldsetter::HasDx2) { if ((tags & BC::E) or (tags & BC::D)) { - if constexpr (traits::fieldsetter::HasEx2 and + if constexpr (::traits::fieldsetter::HasEx2 and S == SimEngine::SRPIC) { Fld(i1, i2, em::ex2) = s * Fld(i1, i2, em::ex2) + (ONE - s) * metric.template transform<2, Idx::T, Idx::U>( { i1_, i2_ + HALF }, fset.ex2(x_Ph_0H)); - } else if constexpr (traits::fieldsetter::HasDx2 and + } else if constexpr (::traits::fieldsetter::HasDx2 and S == SimEngine::GRPIC) { Fld(i1, i2, em::dx2) = s * Fld(i1, i2, em::dx2) + (ONE - s) * fset.dx2(x_Ph_0H); @@ -296,7 +298,7 @@ namespace kernel::bc { } } - if constexpr (traits::fieldsetter::HasBx1) { + if constexpr (::traits::fieldsetter::HasBx1) { if (tags & BC::B) { if constexpr (S == SimEngine::SRPIC) { Fld(i1, i2, em::bx1) = s * Fld(i1, i2, em::bx1) + @@ -313,8 +315,8 @@ namespace kernel::bc { } // if constexpr (defines_ex3 or defines_dx3) { - if constexpr (traits::fieldsetter::HasEx3 or - traits::fieldsetter::HasDx3) { + if constexpr (::traits::fieldsetter::HasEx3 or + ::traits::fieldsetter::HasDx3) { if (tags & BC::E) { // i1, i2 real_t xi_Cd; @@ -330,7 +332,7 @@ namespace kernel::bc { coord_t x_Ph_00 { ZERO }; metric.template convert({ i1_, i2_ }, x_Ph_00); - if constexpr (traits::fieldsetter::HasEx3 and + if constexpr (::traits::fieldsetter::HasEx3 and S == SimEngine::SRPIC) { Fld(i1, i2, em::ex3) = s * Fld(i1, i2, em::ex3); if ((!is_axis_i2min or (i2 > N_GHOSTS)) and @@ -340,7 +342,7 @@ namespace kernel::bc { { i1_, i2_ }, fset.ex3(x_Ph_00)); } - } else if constexpr (traits::fieldsetter::HasDx3 and + } else if constexpr (::traits::fieldsetter::HasDx3 and S == SimEngine::GRPIC) { Fld(i1, i2, em::dx3) = s * Fld(i1, i2, em::dx3); if ((!is_axis_i2min or (i2 > N_GHOSTS)) and @@ -351,7 +353,7 @@ namespace kernel::bc { } } - if constexpr (traits::fieldsetter::HasBx3) { + if constexpr (::traits::fieldsetter::HasBx3) { if (tags & BC::B) { // i1 + 1/2, i2 + 1/2 real_t xi_Cd; @@ -395,11 +397,11 @@ namespace kernel::bc { if constexpr (S == SimEngine::SRPIC) { // SRPIC - if constexpr (traits::fieldsetter::HasEx1 or - traits::fieldsetter::HasEx2 or - traits::fieldsetter::HasEx3) { + if constexpr (::traits::fieldsetter::HasEx1 or + ::traits::fieldsetter::HasEx2 or + ::traits::fieldsetter::HasEx3) { if (tags & BC::E) { - if constexpr (traits::fieldsetter::HasEx1) { + if constexpr (::traits::fieldsetter::HasEx1) { // i1 + 1/2, i2, i3 real_t xi_Cd; if constexpr (o == in::x1) { @@ -423,7 +425,7 @@ namespace kernel::bc { fset.ex1(x_Ph_H00)); } - if constexpr (traits::fieldsetter::HasEx2) { + if constexpr (::traits::fieldsetter::HasEx2) { // i1, i2 + 1/2, i3 real_t xi_Cd; if constexpr (o == in::x1) { @@ -447,7 +449,7 @@ namespace kernel::bc { fset.ex2(x_Ph_0H0)); } - if constexpr (traits::fieldsetter::HasEx3) { + if constexpr (::traits::fieldsetter::HasEx3) { // i1, i2, i3 + 1/2 real_t xi_Cd; if constexpr (o == in::x1) { @@ -475,11 +477,11 @@ namespace kernel::bc { } } - if constexpr (traits::fieldsetter::HasBx1 or - traits::fieldsetter::HasBx2 or - traits::fieldsetter::HasBx3) { + if constexpr (::traits::fieldsetter::HasBx1 or + ::traits::fieldsetter::HasBx2 or + ::traits::fieldsetter::HasBx3) { if (tags & BC::B) { - if constexpr (traits::fieldsetter::HasBx1) { + if constexpr (::traits::fieldsetter::HasBx1) { // i1, i2 + 1/2, i3 + 1/2 real_t xi_Cd; if constexpr (o == in::x1) { @@ -504,7 +506,7 @@ namespace kernel::bc { fset.bx1(x_Ph_0HH)); } - if constexpr (traits::fieldsetter::HasBx2) { + if constexpr (::traits::fieldsetter::HasBx2) { // i1 + 1/2, i2, i3 + 1/2 real_t xi_Cd; if constexpr (o == in::x1) { @@ -529,7 +531,7 @@ namespace kernel::bc { fset.bx2(x_Ph_H0H)); } - if constexpr (traits::fieldsetter::HasBx3) { + if constexpr (::traits::fieldsetter::HasBx3) { // i1 + 1/2, i2 + 1/2, i3 real_t xi_Cd; if constexpr (o == in::x1) { @@ -971,12 +973,12 @@ namespace kernel::bc { requires metric::traits::HasD && metric::traits::HasTransform_i && metric::traits::HasConvert && (static_cast(O) < static_cast(M::Dim)) && - (traits::fieldsetter::HasEx1 || - traits::fieldsetter::HasEx2 || - traits::fieldsetter::HasEx3 || - traits::fieldsetter::HasBx1 || - traits::fieldsetter::HasBx2 || - traits::fieldsetter::HasBx3) + (::traits::fieldsetter::HasEx1 || + ::traits::fieldsetter::HasEx2 || + ::traits::fieldsetter::HasEx3 || + ::traits::fieldsetter::HasBx1 || + ::traits::fieldsetter::HasBx2 || + ::traits::fieldsetter::HasBx3) struct EnforcedBoundaries_kernel { static constexpr Dimension D = M::Dim; @@ -1004,12 +1006,12 @@ namespace kernel::bc { coord_t x_Ph_H { ZERO }; metric.template convert({ i1_ }, x_Ph_0); metric.template convert({ i1_ + HALF }, x_Ph_H); - bool setEx1 = traits::fieldsetter::HasEx1 and (tags & BC::E), - setEx2 = traits::fieldsetter::HasEx2 and (tags & BC::E), - setEx3 = traits::fieldsetter::HasEx3 and (tags & BC::E), - setBx1 = traits::fieldsetter::HasBx1 and (tags & BC::B), - setBx2 = traits::fieldsetter::HasBx2 and (tags & BC::B), - setBx3 = traits::fieldsetter::HasBx3 and (tags & BC::B); + bool setEx1 = ::traits::fieldsetter::HasEx1 and (tags & BC::E), + setEx2 = ::traits::fieldsetter::HasEx2 and (tags & BC::E), + setEx3 = ::traits::fieldsetter::HasEx3 and (tags & BC::E), + setBx1 = ::traits::fieldsetter::HasBx1 and (tags & BC::B), + setBx2 = ::traits::fieldsetter::HasBx2 and (tags & BC::B), + setBx3 = ::traits::fieldsetter::HasBx3 and (tags & BC::B); if constexpr (O == in::x1) { // x1 -- normal // x2,x3 -- tangential @@ -1025,42 +1027,42 @@ namespace kernel::bc { } else { raise::KernelError(HERE, "Invalid Orientation"); } - if constexpr (traits::fieldsetter::HasEx1) { + if constexpr (::traits::fieldsetter::HasEx1) { if (setEx1) { Fld(i1, em::ex1) = metric.template transform<1, Idx::T, Idx::U>( { i1_ + HALF }, fset.ex1(x_Ph_H)); } } - if constexpr (traits::fieldsetter::HasEx2) { + if constexpr (::traits::fieldsetter::HasEx2) { if (setEx2) { Fld(i1, em::ex2) = metric.template transform<2, Idx::T, Idx::U>( { i1_ }, fset.ex2(x_Ph_0)); } } - if constexpr (traits::fieldsetter::HasEx3) { + if constexpr (::traits::fieldsetter::HasEx3) { if (setEx3) { Fld(i1, em::ex3) = metric.template transform<3, Idx::T, Idx::U>( { i1_ }, fset.ex3(x_Ph_0)); } } - if constexpr (traits::fieldsetter::HasBx1) { + if constexpr (::traits::fieldsetter::HasBx1) { if (setBx1) { Fld(i1, em::bx1) = metric.template transform<1, Idx::T, Idx::U>( { i1_ }, fset.bx1(x_Ph_0)); } } - if constexpr (traits::fieldsetter::HasBx2) { + if constexpr (::traits::fieldsetter::HasBx2) { if (setBx2) { Fld(i1, em::bx2) = metric.template transform<2, Idx::T, Idx::U>( { i1_ + HALF }, fset.bx2(x_Ph_H)); } } - if constexpr (traits::fieldsetter::HasBx3) { + if constexpr (::traits::fieldsetter::HasBx3) { if (setBx3) { Fld(i1, em::bx3) = metric.template transform<3, Idx::T, Idx::U>( { i1_ + HALF }, @@ -1085,12 +1087,12 @@ namespace kernel::bc { metric.template convert({ i1_ + HALF, i2_ }, x_Ph_H0); metric.template convert({ i1_ + HALF, i2_ + HALF }, x_Ph_HH); - bool setEx1 = traits::fieldsetter::HasEx1 and (tags & BC::E), - setEx2 = traits::fieldsetter::HasEx2 and (tags & BC::E), - setEx3 = traits::fieldsetter::HasEx3 and (tags & BC::E), - setBx1 = traits::fieldsetter::HasBx1 and (tags & BC::B), - setBx2 = traits::fieldsetter::HasBx2 and (tags & BC::B), - setBx3 = traits::fieldsetter::HasBx3 and (tags & BC::B); + bool setEx1 = ::traits::fieldsetter::HasEx1 and (tags & BC::E), + setEx2 = ::traits::fieldsetter::HasEx2 and (tags & BC::E), + setEx3 = ::traits::fieldsetter::HasEx3 and (tags & BC::E), + setBx1 = ::traits::fieldsetter::HasBx1 and (tags & BC::B), + setBx2 = ::traits::fieldsetter::HasBx2 and (tags & BC::B), + setBx3 = ::traits::fieldsetter::HasBx3 and (tags & BC::B); if constexpr (O == in::x1) { // x1 -- normal @@ -1119,42 +1121,42 @@ namespace kernel::bc { } else { raise::KernelError(HERE, "Invalid Orientation"); } - if constexpr (traits::fieldsetter::HasEx1) { + if constexpr (::traits::fieldsetter::HasEx1) { if (setEx1) { Fld(i1, i2, em::ex1) = metric.template transform<1, Idx::T, Idx::U>( { i1_ + HALF, i2_ }, fset.ex1(x_Ph_H0)); } } - if constexpr (traits::fieldsetter::HasEx2) { + if constexpr (::traits::fieldsetter::HasEx2) { if (setEx2) { Fld(i1, i2, em::ex2) = metric.template transform<2, Idx::T, Idx::U>( { i1_, i2_ + HALF }, fset.ex2(x_Ph_0H)); } } - if constexpr (traits::fieldsetter::HasEx3) { + if constexpr (::traits::fieldsetter::HasEx3) { if (setEx3) { Fld(i1, i2, em::ex3) = metric.template transform<3, Idx::T, Idx::U>( { i1_, i2_ }, fset.ex3(x_Ph_00)); } } - if constexpr (traits::fieldsetter::HasBx1) { + if constexpr (::traits::fieldsetter::HasBx1) { if (setBx1) { Fld(i1, i2, em::bx1) = metric.template transform<1, Idx::T, Idx::U>( { i1_, i2_ + HALF }, fset.bx1(x_Ph_0H)); } } - if constexpr (traits::fieldsetter::HasBx2) { + if constexpr (::traits::fieldsetter::HasBx2) { if (setBx2) { Fld(i1, i2, em::bx2) = metric.template transform<2, Idx::T, Idx::U>( { i1_ + HALF, i2_ }, fset.bx2(x_Ph_H0)); } } - if constexpr (traits::fieldsetter::HasBx3) { + if constexpr (::traits::fieldsetter::HasBx3) { if (setBx3) { Fld(i1, i2, em::bx3) = metric.template transform<3, Idx::T, Idx::U>( { i1_ + HALF, i2_ + HALF }, @@ -1190,12 +1192,12 @@ namespace kernel::bc { x_Ph_H0H); metric.template convert({ i1_, i2_ + HALF, i3_ + HALF }, x_Ph_0HH); - bool setEx1 = traits::fieldsetter::HasEx1 and (tags & BC::E), - setEx2 = traits::fieldsetter::HasEx2 and (tags & BC::E), - setEx3 = traits::fieldsetter::HasEx3 and (tags & BC::E), - setBx1 = traits::fieldsetter::HasBx1 and (tags & BC::B), - setBx2 = traits::fieldsetter::HasBx2 and (tags & BC::B), - setBx3 = traits::fieldsetter::HasBx3 and (tags & BC::B); + bool setEx1 = ::traits::fieldsetter::HasEx1 and (tags & BC::E), + setEx2 = ::traits::fieldsetter::HasEx2 and (tags & BC::E), + setEx3 = ::traits::fieldsetter::HasEx3 and (tags & BC::E), + setBx1 = ::traits::fieldsetter::HasBx1 and (tags & BC::B), + setBx2 = ::traits::fieldsetter::HasBx2 and (tags & BC::B), + setBx3 = ::traits::fieldsetter::HasBx3 and (tags & BC::B); if constexpr (O == in::x1) { // x1 -- normal // x2,x3 -- tangential @@ -1235,42 +1237,42 @@ namespace kernel::bc { } else { raise::KernelError(HERE, "Invalid Orientation"); } - if constexpr (traits::fieldsetter::HasEx1) { + if constexpr (::traits::fieldsetter::HasEx1) { if (setEx1) { Fld(i1, i2, i3, em::ex1) = metric.template transform<1, Idx::T, Idx::U>( { i1_ + HALF, i2_, i3_ }, fset.ex1(x_Ph_H00)); } } - if constexpr (traits::fieldsetter::HasEx2) { + if constexpr (::traits::fieldsetter::HasEx2) { if (setEx2) { Fld(i1, i2, i3, em::ex2) = metric.template transform<2, Idx::T, Idx::U>( { i1_, i2_ + HALF, i3_ }, fset.ex2(x_Ph_0H0)); } } - if constexpr (traits::fieldsetter::HasEx3) { + if constexpr (::traits::fieldsetter::HasEx3) { if (setEx3) { Fld(i1, i2, i3, em::ex3) = metric.template transform<3, Idx::T, Idx::U>( { i1_, i2_, i3_ + HALF }, fset.ex3(x_Ph_00H)); } } - if constexpr (traits::fieldsetter::HasBx1) { + if constexpr (::traits::fieldsetter::HasBx1) { if (setBx1) { Fld(i1, i2, i3, em::bx1) = metric.template transform<1, Idx::T, Idx::U>( { i1_, i2_ + HALF, i3_ + HALF }, fset.bx1(x_Ph_0HH)); } } - if constexpr (traits::fieldsetter::HasBx2) { + if constexpr (::traits::fieldsetter::HasBx2) { if (setBx2) { Fld(i1, i2, i3, em::bx2) = metric.template transform<2, Idx::T, Idx::U>( { i1_ + HALF, i2_, i3_ + HALF }, fset.bx2(x_Ph_H0H)); } } - if constexpr (traits::fieldsetter::HasBx3) { + if constexpr (::traits::fieldsetter::HasBx3) { if (setBx3) { Fld(i1, i2, i3, em::bx3) = metric.template transform<3, Idx::T, Idx::U>( { i1_ + HALF, i2_ + HALF, i3_ },