flow 1.3.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
anderson_accelerator.hpp
Go to the documentation of this file.
1
21#ifndef PECLET_FLOW_ANDERSON_ACCELERATOR_HPP
22#define PECLET_FLOW_ANDERSON_ACCELERATOR_HPP
23
24#include <array>
25#include <chrono>
26#include <cstddef>
27#include <stdexcept>
28#include <string>
29#include <utility>
30
31#include "flow_ibm.hpp"
32#include "peclet/core/solver/anderson.hpp"
33#ifdef PECLET_FLOW_MPI
34#include "peclet/core/solver/anderson_mpi.hpp"
35#endif
36
37namespace peclet::flow {
38
39template <class Grid>
41 public:
42 using Core = peclet::core::solver::AndersonCore;
43
47 explicit AndersonAccelerator(Solver<Grid>& solver, int window = 5, double mixing = 1.0)
48 : AndersonAccelerator(solver, solver.marchState(), window, mixing) {}
49
52
55 void step(bool accelerate);
56
57 // ---- status (forwarded from the core) ----
58 const char* statusName() const { return core_.statusName(); }
59 const std::string& reason() const { return core_.reason(); }
61 double residual() const { return core_.residual(); }
62 int numRestarts() const { return core_.numRestarts(); }
63 int numResets() const { return core_.numResets(); }
64 int numColumns() const { return core_.numColumns(); }
65 int window() const { return core_.window(); }
66 double mixing() const { return core_.mixing(); }
68 std::size_t memoryBytes() const { return core_.memoryBytes(); }
71 double seconds() const { return seconds_; }
72 void reset() { core_.reset(); }
73 void disable() { core_.disable(); }
75 const Core& core() const { return core_; }
76
77 private:
79 double mixing);
80 static Core makeCore(typename Solver<Grid>::MarchState& ms, int window, double mixing);
81 static double now();
82
83 Solver<Grid>& s_;
84 std::array<double, 9> sig_;
85 Core core_;
86 double seconds_ = 0.0;
87};
88
89template <class Grid>
91 typename Solver<Grid>::MarchState ms, int window,
92 double mixing)
93 : s_(solver), sig_(ms.signature), core_(makeCore(ms, window, mixing)) {}
94
95template <class Grid>
96typename AndersonAccelerator<Grid>::Core AndersonAccelerator<Grid>::makeCore(
97 typename Solver<Grid>::MarchState& ms, int window, double mixing) {
98 peclet::core::solver::AndersonState st;
99 st.fields = ms.fields;
100 st.roles = ms.roles;
101 st.extent = {ms.e.x, ms.e.y, ms.e.z};
102 st.ghost = ms.G;
103#ifdef PECLET_FLOW_MPI
104 if (ms.distributed)
105 st.comm = peclet::core::solver::andersonComm(ms.comm);
106#endif
107 try {
108 return Core(std::move(st), window, mixing);
109 } catch (const std::runtime_error& e) { // the history does not fit (§6.3), on every rank
110 throw std::runtime_error(std::string("AndersonAccelerator: ") + e.what() +
111 "; pass accelerate=False");
112 }
113}
114
115template <class Grid>
116double AndersonAccelerator<Grid>::now() {
117 return std::chrono::duration<double>(std::chrono::steady_clock::now().time_since_epoch()).count();
118}
119
120template <class Grid>
122 double t0 = now();
123 // §5.3: the refusals are re-evaluated at every call (host flags only), so a feature enabled
124 // after construction is refused at the next call.
125 const auto ms = s_.marchState();
126 // A different number of state fields is a configuration change (review R5): on the collocated
127 // grid set_advection / the projected-face advection add or remove the face field uf/vf/wf. The
128 // history belongs to the old map, so it is invalidated, and the core cannot mix a state it was
129 // not built on, so the call is refused.
130 const auto& held = core_.state().fields;
131 if (held.size() != ms.fields.size()) {
132 core_.invalidate();
133 throw std::logic_error(
134 "AndersonAccelerator: the march state changed from " + std::to_string(held.size()) +
135 " to " + std::to_string(ms.fields.size()) +
136 " fields since construction (a configuration change: set_advection on the collocated "
137 "solver adds or removes the face field uf/vf/wf); construct a new accelerator");
138 }
139 // The core mixes the buffers it was built on; a redistribute reallocates them, after which the
140 // accelerator would act on buffers the solver no longer reads.
141 bool same = true;
142 for (std::size_t f = 0; same && f < held.size(); ++f)
143 same = held[f].data() == ms.fields[f].data() && held[f].extent(0) == ms.fields[f].extent(0);
144 if (!same)
145 throw std::logic_error(
146 "AndersonAccelerator: the solver's state buffers were reallocated (a redistribute or a "
147 "rebalance since construction); construct a new accelerator");
148 // §4.3 step 0, the signature half: a parameter change is a new map (dt, rho, mu, F, and since
149 // review R5 the advection settings, so staggered set_advection between calls resets too).
150 if (core_.status() == Core::Status::Active && ms.signature != sig_) {
151 core_.invalidate();
152 sig_ = ms.signature;
153 }
154 core_.prepare(accelerate);
155 Kokkos::fence();
156 seconds_ += now() - t0;
157 try {
158 s_.step();
159 } catch (const std::exception& e) {
160 t0 = now();
161 const bool absorbed = core_.stepFailed(e.what());
162 seconds_ += now() - t0;
163 if (!absorbed)
164 throw;
165 return;
166 }
167 t0 = now();
168 core_.complete(s_.pressureSolveFailed());
169 Kokkos::fence();
170 seconds_ += now() - t0;
171}
172
173} // namespace peclet::flow
174
175// Compiled once per grid in src/flow_solver_{staggered,colocated}.cpp (QUALITY_PLAN G.8).
176#ifndef PECLET_FLOW_INSTANTIATING
177namespace peclet::flow {
178extern template class AndersonAccelerator<Staggered>;
179extern template class AndersonAccelerator<Colocated>;
180} // namespace peclet::flow
181#endif
182
183#endif // PECLET_FLOW_ANDERSON_ACCELERATOR_HPP
const Core & core() const
The core itself (tests: γ, engagement, the descriptor).
void step(bool accelerate)
One map evaluation (§4.3): the lazy mix when accelerate and a mix is pending, then solver....
AndersonAccelerator(Solver< Grid > &solver, int window=5, double mixing=1.0)
Builds the march state (throws std::runtime_error on a refused configuration, §5.3) and allocates the...
peclet::core::solver::AndersonCore Core
double seconds() const
Cumulative wall time spent in the accelerator, solver.step() excluded (device-fenced at both ends of ...
std::size_t memoryBytes() const
Bytes of the history (= Core::memoryBytesFor(window, n_s, n_pad), design §6.3).
AndersonAccelerator(const AndersonAccelerator &)=delete
AndersonAccelerator & operator=(const AndersonAccelerator &)=delete
double residual() const
Relative velocity residual of the last evaluation (design §3.2); +inf before the first.
flow — host-facing Kokkos IBM Navier-Stokes solver (drop-in flow-style API).
static bool same(double a, double b)