1 #ifndef ERF_NODAL_RECONSTRUCTION_H_
2 #define ERF_NODAL_RECONSTRUCTION_H_
10 #include "AMReX_Array4.H"
11 #include "AMReX_Box.H"
12 #include "AMReX_FArrayBox.H"
13 #include "AMReX_Geometry.H"
14 #include "AMReX_REAL.H"
125 amrex::Geometry
const& geom)
127 m_ilo(face_box.smallEnd(0)),
128 m_ihi(face_box.bigEnd(0)),
129 m_jlo(face_box.smallEnd(1)),
130 m_jhi(face_box.bigEnd(1))
132 if (face_box.length(2) != 1) {
133 throw std::invalid_argument(
134 "face_box must contain exactly one z cell.");
136 if (face_box.smallEnd(2) != 0) {
137 throw std::invalid_argument(
138 "face_box must be a slab at k = 0; all fabs are indexed at k = 0.");
145 Real const dx = geom.CellSizeArray()[0];
146 Real const dy = geom.CellSizeArray()[1];
148 throw std::invalid_argument(
"Cell sizes must be positive.");
161 [[nodiscard]] amrex::Box
const&
nodalBox () const noexcept {
173 amrex::FArrayBox
R(
m_nodal_box,1,amrex::The_Managed_Arena());
174 auto const T_arr =
T.const_array();
175 auto const R_arr =
R.array();
178 int const jm = std::max(
m_jlo, std::min(j-1,
m_jhi));
179 int const jp = std::max(
m_jlo, std::min(j ,
m_jhi));
181 int const im = std::max(
m_ilo, std::min(i-1,
m_ihi));
182 int const ip = std::max(
m_ilo, std::min(i ,
m_ihi));
183 R_arr(i,j,0) =
fourth * ( T_arr(im,jm,0) + T_arr(ip,jm,0)
184 + T_arr(im,jp,0) + T_arr(ip,jp,0) );
202 [[nodiscard]] std::pair<amrex::FArrayBox,SolveInfo>
204 amrex::FArrayBox
const& reference,
206 Real relative_tolerance =
Real(1.e-10),
208 Real min_regularization =
Real(2.5e-4),
209 int max_iterations = 1000)
211 if (!(smoothing >
zero)) {
212 throw std::invalid_argument(
"Smoothing weight must be positive.");
214 if (!(min_regularization >
zero)) {
218 throw std::invalid_argument(
"Regularization must be positive.");
230 amrex::FArrayBox misfit(
m_face_box,1,amrex::The_Managed_Arena());
232 Real t_min = std::numeric_limits<Real>::max();
233 Real t_max = -std::numeric_limits<Real>::max();
236 auto const T_arr =
T.const_array();
237 auto const m_arr = misfit.array();
240 m_arr(i,j,0) = T_arr(i,j,0) - m_arr(i,j,0);
241 misfit_max = std::max(misfit_max, std::abs(m_arr(i,j,0)));
242 t_min = std::min(t_min, T_arr(i,j,0));
243 t_max = std::max(t_max, T_arr(i,j,0));
252 amrex::FArrayBox rhs(
m_nodal_box,1,amrex::The_Managed_Arena());
255 amrex::FArrayBox E(
m_nodal_box,1,amrex::The_Managed_Arena());
256 amrex::FArrayBox S(
m_nodal_box,1,amrex::The_Managed_Arena());
258 m_mu = min_regularization;
259 bool accepted =
false;
274 auto const S_arr = S.array();
275 auto const r_arr = reference.const_array();
276 auto const E_arr = E.const_array();
279 S_arr(i,j,0) = r_arr(i,j,0) + E_arr(i,j,0);
285 S.copy<amrex::RunOn::Host>(reference,0,0,1);
291 return {std::move(S),info};
296 amrex::FArrayBox
const& S)
const
298 auto const T_arr =
T.const_array();
299 auto const S_arr = S.const_array();
303 Real const avg =
fourth * ( S_arr(i ,j ,0) + S_arr(i+1,j ,0)
304 + S_arr(i ,j+1,0) + S_arr(i+1,j+1,0) );
305 err = std::max(err, std::abs(avg - T_arr(i,j,0)));
313 auto const S_arr = S.const_array();
318 Real const d = S_arr(i+1,j,0) - S_arr(i,j,0);
324 Real const d = S_arr(i,j+1,0) - S_arr(i,j,0);
361 amrex::FArrayBox&
T)
const
363 auto const S_arr = S.const_array();
364 auto const T_arr =
T.array();
367 T_arr(i,j,0) =
fourth * ( S_arr(i ,j ,0) + S_arr(i+1,j ,0)
368 + S_arr(i ,j+1,0) + S_arr(i+1,j+1,0) );
375 amrex::FArrayBox&
R)
const
377 R.setVal<amrex::RunOn::Host>(
zero);
378 auto const T_arr =
T.const_array();
379 auto const R_arr =
R.array();
384 R_arr(i+1,j ,0) +=
q;
385 R_arr(i ,j+1,0) +=
q;
386 R_arr(i+1,j+1,0) +=
q;
392 amrex::FArrayBox& difx,
393 amrex::FArrayBox& dify)
const
395 difx.setVal<amrex::RunOn::Host>(
zero);
396 dify.setVal<amrex::RunOn::Host>(
zero);
398 auto const S_arr = S.const_array();
399 auto const difx_arr = difx.array();
400 auto const dify_arr = dify.array();
404 difx_arr(i, j, 0) =
m_gx * ( S_arr(i+1, j, 0) - S_arr(i, j, 0) );
410 dify_arr(i, j, 0) =
m_gy * ( S_arr(i, j+1, 0) - S_arr(i, j, 0) );
416 amrex::FArrayBox
const& dify,
417 amrex::FArrayBox&
R)
const
419 R.setVal<amrex::RunOn::Host>(
zero);
421 auto const qx_arr = difx.const_array();
422 auto const qy_arr = dify.const_array();
423 auto const R_arr =
R.array();
427 R_arr(i , j, 0) -=
m_gx * qx_arr(i, j, 0);
428 R_arr(i+1, j, 0) +=
m_gx * qx_arr(i, j, 0);
434 R_arr(i, j , 0) -=
m_gy * qy_arr(i, j, 0);
435 R_arr(i, j+1, 0) +=
m_gy * qy_arr(i, j, 0);
441 amrex::FArrayBox&
R)
const
445 x_edge_box.growHi(0,-1);
446 y_edge_box.growHi(1,-1);
447 amrex::FArrayBox difx(x_edge_box,1,amrex::The_Managed_Arena());
448 amrex::FArrayBox dify(y_edge_box,1,amrex::The_Managed_Arena());
454 amrex::FArrayBox& lap)
const
456 lap.setVal<amrex::RunOn::Host>(
zero);
458 auto const S_arr = S.const_array();
459 auto const lap_arr = lap.array();
463 lap_arr(i, j, 0) =
m_gxx * ( S_arr(i+1, j , 0)
464 -
two * S_arr(i , j , 0)
465 + S_arr(i-1, j , 0) )
466 +
m_gyy * ( S_arr(i , j+1, 0)
467 -
two * S_arr(i , j , 0)
468 + S_arr(i , j-1, 0) );
474 amrex::FArrayBox&
R)
const
476 R.setVal<amrex::RunOn::Host>(
zero);
478 auto const q_arr = lap.const_array();
479 auto const R_arr =
R.array();
484 R_arr(i-1, j , 0) +=
m_gxx * val;
485 R_arr(i+1, j , 0) +=
m_gxx * val;
486 R_arr(i , j-1, 0) +=
m_gyy * val;
487 R_arr(i , j+1, 0) +=
m_gyy * val;
494 amrex::FArrayBox&
R)
const
497 interior_nodal_box.grow(0,-1);
498 interior_nodal_box.grow(1,-1);
499 if (!interior_nodal_box.ok()) {
502 R.setVal<amrex::RunOn::Host>(
zero);
505 amrex::FArrayBox lap(interior_nodal_box,1,amrex::The_Managed_Arena());
511 amrex::FArrayBox&
R)
const
523 throw std::runtime_error(
"Unsupported variation operator.");
529 amrex::FArrayBox&
R)
const
535 auto const R_arr =
R.array();
537 auto const S_arr = S.const_array();
540 R_arr(i,j,0) +=
m_lambda * v_arr(i,j,0) +
m_mu * S_arr(i,j,0);
551 diag.setVal<amrex::RunOn::Host>(
m_mu);
552 auto const d_arr = diag.array();
558 d_arr(i ,j ,0) +=
qa;
559 d_arr(i+1,j ,0) +=
qa;
560 d_arr(i ,j+1,0) +=
qa;
561 d_arr(i+1,j+1,0) +=
qa;
572 d_arr(i+1,j,0) += qx;
578 d_arr(i,j+1,0) += qy;
587 d_arr(i-1,j ,0) += qx;
588 d_arr(i+1,j ,0) += qx;
589 d_arr(i ,j-1,0) += qy;
590 d_arr(i ,j+1,0) += qy;
591 d_arr(i ,j ,0) +=
qc;
598 amrex::FArrayBox
const& S,
601 auto const S_arr = S.const_array();
602 Real smin = std::numeric_limits<Real>::max();
603 Real smax = -std::numeric_limits<Real>::max();
606 smin = std::min(smin, S_arr(i,j,0));
607 smax = std::max(smax, S_arr(i,j,0));
617 auto const F_arr = F.const_array();
621 v = std::max(v, std::abs(F_arr(i,j,0)));
632 Real relative_tolerance,
633 int max_iterations)
const
635 amrex::FArrayBox diag(
m_nodal_box,1,amrex::The_Managed_Arena());
638 amrex::FArrayBox r (
m_nodal_box,1,amrex::The_Managed_Arena());
639 amrex::FArrayBox
z (
m_nodal_box,1,amrex::The_Managed_Arena());
640 amrex::FArrayBox
p (
m_nodal_box,1,amrex::The_Managed_Arena());
641 amrex::FArrayBox Mp(
m_nodal_box,1,amrex::The_Managed_Arena());
643 x.setVal<amrex::RunOn::Host>(
zero);
644 r.copy<amrex::RunOn::Host>(rhs,0,0,1);
646 p.copy<amrex::RunOn::Host>(
z,0,0,1);
649 Real const initial = std::sqrt(
dot(r,r));
650 Real const tol = relative_tolerance * std::max({initial,
one});
654 if (initial <= tol) {
655 info.converged =
true;
659 for (
int it=0; it<max_iterations; ++it) {
662 if (!(pMp >
zero) || !std::isfinite(pMp)) {
663 throw std::runtime_error(
"CG curvature failure.");
668 auto const x_arr =
x.array();
669 auto const r_arr = r.array();
670 auto const p_arr =
p.const_array();
671 auto const Mp_arr = Mp.const_array();
674 x_arr(i,j,0) +=
alpha * p_arr(i,j,0);
675 r_arr(i,j,0) -=
alpha * Mp_arr(i,j,0);
680 info.iterations = it+1;
681 info.final_residual = std::sqrt(
dot(r,r));
682 if (info.final_residual <= tol) {
683 info.converged =
true;
691 auto const p_arr =
p.array();
692 auto const z_arr =
z.const_array();
695 p_arr(i,j,0) = z_arr(i,j,0) +
beta * p_arr(i,j,0);
705 amrex::FArrayBox
const& r,
706 amrex::FArrayBox&
z)
const
708 auto const d_arr = diag.const_array();
709 auto const r_arr = r.const_array();
710 auto const z_arr =
z.array();
713 z_arr(i,j,0) = r_arr(i,j,0) / d_arr(i,j,0);
718 [[nodiscard]]
Real dot (amrex::FArrayBox
const& a,
719 amrex::FArrayBox
const& b)
const
721 auto const a_arr = a.const_array();
722 auto const b_arr = b.const_array();
726 v += a_arr(i,j,0) * b_arr(i,j,0);
constexpr amrex::Real four
Definition: ERF_Constants.H:12
constexpr amrex::Real two
Definition: ERF_Constants.H:10
constexpr amrex::Real one
Definition: ERF_Constants.H:9
constexpr amrex::Real fourth
Definition: ERF_Constants.H:14
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
Real value
Definition: ERF_HurricaneDiagnostics.cpp:30
const Real dy
Definition: ERF_InitCustomPert_ABL.H:24
const Real dx
Definition: ERF_InitCustomPert_ABL.H:23
Real T
Definition: ERF_InitCustomPert_Bubble.H:106
amrex::Real beta
Definition: ERF_InitCustomPert_DataAssimilation_ISV.H:10
VariationOperator
Definition: ERF_NodalReconstruction.H:19
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_NodalReconstruction.H:120
amrex::Real m_gyy
Definition: ERF_NodalReconstruction.H:351
void applyLTL(amrex::FArrayBox const &S, amrex::FArrayBox &R) const
Definition: ERF_NodalReconstruction.H:493
void applyDT(amrex::FArrayBox const &difx, amrex::FArrayBox const &dify, amrex::FArrayBox &R) const
Definition: ERF_NodalReconstruction.H:415
SolveInfo conjugateGradient(amrex::FArrayBox const &rhs, amrex::FArrayBox &x, Real relative_tolerance, int max_iterations) const
Definition: ERF_NodalReconstruction.H:630
amrex::Real m_lambda
Definition: ERF_NodalReconstruction.H:352
int m_ihi
Definition: ERF_NodalReconstruction.H:345
void applyAT(amrex::FArrayBox const &T, amrex::FArrayBox &R) const
Adjoint of applyA: scatter each cell value to its four nodes.
Definition: ERF_NodalReconstruction.H:374
Real maxAverageError(amrex::FArrayBox const &T, amrex::FArrayBox const &S) const
max_ij | avg4(S) - T |
Definition: ERF_NodalReconstruction.H:295
amrex::Box const & nodalBox() const noexcept
Definition: ERF_NodalReconstruction.H:161
VariationOperator m_var_op
Definition: ERF_NodalReconstruction.H:354
void applyJacobi(amrex::FArrayBox const &diag, amrex::FArrayBox const &r, amrex::FArrayBox &z) const
Definition: ERF_NodalReconstruction.H:704
int m_ilo
Definition: ERF_NodalReconstruction.H:344
void computeDiagonal(amrex::FArrayBox &diag) const
Definition: ERF_NodalReconstruction.H:549
Real totalSquaredVariation(amrex::FArrayBox const &S) const
Definition: ERF_NodalReconstruction.H:311
amrex::FArrayBox makeReference(amrex::FArrayBox const &T) const
Definition: ERF_NodalReconstruction.H:171
void applyM(amrex::FArrayBox const &S, amrex::FArrayBox &R) const
R = ( A^T A + lambda V^T V + mu I ) S.
Definition: ERF_NodalReconstruction.H:528
void applyA(amrex::FArrayBox const &S, amrex::FArrayBox &T) const
(A S)(i,j) = 1/4 [ S(i,j) + S(i+1,j) + S(i,j+1) + S(i+1,j+1) ]
Definition: ERF_NodalReconstruction.H:360
static constexpr amrex::Real relief_factor
... nor than this fraction of the relief of the data.
Definition: ERF_NodalReconstruction.H:336
void applyD(amrex::FArrayBox const &S, amrex::FArrayBox &difx, amrex::FArrayBox &dify) const
Definition: ERF_NodalReconstruction.H:391
amrex::Real m_gxx
Definition: ERF_NodalReconstruction.H:350
amrex::FArrayBox m_nd_scratch
Definition: ERF_NodalReconstruction.H:357
Real maxAbs(amrex::FArrayBox const &F) const
Definition: ERF_NodalReconstruction.H:615
void applyLT(amrex::FArrayBox const &lap, amrex::FArrayBox &R) const
Definition: ERF_NodalReconstruction.H:473
static constexpr amrex::Real mu_growth
Definition: ERF_NodalReconstruction.H:339
amrex::Box m_nodal_box
Definition: ERF_NodalReconstruction.H:343
std::pair< amrex::FArrayBox, SolveInfo > solve(amrex::FArrayBox const &T, amrex::FArrayBox const &reference, VariationOperator var_op, Real relative_tolerance=Real(1.e-10), Real smoothing=Real(1.e-2), Real min_regularization=Real(2.5e-4), int max_iterations=1000)
Definition: ERF_NodalReconstruction.H:203
amrex::FArrayBox m_cc_scratch
Definition: ERF_NodalReconstruction.H:356
amrex::Real m_mu
Definition: ERF_NodalReconstruction.H:353
int m_jlo
Definition: ERF_NodalReconstruction.H:346
static constexpr amrex::Real deviation_factor
Definition: ERF_NodalReconstruction.H:334
void applyVariationOperator(amrex::FArrayBox const &S, amrex::FArrayBox &R) const
Definition: ERF_NodalReconstruction.H:510
void computeDiagnostics(amrex::FArrayBox const &T, amrex::FArrayBox const &S, SolveInfo &info) const
Definition: ERF_NodalReconstruction.H:597
amrex::Real m_gx
Definition: ERF_NodalReconstruction.H:348
NodalReconstruction(amrex::Box const &face_box, amrex::Geometry const &geom)
Definition: ERF_NodalReconstruction.H:124
Real dot(amrex::FArrayBox const &a, amrex::FArrayBox const &b) const
Definition: ERF_NodalReconstruction.H:718
amrex::Real m_gy
Definition: ERF_NodalReconstruction.H:349
void applyL(amrex::FArrayBox const &S, amrex::FArrayBox &lap) const
Definition: ERF_NodalReconstruction.H:453
amrex::Real Real
Definition: ERF_NodalReconstruction.H:122
amrex::Box m_face_box
Definition: ERF_NodalReconstruction.H:342
int m_jhi
Definition: ERF_NodalReconstruction.H:347
void applyDTD(amrex::FArrayBox const &S, amrex::FArrayBox &R) const
Definition: ERF_NodalReconstruction.H:440
static constexpr int max_attempts
Definition: ERF_NodalReconstruction.H:340
@ qc
Definition: ERF_SatAdj.H:40
@ R
Definition: ERF_IndexDefines.H:127
@ q
Definition: ERF_WSM6.H:184
@ p
Definition: ERF_WSM6.H:191
@ qa
Definition: ERF_AdvanceWSM6.cpp:136
real(kind=kind_phys), parameter, public alpha
Definition: ERF_module_mp_wsm6.F90:44
Definition: ERF_NodalReconstruction.H:24
amrex::Real final_residual
CG residual of the accepted solve.
Definition: ERF_NodalReconstruction.H:26
int iterations
total CG iterations, summed over attempts
Definition: ERF_NodalReconstruction.H:25
amrex::Real max_average_error
max |avg4(S) - T|
Definition: ERF_NodalReconstruction.H:34
amrex::Real max_value
max over nodes of S
Definition: ERF_NodalReconstruction.H:37
amrex::Real min_value
min over nodes of S
Definition: ERF_NodalReconstruction.H:36
bool converged
Definition: ERF_NodalReconstruction.H:27
int refinements
times the regularization had to be raised
Definition: ERF_NodalReconstruction.H:28
amrex::Real deviation
max |S - S_ref|
Definition: ERF_NodalReconstruction.H:32
amrex::Real deviation_cap
bound imposed on the above
Definition: ERF_NodalReconstruction.H:33
amrex::Real interp_average_error
max |avg4(S_ref) - T|, for comparison
Definition: ERF_NodalReconstruction.H:35
amrex::Real regularization
accepted value of mu
Definition: ERF_NodalReconstruction.H:29