5
5
#include < utility>
6
6
#include " AMReX_ParmParse.H"
7
7
#include " amr-wind/utilities/IOManager.H"
8
+ #include " amr-wind/utilities/constants.H"
8
9
9
10
namespace amr_wind ::field_norms {
10
11
@@ -22,20 +23,42 @@ void FieldNorms::initialize()
22
23
amrex::ParmParse pp (m_label);
23
24
populate_output_parameters (pp);
24
25
pp.query (" mask_redundant_grids" , m_use_mask);
26
+ pp.query (" use_vector_magnitude" , m_use_vector_magnitude);
27
+ std::string norm_type (std::to_string (m_norm_type));
28
+ pp.query (" norm_type" , norm_type);
29
+ if (norm_type == " 2" ) {
30
+ m_norm_type = 2 ;
31
+ } else if (norm_type == " 1" ) {
32
+ m_norm_type = 1 ;
33
+ } else if (amrex::toLower (norm_type) == " infinity" ) {
34
+ m_norm_type = -1 ;
35
+ } else {
36
+ amrex::Abort (
37
+ " FieldNorms: norm_type not recognized. Valid options are 1, 2, "
38
+ " and infinity." );
39
+ }
25
40
}
26
41
27
42
const auto & io_mng = m_sim.io_manager ();
28
43
for (const auto & fld : io_mng.plot_fields ()) {
29
- ioutils::add_var_names (m_var_names, fld->name (), fld->num_comp ());
44
+ if (m_use_vector_magnitude) {
45
+ m_var_names.push_back (fld->name ());
46
+ } else {
47
+ ioutils::add_var_names (m_var_names, fld->name (), fld->num_comp ());
48
+ }
30
49
}
31
50
32
51
m_fnorms.resize (m_var_names.size (), 0.0 );
33
52
34
53
prepare_ascii_file ();
35
54
}
36
55
37
- amrex::Real FieldNorms::l2_norm (
38
- const amr_wind::Field& field, const int comp, const bool use_mask)
56
+ amrex::Real FieldNorms::get_norm (
57
+ const amr_wind::Field& field,
58
+ const int comp,
59
+ const int ncomp,
60
+ const int norm_type,
61
+ const bool use_mask)
39
62
{
40
63
amrex::Real nrm = 0.0 ;
41
64
@@ -81,55 +104,111 @@ amrex::Real FieldNorms::l2_norm(
81
104
level_mask.setVal (1 .);
82
105
}
83
106
84
- nrm += amrex::ReduceSum (
85
- level_mask, field (lev), nghost,
86
- [=] AMREX_GPU_HOST_DEVICE (
87
- amrex::Box const & bx,
88
- amrex::Array4<amrex::Real const > const & mask_arr,
89
- amrex::Array4<amrex::Real const > const & field_arr)
90
- -> amrex::Real {
91
- amrex::Real nrm_fab = 0.0 ;
92
-
93
- const auto & fbx =
94
- it_sum == 1
95
- ? amrex::surroundingNodes (bx, node_dir)
96
- : (it_sum > 1 ? amrex::surroundingNodes (bx) : bx);
97
-
98
- amrex::Loop (fbx, [=, &nrm_fab](int i, int j, int k) noexcept {
99
- const amrex::IntVect iv{i, j, k};
100
- amrex::IntVect iv_cc = iv;
101
- // adjust volume for different data locations
102
- amrex::Real data_vol = cell_vol;
103
- for (int nn = 0 ; nn < AMREX_SPACEDIM; ++nn) {
104
- const bool at_node_dir =
105
- index_type[nn] == 1 && (iv[nn] == fbx.bigEnd (nn) ||
106
- iv[nn] == fbx.smallEnd (nn));
107
- data_vol *= at_node_dir ? 0.5 : 1.0 ;
108
- // limit mask array indices to cell-centered
109
- iv_cc[nn] = amrex::min (
110
- bx.bigEnd (nn),
111
- amrex::max (bx.smallEnd (nn), iv_cc[nn]));
112
- }
113
- nrm_fab += data_vol * field_arr (iv, comp) *
114
- field_arr (iv, comp) * mask_arr (iv_cc);
107
+ if (norm_type > 0 ) {
108
+ nrm += amrex::ReduceSum (
109
+ level_mask, field (lev), nghost,
110
+ [=] AMREX_GPU_HOST_DEVICE (
111
+ amrex::Box const & bx,
112
+ amrex::Array4<amrex::Real const > const & mask_arr,
113
+ amrex::Array4<amrex::Real const > const & field_arr)
114
+ -> amrex::Real {
115
+ amrex::Real nrm_fab = 0.0 ;
116
+
117
+ const auto & fbx =
118
+ it_sum == 1
119
+ ? amrex::surroundingNodes (bx, node_dir)
120
+ : (it_sum > 1 ? amrex::surroundingNodes (bx) : bx);
121
+
122
+ amrex::Loop (
123
+ fbx, [=, &nrm_fab](int i, int j, int k) noexcept {
124
+ const amrex::IntVect iv{i, j, k};
125
+ amrex::IntVect iv_cc = iv;
126
+ // adjust volume for different data locations
127
+ amrex::Real data_vol = cell_vol;
128
+ for (int nn = 0 ; nn < AMREX_SPACEDIM; ++nn) {
129
+ const bool at_node_dir =
130
+ index_type[nn] == 1 &&
131
+ (iv[nn] == fbx.bigEnd (nn) ||
132
+ iv[nn] == fbx.smallEnd (nn));
133
+ data_vol *= at_node_dir ? 0.5 : 1.0 ;
134
+ // limit mask array indices to cell-centered
135
+ iv_cc[nn] = amrex::min (
136
+ bx.bigEnd (nn),
137
+ amrex::max (bx.smallEnd (nn), iv_cc[nn]));
138
+ }
139
+ amrex::Real fval =
140
+ std::abs (field_arr (i, j, k, comp));
141
+ // Calculate magnitude if requested
142
+ for (int n = 1 ; n < ncomp; ++n) {
143
+ fval *= fval;
144
+ fval += field_arr (i, j, k, n) *
145
+ field_arr (i, j, k, n);
146
+ fval = std::sqrt (fval);
147
+ }
148
+ fval *= norm_type == 2 ? fval : 1 .;
149
+ nrm_fab += data_vol * fval * mask_arr (iv_cc);
150
+ });
151
+ return nrm_fab;
152
+ });
153
+ } else {
154
+ // Can directly use the field box for the infinity norm
155
+ const amrex::Real nrm_lev = amrex::ReduceMax (
156
+ field (lev), level_mask, nghost,
157
+ [=] AMREX_GPU_HOST_DEVICE (
158
+ amrex::Box const & bx,
159
+ amrex::Array4<amrex::Real const > const & field_arr,
160
+ amrex::Array4<amrex::Real const > const & mask_arr)
161
+ -> amrex::Real {
162
+ amrex::Real nrm_fab = 0.0 ;
163
+
164
+ amrex::Loop (
165
+ bx, [=, &nrm_fab](int i, int j, int k) noexcept {
166
+ amrex::Real fval =
167
+ std::abs (field_arr (i, j, k, comp));
168
+ // Calculate magnitude if requested
169
+ for (int n = 1 ; n < ncomp; ++n) {
170
+ fval *= fval;
171
+ fval += field_arr (i, j, k, n) *
172
+ field_arr (i, j, k, n);
173
+ fval = std::sqrt (fval);
174
+ }
175
+ if (std::abs (mask_arr (i, j, k) - 1 .) <
176
+ constants::TIGHT_TOL) {
177
+ nrm_fab = std::max (nrm_fab, fval);
178
+ }
179
+ });
180
+ return nrm_fab;
115
181
});
116
- return nrm_fab ;
117
- });
182
+ nrm = amrex::max (nrm_lev, nrm) ;
183
+ }
118
184
}
119
185
120
- amrex::ParallelDescriptor::ReduceRealSum (nrm);
121
-
122
- const amrex::Real total_volume = geom[0 ].ProbDomain ().volume ();
186
+ if (norm_type > 0 ) {
187
+ amrex::ParallelDescriptor::ReduceRealSum (nrm);
188
+ const amrex::Real total_volume = geom[0 ].ProbDomain ().volume ();
189
+ nrm /= total_volume;
190
+ if (norm_type == 2 ) {
191
+ nrm = std::sqrt (nrm);
192
+ }
193
+ } else {
194
+ amrex::ParallelDescriptor::ReduceRealMax (nrm);
195
+ }
123
196
124
- return std::sqrt ( nrm / total_volume) ;
197
+ return nrm;
125
198
}
126
199
127
200
void FieldNorms::process_field_norms ()
128
201
{
129
202
int ind = 0 ;
130
203
for (const auto & fld : m_sim.io_manager ().plot_fields ()) {
131
- for (int comp = 0 ; comp < fld->num_comp (); ++comp) {
132
- m_fnorms[ind++] = l2_norm (*fld, comp, m_use_mask);
204
+ if (m_use_vector_magnitude) {
205
+ m_fnorms[ind++] =
206
+ get_norm (*fld, 0 , fld->num_comp (), m_norm_type, m_use_mask);
207
+ } else {
208
+ for (int comp = 0 ; comp < fld->num_comp (); ++comp) {
209
+ m_fnorms[ind++] =
210
+ get_norm (*fld, comp, 1 , m_norm_type, m_use_mask);
211
+ }
133
212
}
134
213
}
135
214
}
0 commit comments