1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
/* Copyright 2021 Neil Zaim
*
* This file is part of WarpX.
*
* License: BSD-3-Clause-LBNL
*/
#include "FieldReduction.H"
#include "Utils/Parser/ParserUtils.H"
#include "Utils/TextMsg.H"
#include "Utils/WarpXAlgorithmSelection.H"
#include <AMReX_Algorithm.H>
#include <AMReX_BLassert.H>
#include <AMReX_ParmParse.H>
#include <AMReX_Vector.H>
#include <algorithm>
#include <ostream>
#include <regex>
// constructor
FieldReduction::FieldReduction (std::string rd_name)
: ReducedDiags{rd_name}
{
using namespace amrex::literals;
// RZ coordinate is not working
#if (defined WARPX_DIM_RZ)
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(false,
"FieldReduction reduced diagnostics does not work for RZ coordinate.");
#endif
// read number of levels
int nLevel = 0;
const amrex::ParmParse pp_amr("amr");
pp_amr.query("max_level", nLevel);
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(nLevel == 0,
"FieldReduction reduced diagnostics does not work with mesh refinement.");
constexpr int noutputs = 1; // A single output in the Field reduction diagnostic
// resize data array
m_data.resize(noutputs, 0.0_rt);
BackwardCompatibility();
const amrex::ParmParse pp_rd_name(rd_name);
// read reduced function with parser
std::string parser_string;
utils::parser::Store_parserString(pp_rd_name,"reduced_function(x,y,z,Ex,Ey,Ez,Bx,By,Bz,jx,jy,jz)",
parser_string);
m_parser = std::make_unique<amrex::Parser>(
utils::parser::makeParser(parser_string,{"x","y","z","Ex","Ey","Ez","Bx","By","Bz","jx","jy","jz"}));
// Replace all newlines and possible following whitespaces with a single whitespace. This
// should avoid weird formatting when the string is written in the header of the output file.
parser_string = std::regex_replace(parser_string, std::regex("\n\\s*"), " ");
// read reduction type
std::string reduction_type_string;
pp_rd_name.get("reduction_type", reduction_type_string);
m_reduction_type = GetAlgorithmInteger (pp_rd_name, "reduction_type");
if (amrex::ParallelDescriptor::IOProcessor())
{
if ( m_write_header )
{
// open file
std::ofstream ofs{m_path + m_rd_name + "." + m_extension, std::ofstream::out};
// write header row
int c = 0;
ofs << "#";
ofs << "[" << c++ << "]step()";
ofs << m_sep;
ofs << "[" << c++ << "]time(s)";
ofs << m_sep;
ofs << "[" << c++ << "]" + reduction_type_string + " of " + parser_string + " (SI units)";
ofs << std::endl;
// close file
ofs.close();
}
}
}
// end constructor
void FieldReduction::BackwardCompatibility ()
{
amrex::ParmParse pp_rd_name(m_rd_name);
std::vector<std::string> backward_strings;
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(
!pp_rd_name.queryarr("reduced_function(x,y,z,Ex,Ey,Ez,Bx,By,Bz)", backward_strings),
"<reduced_diag_name>.reduced_function(x,y,z,Ex,Ey,Ez,Bx,By,Bz) is no longer a valid option. "
"Please use the renamed option <reduced_diag_name>.reduced_function(x,y,z,Ex,Ey,Ez,Bx,By,Bz,jx,jy,jz) instead."
);
}
// function that does an arbitrary reduction of the electromagnetic fields
void FieldReduction::ComputeDiags (int step)
{
// Judge if the diags should be done
if (!m_intervals.contains(step+1)) { return; }
if (m_reduction_type == ReductionType::Maximum)
{
ComputeFieldReduction<amrex::ReduceOpMax>();
}
else if (m_reduction_type == ReductionType::Minimum)
{
ComputeFieldReduction<amrex::ReduceOpMin>();
}
else if (m_reduction_type == ReductionType::Sum)
{
ComputeFieldReduction<amrex::ReduceOpSum>();
}
}
// end void FieldMaximum::ComputeDiags
|