21#ifndef PECLET_FLOW_ANDERSON_ACCELERATOR_HPP
22#define PECLET_FLOW_ANDERSON_ACCELERATOR_HPP
32#include "peclet/core/solver/anderson.hpp"
34#include "peclet/core/solver/anderson_mpi.hpp"
42 using Core = peclet::core::solver::AndersonCore;
55 void step(
bool accelerate);
58 const char*
statusName()
const {
return core_.statusName(); }
59 const std::string&
reason()
const {
return core_.reason(); }
61 double residual()
const {
return core_.residual(); }
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_; }
84 std::array<double, 9> sig_;
86 double seconds_ = 0.0;
91 typename Solver<Grid>::MarchState ms,
int window,
93 : s_(
solver), sig_(ms.signature), core_(makeCore(ms, window, mixing)) {}
97 typename Solver<Grid>::MarchState& ms,
int window,
double mixing) {
98 peclet::core::solver::AndersonState st;
99 st.fields = ms.fields;
101 st.extent = {ms.e.x, ms.e.y, ms.e.z};
103#ifdef PECLET_FLOW_MPI
105 st.comm = peclet::core::solver::andersonComm(ms.comm);
108 return Core(std::move(st), window, mixing);
109 }
catch (
const std::runtime_error& e) {
110 throw std::runtime_error(std::string(
"AndersonAccelerator: ") +
e.what() +
111 "; pass accelerate=False");
116double AndersonAccelerator<Grid>::now() {
117 return std::chrono::duration<double>(std::chrono::steady_clock::now().time_since_epoch()).count();
125 const auto ms = s_.marchState();
130 const auto&
held = core_.state().fields;
131 if (
held.size() != ms.fields.size()) {
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");
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);
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");
150 if (core_.status() == Core::Status::Active && ms.signature != sig_) {
156 seconds_ += now() - t0;
159 }
catch (
const std::exception& e) {
161 const bool absorbed = core_.stepFailed(e.what());
162 seconds_ += now() - t0;
168 core_.complete(s_.pressureSolveFailed());
170 seconds_ += now() - t0;
176#ifndef PECLET_FLOW_INSTANTIATING
178extern template class AndersonAccelerator<Staggered>;
179extern template class AndersonAccelerator<Colocated>;
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
const std::string & reason() const
const char * statusName() const
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)