SystemFieldSolver< Impl > Class Template Reference

adc_cpp: pops::field_solver::SystemFieldSolver< Impl > Class Template Reference
adc_cpp 0.3.0
Model-free C++23 core for coupled hyperbolic-elliptic systems on adaptive (AMR) meshes, with MPI and GPU (Kokkos) backends
pops::field_solver::SystemFieldSolver< Impl > Class Template Reference

SystemFieldSolver<Impl>: see contract above. More...

#include <system_field_solver.hpp>

+ Collaboration diagram for pops::field_solver::SystemFieldSolver< Impl >:

Classes

struct  NamedField
 

Public Member Functions

 SystemFieldSolver (Impl *owner)
 
bool provides_aux (const std::string &name) const
 True if the named aux field is provided at install time, for Spec-2 criterion 24 install-time requirement validation (ADC-446).
 
void register_named_field (const std::string &field, int phi_comp, int gx_comp, int gy_comp)
 Register a named elliptic field (ADC-428): records the aux output components (where the field's solved phi and centered gradient land).
 
void apply_named_aux_bc ()
 Re-applies the per-field aux HALO policies (ADC-369) onto the shared channel, AFTER the shared fill_ghosts/fill_boundary.
 
void apply_bz ()
 Populates the B_z component (index kAuxBaseComps) of the shared channel from bz_field_, over the valid cells.
 
void apply_te ()
 Populates the T_e component (electron temperature) = p/rho of the fluid block source te_src_.
 
void apply_named_aux_one (int comp, const std::vector< Real > &field)
 Populates ONE NAMED aux component (canonical index comp >= kAuxNamedBase) of the shared channel from field (row-major), over the valid cells.
 
void apply_named_aux ()
 Re-applies ALL the stored named aux fields (cf.
 
BCRec poisson_bc ()
 Resolves the BC mode into a BCRec: "auto" -> dirichlet if wall/non-periodic, otherwise periodic; "periodic"|"dirichlet"|"neumann" (Foextrap).
 
std::function< bool(Real, Real)> wall_active ()
 "Conductor interior" predicate from p_wall / p_wall_radius / cfg.L (cf.
 
void ensure_elliptic ()
 Builds the cartesian elliptic solver (ell_) LAZILY according to p_solver: GeometricMG (carries eps(x)/aniso/kappa if provided) or PoissonFFTSolver (constant coefficient, single-rank, no wall; kind 'fft' = discrete stencil, 'fft_spectral' = continuous spectral symbol).
 
void apply_epsilon_field ()
 Installs the eps(x) field (n*n row-major) on the GeometricMG: the operator becomes div(eps grad phi) = f, eps CARRIED BY THE OPERATOR (harmonic face coefficient, order 2), without 1/eps scaling of the right-hand side.
 
void apply_epsilon_anisotropic_field ()
 Installs the eps_x(x), eps_y(x) fields (n*n row-major each) on the GeometricMG: the operator becomes div(diag(eps_x, eps_y) grad phi) = f.
 
void apply_reaction_field ()
 Installs the reaction term kappa(x) (n*n row-major) on the GeometricMG: the operator becomes div(eps grad phi) - kappa phi = f (screened Poisson / Helmholtz; kappa = 1/lambda_D^2 for Debye).
 
MultiFabell_rhs ()
 Right-hand side f of the active cartesian elliptic solver (GeometricMG or FFT), via std::visit.
 
MultiFabell_phi ()
 Potential phi read (and rewritten) by the condensed source stage.
 
void ell_solve ()
 Solves the active cartesian Poisson (GeometricMG V-cycle or direct FFT).
 
int last_mg_cycles () const
 
int last_krylov_iters () const
 
int last_num_levels () const
 
double last_bottom_seconds () const
 
void ensure_elliptic_polar ()
 Builds the direct POLAR Poisson (PolarPoissonSolver, single-rank, single box covering the ring) LAZILY.
 
void assemble_poisson_rhs (MultiFab &rhs, int target_block=-1, const MultiFab *U_stage=nullptr)
 Assembles the system Poisson RIGHT-HAND SIDE into rhs: f = Sum_s elliptic_rhs_s(U_s), the elliptic brick of EACH block, summed in place (rhs is zeroed first).
 
void assemble_poisson_rhs_from_blocks (MultiFab &rhs, const std::vector< const MultiFab * > &U_stages)
 Assembles the system Poisson RIGHT-HAND SIDE into rhs for a SIMULTANEOUS coupled multi-block solve (Spec 3 criterion 24, ADC-457): f = Sum_s elliptic_rhs_s(U_s) where EVERY block reads its OWN stage state at once, instead of overriding a single target block (assemble_poisson_rhs).
 
void solve_fields_polar (int target_block=-1, const MultiFab *U_stage=nullptr)
 POLAR solve_fields: assembles f = Sum_s elliptic_rhs_s(U_s) (host loop per cell), solves the polar Poisson, then DERIVES the aux in the local basis (e_r, e_theta): aux[0] = phi; aux[1] = grad_r = d phi/dr; aux[2] = grad_theta = (1/r) d phi/d theta.
 
void solve_fields (int target_block=-1, const MultiFab *U_stage=nullptr)
 Solves the system Poisson then DERIVES the aux = (phi, grad phi[, B_z, T_e]).
 
void solve_fields_from_state (int block_idx, const MultiFab &U_stage)
 Per-stage field solve (ADC-409): SAME solve + derive-aux as solve_fields(), but the target block block_idx assembles its Poisson RHS from U_stage instead of its live s.U (the other blocks keep s.U).
 
void solve_fields_polar_from_blocks (const std::vector< const MultiFab * > &U_stages)
 POLAR coupled multi-block solve (Spec 3 criterion 24, ADC-457): same solve + aux derivation as solve_fields_polar(), but the Poisson RHS is assembled from the SIMULTANEOUS stage states of all blocks (assemble_poisson_rhs_from_blocks) instead of a single-target override.
 
void solve_fields_from_blocks (const std::vector< const MultiFab * > &U_stages)
 Coupled multi-block field solve (Spec 3 criterion 24, ADC-457): SAME elliptic solve + aux derivation as solve_fields(), but the system Poisson RHS is assembled from the SIMULTANEOUS stage states of MULTIPLE blocks (assemble_poisson_rhs_from_blocks) – every coupled block reads its OWN stage state at once, not a single-target override.
 
void ensure_named_elliptic (NamedField &nf)
 Builds the DEDICATED cartesian elliptic solver of named field nf, the SAME poisson operator as the default ell_ (ensure_elliptic): GeometricMG (default) or PoissonFFTSolver/RemappedFFTSolver, with the System's Poisson BC and wall.
 
void assemble_named_poisson_rhs (const std::string &field, MultiFab &rhs, int target_block, const MultiFab *U_stage)
 Assembles the RIGHT-HAND SIDE of named field field into rhs: f = Sum_s named_poisson_rhs_s[field](U_s), the per-field elliptic brick of EACH block that declares it (ADC-428).
 
void solve_named_field_from_state (const std::string &field, int block_idx, const MultiFab &U_stage)
 Solves named field field's SECOND elliptic problem from block block_idx's stage state U_stage and writes phi (+ centered grad) into the field's OWN aux components (ADC-428): assemble f = Sum_s named_poisson_rhs_s[field] -> ell.solve() (the dedicated native solver) -> aux[phi_comp] = phi, aux[gx_comp]/aux[gy_comp] = centered grad.
 

Public Attributes

std::string p_rhs = "charge_density"
 
std::string p_solver = "geometric_mg"
 
std::string p_bc = "auto"
 
std::string p_wall = "none"
 
double p_wall_radius = 0.0
 
Real p_eps_ = 1
 
Real p_abs_tol_ = 0
 
bool has_eps_field_ = false
 
std::vector< double > p_eps_field_
 
bool has_eps_xy_field_
 
std::vector< double > p_eps_x_field_
 
std::vector< double > p_eps_y_field_
 
bool has_kappa_field_ = false
 
std::vector< double > p_kappa_field_
 
bool gauss_evolve_ = false
 
bool gauss_solved_once_ = false
 
std::optional< std::variant< GeometricMG, PoissonFFTSolver, RemappedFFTSolver > > ell_
 
std::optional< PolarPoissonSolverpell_
 
std::optional< MultiFabphi_src_polar_
 
std::vector< Realbz_field_
 
int te_src_ = -1
 
std::map< int, std::vector< Real > > named_aux_
 
std::map< int, AuxHaloPolicynamed_aux_bc_
 
std::map< std::string, NamedFieldnamed_fields_
 

Static Public Attributes

static constexpr int kTeComp = kAuxBaseComps + 1
 Canonical component of T_e (after phi/grad/B_z); cf. pops::Aux and AUX_CANONICAL on the DSL side.
 

Detailed Description

template<class Impl>
class pops::field_solver::SystemFieldSolver< Impl >

SystemFieldSolver<Impl>: see contract above.

All methods are MEMBERS (not free functions) because they share the elliptic state owned by this class; accesses to the SHARED state of Impl go through owner_-> verbatim. Templated on Impl to stay free of any dependency on the (private) definition of System::Impl.

Constructor & Destructor Documentation

◆ SystemFieldSolver()

template<class Impl >
pops::field_solver::SystemFieldSolver< Impl >::SystemFieldSolver ( Impl *  owner)
inlineexplicit
Parameters
ownerback-pointer to System::Impl (lifetime subordinate to that of Impl).

Member Function Documentation

◆ apply_bz()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::apply_bz ( )
inline

Populates the B_z component (index kAuxBaseComps) of the shared channel from bz_field_, over the valid cells.

No-op if B_z not provided or if no block reads it (base width). The halos of B_z are filled by solve_fields (like grad); field_postprocess only writes comp 0..2.

◆ apply_epsilon_anisotropic_field()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::apply_epsilon_anisotropic_field ( )
inline

Installs the eps_x(x), eps_y(x) fields (n*n row-major each) on the GeometricMG: the operator becomes div(diag(eps_x, eps_y) grad phi) = f.

The faces normal to x read eps_x, those normal to y read eps_y (harmonic face coefficients, order 2), CARRIED BY THE OPERATOR without 1/eps scaling of the right-hand side. GeometricMG only (variable tensor coefficient).

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ apply_epsilon_field()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::apply_epsilon_field ( )
inline

Installs the eps(x) field (n*n row-major) on the GeometricMG: the operator becomes div(eps grad phi) = f, eps CARRIED BY THE OPERATOR (harmonic face coefficient, order 2), without 1/eps scaling of the right-hand side.

Only GeometricMG supports this variable coefficient.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ apply_named_aux()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::apply_named_aux ( )
inline

Re-applies ALL the stored named aux fields (cf.

named_aux_). Called by ensure_aux_width after a reallocation of the aux channel (which starts again from a zeroed MultiFab), like apply_bz / apply_te.

+ Here is the call graph for this function:

◆ apply_named_aux_bc()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::apply_named_aux_bc ( )
inline

Re-applies the per-field aux HALO policies (ADC-369) onto the shared channel, AFTER the shared fill_ghosts/fill_boundary.

For each declared component, overrides ONLY that component's physical-face ghosts (aux_halo_override keeps periodic faces periodic). No-op when empty.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ apply_named_aux_one()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::apply_named_aux_one ( int  comp,
const std::vector< Real > &  field 
)
inline

Populates ONE NAMED aux component (canonical index comp >= kAuxNamedBase) of the shared channel from field (row-major), over the valid cells.

No-op if the channel is too narrow (no block reads this component) or if the field is empty. SAME pattern as apply_bz: STATIC field provided by the user, never rewritten by solve_fields; its halos are filled by solve_fields (fill_ghosts/fill_boundary over the whole channel). LOCAL population on the rank (iteration over the local fabs, no-op on a rank without a box at np>1).

+ Here is the caller graph for this function:

◆ apply_reaction_field()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::apply_reaction_field ( )
inline

Installs the reaction term kappa(x) (n*n row-major) on the GeometricMG: the operator becomes div(eps grad phi) - kappa phi = f (screened Poisson / Helmholtz; kappa = 1/lambda_D^2 for Debye).

kappa is DIAGONAL (read at cell), restricted by averaging to the coarse levels. GeometricMG only.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ apply_te()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::apply_te ( )
inline

Populates the T_e component (electron temperature) = p/rho of the fluid block source te_src_.

RECOMPUTED on each solve_fields (T_e varies with the fluid, unlike the static B_z). No-op if no source or if no block reads T_e (insufficient width). The source block is compressible (4 var); p = (gamma-1)(E - 0.5 rho|v|^2), T = p/rho.

+ Here is the caller graph for this function:

◆ assemble_named_poisson_rhs()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::assemble_named_poisson_rhs ( const std::string &  field,
MultiFab rhs,
int  target_block,
const MultiFab U_stage 
)
inline

Assembles the RIGHT-HAND SIDE of named field field into rhs: f = Sum_s named_poisson_rhs_s[field](U_s), the per-field elliptic brick of EACH block that declares it (ADC-428).

When target_block >= 0 and U_stage != nullptr, the target block reads U_stage instead of its live s.U (per-stage field solve, like assemble_poisson_rhs).

Exceptions
ifno block declares this field (a named field with no contributing block would solve a zero RHS silently).
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ assemble_poisson_rhs()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::assemble_poisson_rhs ( MultiFab rhs,
int  target_block = -1,
const MultiFab U_stage = nullptr 
)
inline

Assembles the system Poisson RIGHT-HAND SIDE into rhs: f = Sum_s elliptic_rhs_s(U_s), the elliptic brick of EACH block, summed in place (rhs is zeroed first).

When target_block >= 0 and U_stage != nullptr, the target block reads U_stage INSTEAD of its live s.U (the rest of the blocks keep s.U); this is what solve_fields_from_state needs to re-solve a field-coupled multi-stage scheme from a per-stage state. With the default (target_block = -1) it is BIT-IDENTICAL to the historical inline loop (every block from s.U). STRIDE: a held (hold-then-catch-up) block stays FROZEN at its last advance, so its charge enters the sum with a STALE state until its next catch-up (loose Poisson coupling, assumed).

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ assemble_poisson_rhs_from_blocks()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::assemble_poisson_rhs_from_blocks ( MultiFab rhs,
const std::vector< const MultiFab * > &  U_stages 
)
inline

Assembles the system Poisson RIGHT-HAND SIDE into rhs for a SIMULTANEOUS coupled multi-block solve (Spec 3 criterion 24, ADC-457): f = Sum_s elliptic_rhs_s(U_s) where EVERY block reads its OWN stage state at once, instead of overriding a single target block (assemble_poisson_rhs).

U_stages is indexed BY BLOCK INDEX (size == the number of blocks): U_stages[b] != nullptr -> block b contributes its stage state, U_stages[b] == nullptr -> block b contributes its live s.U. With every entry pointing at the corresponding live s.U it is the same f as assemble_poisson_rhs(rhs) (the default head solve), so a coupled solve from the live states is bit-identical to solve_fields. This is the multi-target stage override solve_fields_from_blocks needs: a field-coupled multi- species step re-solves phi from the SIMULTANEOUS stage states of all coupled blocks (no operator observes a partially committed group, the IR commit_many guarantee).

Exceptions
std::invalid_argumentif U_stages is not sized to the block count (a stale binding cannot silently mis-route).
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ell_phi()

template<class Impl >
MultiFab & pops::field_solver::SystemFieldSolver< Impl >::ell_phi ( )
inline

Potential phi read (and rewritten) by the condensed source stage.

CARTESIAN: the phi of the active elliptic solver (GeometricMG/FFT, WITH ghosts), BIT-IDENTICAL. POLAR: a dedicated 1-ghost buffer (phi_src_polar_), fed with phi^n (= aux[0], set by solve_fields_polar) at call time – the direct PolarPoissonSolver has no ghosts, so we cannot expose pell_->phi() directly to a stepper that does fill_ghosts/apply_polar_tensor. The stepper writes phi^{n+1} into it (warm start of the next step; aux[0] will be rewritten anyway by the next solve_fields).

+ Here is the caller graph for this function:

◆ ell_rhs()

template<class Impl >
MultiFab & pops::field_solver::SystemFieldSolver< Impl >::ell_rhs ( )
inline

Right-hand side f of the active cartesian elliptic solver (GeometricMG or FFT), via std::visit.

+ Here is the caller graph for this function:

◆ ell_solve()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::ell_solve ( )
inline

Solves the active cartesian Poisson (GeometricMG V-cycle or direct FFT).

Sets the trace markers; the device_fence after ell_solve is carried by the CALLER (solve_fields), not here.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ensure_elliptic()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::ensure_elliptic ( )
inline

Builds the cartesian elliptic solver (ell_) LAZILY according to p_solver: GeometricMG (carries eps(x)/aniso/kappa if provided) or PoissonFFTSolver (constant coefficient, single-rank, no wall; kind 'fft' = discrete stencil, 'fft_spectral' = continuous spectral symbol).

No-op if ell_ already exists.

Exceptions
std::runtime_erroron unknown rhs/solver or unsupported combination (fft + MPI/wall/variable eps/kappa; kappa + constant eps != 1).
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ensure_elliptic_polar()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::ensure_elliptic_polar ( )
inline

Builds the direct POLAR Poisson (PolarPoissonSolver, single-rank, single box covering the ring) LAZILY.

The radial BC comes from poisson_bc() (Foextrap -> homogeneous Neumann, wall; the circular cartesian 'wall' makes no sense on a global ring and is not applied). theta is PERIODIC (handled by the FFT-in-theta, no azimuthal BC). ADDITIVE: never touches ell_.

Exceptions
std::runtime_erroron unknown rhs/solver or variable/aniso/reaction permittivity (unsupported by the direct polar Poisson).
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ensure_named_elliptic()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::ensure_named_elliptic ( NamedField nf)
inline

Builds the DEDICATED cartesian elliptic solver of named field nf, the SAME poisson operator as the default ell_ (ensure_elliptic): GeometricMG (default) or PoissonFFTSolver/RemappedFFTSolver, with the System's Poisson BC and wall.

REUSES the native solver – no operator is reimplemented. The variable / anisotropic permittivity and reaction coefficients of the DEFAULT Poisson are NOT carried onto a named field (a named field is a plain Laplacian; its own coefficients are a future extension). Built lazily; no-op if already built.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ last_bottom_seconds()

template<class Impl >
double pops::field_solver::SystemFieldSolver< Impl >::last_bottom_seconds ( ) const
inline

◆ last_krylov_iters()

template<class Impl >
int pops::field_solver::SystemFieldSolver< Impl >::last_krylov_iters ( ) const
inline

◆ last_mg_cycles()

template<class Impl >
int pops::field_solver::SystemFieldSolver< Impl >::last_mg_cycles ( ) const
inline

◆ last_num_levels()

template<class Impl >
int pops::field_solver::SystemFieldSolver< Impl >::last_num_levels ( ) const
inline

◆ poisson_bc()

template<class Impl >
BCRec pops::field_solver::SystemFieldSolver< Impl >::poisson_bc ( )
inline

Resolves the BC mode into a BCRec: "auto" -> dirichlet if wall/non-periodic, otherwise periodic; "periodic"|"dirichlet"|"neumann" (Foextrap).

Exceptions
std::runtime_erroron an unknown mode.
+ Here is the caller graph for this function:

◆ provides_aux()

template<class Impl >
bool pops::field_solver::SystemFieldSolver< Impl >::provides_aux ( const std::string &  name) const
inline

True if the named aux field is provided at install time, for Spec-2 criterion 24 install-time requirement validation (ADC-446).

Only the user-supplied APPLICATION fields can be a hard requirement: B_z (System::set_magnetic_field) and T_e (System::set_electron_temperature). The derived fields phi/grad_x/grad_y are always available (the elliptic solver builds lazily from the default Poisson config), and a generic named aux is keyed only by component C++-side (its name is not retained), so neither can be a hard failure here – they return true (cannot block).

◆ register_named_field()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::register_named_field ( const std::string &  field,
int  phi_comp,
int  gx_comp,
int  gy_comp 
)
inline

Register a named elliptic field (ADC-428): records the aux output components (where the field's solved phi and centered gradient land).

gx_comp / gy_comp < 0 => only phi is written (the model declared fewer than 3 aux slots for the field). Idempotent (re-register overwrites the component map, drops the lazily-built solver so the next solve rebuilds it). The DEDICATED solver is built on first solve, never here.

◆ solve_fields()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::solve_fields ( int  target_block = -1,
const MultiFab U_stage = nullptr 
)
inline

Solves the system Poisson then DERIVES the aux = (phi, grad phi[, B_z, T_e]).

Routes to solve_fields_polar() in polar geometry. device INVARIANT: the device_fence() between ell_solve() and the derivation of grad phi MUST stay atomic (without it the GPU V-cycle is not finished when phi is read); the derivation / population loops iterate over the LOCAL fabs (MPI-safe).

target_block / U_stage: when set (target_block >= 0, U_stage != nullptr), the target block's Poisson RHS is assembled from U_stage INSTEAD of its live s.U – the seam solve_fields_from_state uses so a field-coupled multi-stage scheme re-solves phi from each STAGE state (the compiled Program runs stages sequentially: stage k's solve overwrites the shared aux before stage k's RHS reads it). The default (-1 / nullptr) keeps every block at s.U: the historical solve_fields(), BIT-IDENTICAL. Inert under the gauss_evolve_ skip (no RHS assembled).

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ solve_fields_from_blocks()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::solve_fields_from_blocks ( const std::vector< const MultiFab * > &  U_stages)
inline

Coupled multi-block field solve (Spec 3 criterion 24, ADC-457): SAME elliptic solve + aux derivation as solve_fields(), but the system Poisson RHS is assembled from the SIMULTANEOUS stage states of MULTIPLE blocks (assemble_poisson_rhs_from_blocks) – every coupled block reads its OWN stage state at once, not a single-target override.

U_stages is indexed by block index (nullptr = the block's live state). Routes to solve_fields_polar_from_blocks() in polar geometry. Mirrors solve_fields() step for step (the device_fence between ell_solve and the grad derivation, the LOCAL-fab loops, the order of fill_ghosts/fill_boundary); only the RHS assembly differs, so a coupled solve from the live states is bit-identical to solve_fields(). The codegen lowers P.solve_fields_from_blocks([...]) to this; the seam a multi-species field-coupled step uses to re-solve phi from all coupled blocks' stage states simultaneously.

Exceptions
(viaassemble_poisson_rhs_from_blocks) if U_stages is not sized to the block count.
+ Here is the call graph for this function:

◆ solve_fields_from_state()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::solve_fields_from_state ( int  block_idx,
const MultiFab U_stage 
)
inline

Per-stage field solve (ADC-409): SAME solve + derive-aux as solve_fields(), but the target block block_idx assembles its Poisson RHS from U_stage instead of its live s.U (the other blocks keep s.U).

This re-fills the SHARED aux (phi, grad phi) with phi(U_stage); a compiled Program's stage-k RHS, called right after this, then reads phi solved from stage k's own state – removing the "solve from current state only" limitation for sequential multi-stage schemes. The next stage's solve overwrites the aux, so no distinct per-stage buffer is needed. With block_idx == 0 and U_stage == U^n (the first stage) this is identical to solve_fields().

Exceptions
std::out_of_rangeif block_idx is not a valid block index.
+ Here is the call graph for this function:

◆ solve_fields_polar()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::solve_fields_polar ( int  target_block = -1,
const MultiFab U_stage = nullptr 
)
inline

POLAR solve_fields: assembles f = Sum_s elliptic_rhs_s(U_s) (host loop per cell), solves the polar Poisson, then DERIVES the aux in the local basis (e_r, e_theta): aux[0] = phi; aux[1] = grad_r = d phi/dr; aux[2] = grad_theta = (1/r) d phi/d theta.

This is the layout expected by ExBVelocityPolar (v_r = -grad_theta/B, v_theta = grad_r/B). target_block / U_stage: per-stage state override for the target block (default -1: every block from s.U, bit-identical to the historical path).

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ solve_fields_polar_from_blocks()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::solve_fields_polar_from_blocks ( const std::vector< const MultiFab * > &  U_stages)
inline

POLAR coupled multi-block solve (Spec 3 criterion 24, ADC-457): same solve + aux derivation as solve_fields_polar(), but the Poisson RHS is assembled from the SIMULTANEOUS stage states of all blocks (assemble_poisson_rhs_from_blocks) instead of a single-target override.

U_stages is indexed by block index (nullptr = the block's live state). Mirrors solve_fields_polar() step for step (eps scaling, pell_->solve, device_fence, derive_aux_polar, apply_te, fill_ghosts, named-aux halo) – only the RHS assembly differs, so a coupled solve from the live states is bit-identical.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ solve_named_field_from_state()

template<class Impl >
void pops::field_solver::SystemFieldSolver< Impl >::solve_named_field_from_state ( const std::string &  field,
int  block_idx,
const MultiFab U_stage 
)
inline

Solves named field field's SECOND elliptic problem from block block_idx's stage state U_stage and writes phi (+ centered grad) into the field's OWN aux components (ADC-428): assemble f = Sum_s named_poisson_rhs_s[field] -> ell.solve() (the dedicated native solver) -> aux[phi_comp] = phi, aux[gx_comp]/aux[gy_comp] = centered grad.

The SHARED phi/grad (components 0..2) and the default Poisson (ell_) are NOT touched. The named aux components are then ghost- filled (the shared aux fill + the per-field halo override). CARTESIAN only (the polar named path is a future extension);

Exceptions
onthe polar geometry or an unknown field.
+ Here is the call graph for this function:

◆ wall_active()

template<class Impl >
std::function< bool(Real, Real)> pops::field_solver::SystemFieldSolver< Impl >::wall_active ( )
inline

"Conductor interior" predicate from p_wall / p_wall_radius / cfg.L (cf.

wall_predicate); empty if no wall.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ bz_field_

template<class Impl >
std::vector<Real> pops::field_solver::SystemFieldSolver< Impl >::bz_field_

◆ ell_

template<class Impl >
std::optional<std::variant<GeometricMG, PoissonFFTSolver, RemappedFFTSolver> > pops::field_solver::SystemFieldSolver< Impl >::ell_

◆ gauss_evolve_

template<class Impl >
bool pops::field_solver::SystemFieldSolver< Impl >::gauss_evolve_ = false

◆ gauss_solved_once_

template<class Impl >
bool pops::field_solver::SystemFieldSolver< Impl >::gauss_solved_once_ = false

◆ has_eps_field_

template<class Impl >
bool pops::field_solver::SystemFieldSolver< Impl >::has_eps_field_ = false

◆ has_eps_xy_field_

template<class Impl >
bool pops::field_solver::SystemFieldSolver< Impl >::has_eps_xy_field_
Initial value:
=
false

◆ has_kappa_field_

template<class Impl >
bool pops::field_solver::SystemFieldSolver< Impl >::has_kappa_field_ = false

◆ kTeComp

template<class Impl >
constexpr int pops::field_solver::SystemFieldSolver< Impl >::kTeComp = kAuxBaseComps + 1
staticconstexpr

Canonical component of T_e (after phi/grad/B_z); cf. pops::Aux and AUX_CANONICAL on the DSL side.

◆ named_aux_

template<class Impl >
std::map<int, std::vector<Real> > pops::field_solver::SystemFieldSolver< Impl >::named_aux_

◆ named_aux_bc_

template<class Impl >
std::map<int, AuxHaloPolicy> pops::field_solver::SystemFieldSolver< Impl >::named_aux_bc_

◆ named_fields_

template<class Impl >
std::map<std::string, NamedField> pops::field_solver::SystemFieldSolver< Impl >::named_fields_

◆ p_abs_tol_

template<class Impl >
Real pops::field_solver::SystemFieldSolver< Impl >::p_abs_tol_ = 0

◆ p_bc

template<class Impl >
std::string pops::field_solver::SystemFieldSolver< Impl >::p_bc = "auto"

◆ p_eps_

template<class Impl >
Real pops::field_solver::SystemFieldSolver< Impl >::p_eps_ = 1

◆ p_eps_field_

template<class Impl >
std::vector<double> pops::field_solver::SystemFieldSolver< Impl >::p_eps_field_

◆ p_eps_x_field_

template<class Impl >
std::vector<double> pops::field_solver::SystemFieldSolver< Impl >::p_eps_x_field_

◆ p_eps_y_field_

template<class Impl >
std::vector<double> pops::field_solver::SystemFieldSolver< Impl >::p_eps_y_field_

◆ p_kappa_field_

template<class Impl >
std::vector<double> pops::field_solver::SystemFieldSolver< Impl >::p_kappa_field_

◆ p_rhs

template<class Impl >
std::string pops::field_solver::SystemFieldSolver< Impl >::p_rhs = "charge_density"

◆ p_solver

template<class Impl >
std::string pops::field_solver::SystemFieldSolver< Impl >::p_solver = "geometric_mg"

◆ p_wall

template<class Impl >
std::string pops::field_solver::SystemFieldSolver< Impl >::p_wall = "none"

◆ p_wall_radius

template<class Impl >
double pops::field_solver::SystemFieldSolver< Impl >::p_wall_radius = 0.0

◆ pell_

template<class Impl >
std::optional<PolarPoissonSolver> pops::field_solver::SystemFieldSolver< Impl >::pell_

◆ phi_src_polar_

template<class Impl >
std::optional<MultiFab> pops::field_solver::SystemFieldSolver< Impl >::phi_src_polar_

◆ te_src_

template<class Impl >
int pops::field_solver::SystemFieldSolver< Impl >::te_src_ = -1

The documentation for this class was generated from the following file: