25#include "libmesh/numeric_vector.h"
26#include "libmesh/system.h"
32template <
typename DestinationContainer>
35 DestinationContainer & destination)
38 mooseAssert(source.size() == destination.size(),
39 "Gradient state component counts must match when copying states.");
43 mooseAssert(source[component],
"Source gradient component vector must be initialized.");
44 mooseAssert(destination[component],
45 "Destination gradient component vector must be initialized.");
47 source[component]->size() == destination[component]->size() &&
48 source[component]->local_size() == destination[component]->local_size() &&
49 source[component]->first_local_index() == destination[component]->first_local_index() &&
50 source[component]->last_local_index() == destination[component]->last_local_index(),
51 "Source and destination gradient component vectors must have matching parallel "
53 *destination[component] = *source[component];
63 if (!fe_problem.hasFVGradientMethod(method_name))
65 if (method_name ==
"green-gauss")
68 fe_problem.addFVGradientMethod(
"FVGreenGaussGradient", method_name, params);
70 else if (method_name ==
"green-gauss-venkatakrishnan")
72 auto params = fe_problem.getMooseApp().getFactory().getValidParams(
"FVGreenGaussGradient");
74 fe_problem.addFVGradientMethod(
"FVGreenGaussGradient", method_name, params);
78 if (!fe_problem.hasFVGradientMethod(method_name))
79 mooseError(
"Unable to find FVGradientMethod with name '", method_name,
"'");
81 return fe_problem.getFVGradientMethod(method_name);
87 const unsigned int oldest_state)
89 auto *
const variable =
92 mooseError(
"Linear FV gradients were requested for variable number ",
96 "', but no field variable with that number exists on the system.");
101 auto & container = method_container->second;
102 container.variable_numbers.insert(variable_number);
107 if (current_solution && current_solution->initialized())
109 if (container.current_values.empty())
111 if (container.next_values.empty())
129 mooseError(
"Cannot exclude a linear FV gradient field from a different system than '",
134 gradient_methods.erase(
135 std::remove(gradient_methods.begin(), gradient_methods.end(), &excluded_reader.
method()),
136 gradient_methods.end());
142 const std::vector<const FVGradientMethod *> & gradient_methods)
148 mooseAssert(perf_graph_interface,
149 "LinearFVGradientManager requires its owning system to implement "
150 "PerfGraphInterface.");
151 const auto perf_id = perf_graph_interface->registerTimedSection(
"LinearVariableFV_Gradients", 3);
152 mooseAssert(!
Threads::in_threads,
"PerfGraph timing cannot be used within threaded sections");
153 PerfGuard time_guard(perf_graph_interface->perfGraph(), perf_id);
159 for (
const auto *
const method : gradient_methods)
162 for (
const auto *
const method : gradient_methods)
171 mooseError(
"Requested update for a linear FV gradient field from a different system than '",
179 mooseAssert(perf_graph_interface,
180 "LinearFVGradientManager requires its owning system to implement "
181 "PerfGraphInterface.");
183 perf_graph_interface->registerTimedSection(
"LinearVariableFV_Gradients", 3);
184 mooseAssert(!
Threads::in_threads,
"PerfGraph timing cannot be used within threaded sections");
185 PerfGuard time_guard(perf_graph_interface->perfGraph(), perf_id);
192 mooseError(
"Requested update for an unregistered linear FV gradient field on system '",
208 mooseAssert(current_solution && current_solution->initialized(),
209 "Current solution must exist before building FV gradient storage.");
211 for (
auto & component : container)
212 component = current_solution->zero_clone();
217 const unsigned int oldest_state)
219 const auto required_states =
static_cast<std::size_t
>(oldest_state) + 1;
224 " was requested on system '",
226 "' after solution states were initialized. Old gradient states must be requested "
229 if (required_states > old_size)
237 for (
const auto state : make_range(std::size_t(1), container.state_values.size()))
238 if (container.state_values[state].empty())
241 for (
const auto component : index_range(state_values))
244 container.state_values[state] = std::move(state_values);
252 "Gradient state storage must contain a current state.");
254 current_view.clear();
257 current_view.push_back(component.get());
262 const unsigned int state,
263 const unsigned int component)
265 return "linear_fv_gradient_" + method.
name() +
"_state_" + std::to_string(state) +
"_component_" +
266 std::to_string(component);
281 if (!app.isRestarting() && !app.isRecovering())
285 for (
const auto state : make_range(std::size_t(1), container.
state_values.size()))
286 for (
const auto component : index_range(container.
state_values[state]))
292 if (!restartable_equation_systems.isVariableRestored(
293 _sys.
name(), vector_name, variable.name()))
298 "' using gradient method '",
300 "' was requested on system '",
304 "' was not available in the restart data.");
323 mooseAssert(!container.state_values.empty(),
324 "Gradient state storage must contain a current state.");
325 mooseAssert(!container.state_values[0].empty(),
326 "Gradient storage must be initialized before gradient computation.");
327 mooseAssert(!container.next_values.empty(),
328 "Replacement gradient storage must be initialized before gradient computation.");
329 mooseAssert(container.next_values.size() == container.current_values.size(),
330 "Next and current gradient containers must have the same size.");
341 "Gradient state storage must contain a current state.");
343 "Next and current gradient containers must have the same size.");
349 for (
const auto state : make_range(std::size_t(1), container.
state_values.size()))
362 if (container.current_values.empty())
364 if (container.next_values.empty())
376 method_container_pair.second.current_values.clear();
377 method_container_pair.second.next_values.clear();
378 method_container_pair.second.has_computed_gradient =
false;
388 if (container.state_values.size() > 1 && !container.has_computed_gradient)
392 if (container.state_values.size() > 1 && !container.has_computed_gradient)
401 "Linear FV gradient storage does not support nonlinear iteration states.");
410 const auto number_of_states = container.state_values.size();
411 if (number_of_states <= 1)
414 mooseAssert(container.has_computed_gradient,
415 "Current gradient state must be initialized before advancing time states.");
418 const std::size_t stop = skip_current_to_old ? 1 : 0;
419 for (std::size_t state = number_of_states - 1; state > stop; --state)
420 copyGradient(container.state_values[state - 1], container.state_values[state]);
430 if (container.state_values.size() <= 1)
433 mooseAssert(container.has_computed_gradient,
434 "Current gradient state must be initialized before restoration.");
435 copyGradient(container.state_values[1], container.state_values[0]);
436 copyGradient(container.state_values[0], container.next_values);
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
const RestartableEquationSystems & getRestartableEquationSystems() const
Get the RestartableEquationSystems object.
Base class for linear finite-volume cell-gradient methods.
void computeGradient(SystemBase &system, GradientContainer &gradient, const std::unordered_set< unsigned int > &variable_numbers) const
Compute the final gradient values for the requested variables.
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
void computeGradientsForMethods(const std::vector< const FVGradientMethod * > &gradient_methods)
Compute and finalize the supplied registered gradient methods.
void resizeGradientStateStorage(LinearFVGradientContainer &container, unsigned int oldest_state)
Ensure that a method container stores every requested time state.
void setCurrentGradientState(LinearFVGradientContainer &container) const
Set solution state zero to the current gradient.
LinearFVGradientContainer & computeLinearFVGradientContainer(const FVGradientMethod &method)
Compute replacement field values for a registered gradient method.
LinearFVGradientReader::GradientContainer GradientContainer
Non-owning view with one vector per spatial component of a cell-centered gradient field.
void initializeContainer(OwnedGradientContainer &container) const
Allocate one zeroed vector per spatial component for gradient storage.
void computeGradientsExcept(const LinearFVGradientReader &excluded_reader)
Compute and finalize every registered linear FV gradient field except one method.
SystemBase & _sys
Reference to the system object.
void finalizeLinearFVGradientContainer(LinearFVGradientContainer &container)
Replace the current gradient storage with the freshly computed new gradients.
std::vector< const FVGradientMethod * > _linear_fv_gradient_methods
Registered gradient methods in registration order.
std::unordered_map< const FVGradientMethod *, LinearFVGradientContainer > _linear_fv_gradient_container_by_method
Gradient containers keyed by the method object that produces them.
void updateFVGradient(const LinearFVGradientReader &reader)
Update a registered gradient reader explicitly.
void computeGradients()
Compute and finalize all registered linear FV gradient fields.
static std::string gradientStateVectorName(const FVGradientMethod &method, unsigned int state, unsigned int component)
Return the stable system-vector name for one old gradient component.
void rebuildLinearFVGradientStorage()
Rebuild cached gradient values and reusable scratch storage after mesh/DOF changes.
void copyPreviousGradientStates(Moose::SolutionIterationType iteration_type, bool skip_current_to_old)
Copy published gradient values into requested older states.
void initializeGradientStatesForTimeAdvance()
Compute and publish uninitialized gradients before their first time-state advancement.
const FVGradientMethod & resolveFVGradientMethod(const GradientMethodName &method_name)
Resolve a named gradient method, constructing a built-in method when needed.
LinearFVGradientReader registerFVGradient(unsigned int variable_number, const FVGradientMethod &method, unsigned int oldest_state=0)
Register a variable for gradient values produced by a method object.
void checkRestartedGradientHistory(const FVGradientMethod &method, LinearFVGradientContainer &container)
Validate and mark gradient history loaded during restart or recovery.
std::vector< std::unique_ptr< libMesh::NumericVector< libMesh::Number > > > OwnedGradientContainer
Owned vectors used for the current gradient and its replacement.
bool hasLinearFVGradients() const
Whether any linear finite-volume gradient fields have been registered to this object.
void restoreGradientStates()
Restore current gradients from state one after a failed timestep.
void initializeLinearFVGradientHistoryStorage()
Register named system vectors for requested historical gradient states.
void initializeLinearFVGradientStorage()
Initialize private current and replacement gradient storage.
Read-only view of one variable's cell-centered linear finite-volume gradient values.
const FVGradientMethod & method() const
Method object that produces the stored values.
const SystemBase & system() const
System whose DOF map indexes the stored values.
std::vector< libMesh::NumericVector< libMesh::Number > * > GradientContainer
One vector per spatial component of the cell-centered gradient.
Factory & getFactory()
Retrieve a writable reference to the Factory associated with this App.
const std::string & name() const
Get the name of the class.
MooseApp & getMooseApp() const
Get the MooseApp this class is associated with.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
virtual unsigned int dimension() const
Returns MeshBase::mesh_dimension(), (not MeshBase::spatial_dimension()!) of the underlying libMesh me...
This class provides an interface for common operations on field variables of both FE and FV types wit...
Interface for objects interacting with the PerfGraph.
Scope guard for starting and stopping timing for a node.
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a variable of with specified name.
bool solutionStatesInitialized() const
Whether or not the solution states have been initialized via initSolutionState()
FEProblemBase & feProblem()
virtual const std::string & name() const
const VariableWarehouse & variableWarehouse(THREAD_ID tid=0) const
NumericVector< Number > & addVector(const std::string &vector_name, const bool project, const libMesh::ParallelType type)
Adds a solution length vector to the system.
virtual libMesh::System & system()=0
Get the reference to the libMesh system.
MooseVariableBase * getVariable(const std::string &var_name) const
Get a variable from the warehouse.
std::unique_ptr< NumericVector< Number > > current_local_solution
auto index_range(const T &sizable)
Gradient values for all variables using the same gradient method.
bool has_computed_gradient
Whether the current gradient has received a computed value.
bool has_initialized_history
Whether the old gradient states contain valid values.
OwnedGradientContainer current_values
Owned current gradient values.
GradientStateContainer state_values
Published gradient values indexed by solution time state.
bool has_checked_restart_history
Whether restart data has been checked for this gradient method.
std::unordered_set< unsigned int > variable_numbers
Variable numbers whose gradients are stored in the gradient containers.
OwnedGradientContainer next_values
Replacement gradient values computed before publication.