17 #include "libmesh/enum_point_locator_type.h" 18 #include "libmesh/system.h" 26 const Real relaxation_parameter,
29 PetscMatrix<Number> * mat =
dynamic_cast<PetscMatrix<Number> *
>(&matrix);
30 mooseAssert(mat,
"This should be a PetscMatrix!");
31 PetscVector<Number> * diff_diag =
dynamic_cast<PetscVector<Number> *
>(&diff_diagonal);
32 mooseAssert(diff_diag,
"This should be a PetscVector!");
38 mat->get_diagonal(*diff_diag);
41 auto original_diagonal = diff_diag->clone();
45 const Real inverse_relaxation = 1 / relaxation_parameter;
60 std::vector<dof_id_type> indices(local_size);
61 std::iota(indices.begin(), indices.end(), matrix.
row_start());
62 std::vector<Real> new_diagonal(local_size, 0.0);
66 for (
const auto row_i :
make_range(local_size))
68 const unsigned int global_index = matrix.
row_start() + row_i;
69 std::vector<numeric_index_type> indices;
70 std::vector<Real> values;
71 mat->get_row(global_index, indices, values);
72 const Real abs_sum = std::accumulate(
73 values.cbegin(), values.cend(), 0.0, [](
Real a,
Real b) {
return a + std::abs(
b); });
74 const Real abs_diagonal = std::abs(diff_diga_reader(global_index));
75 new_diagonal[row_i] = inverse_relaxation * std::max(abs_sum - abs_diagonal, abs_diagonal);
78 diff_diag->insert(new_diagonal, indices);
81 LibmeshPetscCallA(mat->comm().get(), MatDiagonalSet(mat->mat(), diff_diag->vec(), INSERT_VALUES));
87 diff_diag->add(-1.0, *original_diagonal);
98 auto working_vector = diff_diagonal.
clone();
99 working_vector->pointwise_mult(solution, *working_vector);
107 rhs.
add(*working_vector);
114 const Real relaxation_factor)
117 vec_new.
scale(relaxation_factor);
118 vec_new.
add(1 - relaxation_factor, vec_old);
125 PetscVector<Number> & solution_vector =
dynamic_cast<PetscVector<Number> &
>(solution);
126 auto value = solution_vector.get_array();
128 for (
auto i :
make_range(solution_vector.local_size()))
129 value[i] = std::min(std::max(min_limit,
value[i]), max_limit);
131 solution_vector.restore_array();
152 auto A_times_average_solution = solution.
zero_clone();
153 auto A_times_solution = solution.
zero_clone();
158 *A_times_solution = solution.
sum() / solution.
size();
159 mat.
vector_mult(*A_times_average_solution, *A_times_solution);
163 A_times_solution->add(-1.0, *A_times_average_solution);
165 A_times_average_solution->add(-1.0, rhs);
166 A_times_solution->abs();
167 A_times_average_solution->abs();
170 A_times_average_solution->add(*A_times_solution);
182 const Real desired_value,
190 Real diag = mx(dof_id, dof_id);
191 rhs.
add(dof_id, desired_value * diag);
192 mx.
add(dof_id, dof_id, diag);
201 point_locator->enable_out_of_mesh_mode();
206 const bool block_restricted =
209 block_restricted ? (*point_locator)(point, &variable.
blockIDs()) : (*point_locator)(point);
213 const dof_id_type elem_id = elem ? elem->id() : DofObject::invalid_id;
217 if (min_elem_id == DofObject::invalid_id)
220 " is not defined at ",
222 "! Try alleviating block restrictions or using another point!");
224 return min_elem_id == elem_id ? elem->dof_number(variable.
sys().
number(), var_num, 0)
225 : DofObject::invalid_id;
229 converged(
const std::vector<std::pair<unsigned int, Real>> & its_and_residuals,
230 const std::vector<Real> & abs_tolerances)
232 mooseAssert(its_and_residuals.size() == abs_tolerances.size(),
233 "The number of residuals should (now " + std::to_string(its_and_residuals.size()) +
234 ") be the same as the number of tolerances (" +
235 std::to_string(abs_tolerances.size()) +
")!");
238 for (
const auto system_i :
index_range(its_and_residuals))
240 converged =
converged && (its_and_residuals[system_i].second < abs_tolerances[system_i]);
void relaxMatrix(SparseMatrix< Number > &matrix_in, const Real relaxation_parameter, NumericVector< Number > &diff_diagonal)
Relax the matrix to ensure diagonal dominance, we hold onto the difference in diagonals for later use...
void mooseError(Args &&... args)
Real computeNormalizationFactor(const NumericVector< Number > &solution, const SparseMatrix< Number > &mat, const NumericVector< Number > &rhs)
Compute a normalization factor which is applied to the linear residual to determine convergence...
static constexpr Real TOLERANCE
void vector_mult(NumericVector< Number > &dest, const NumericVector< Number > &arg) const
virtual Number sum() const =0
virtual numeric_index_type size() const =0
virtual std::unique_ptr< NumericVector< Number > > zero_clone() const =0
virtual libMesh::System & system()=0
const std::string & name() const override
const Parallel::Communicator & comm() const
virtual std::unique_ptr< NumericVector< Number > > clone() const =0
virtual const std::set< SubdomainID > & blockIDs() const
void relaxRightHandSide(NumericVector< Number > &rhs_in, const NumericVector< Number > &solution_in, const NumericVector< Number > &diff_diagonal)
Relax the right hand side of an equation, this needs to be called once and the system matrix has been...
virtual numeric_index_type row_stop() const =0
unsigned int variable_number(std::string_view var) const
virtual void add(const numeric_index_type i, const numeric_index_type j, const Number value)=0
bool converged(const std::vector< std::pair< unsigned int, Real >> &residuals, const std::vector< Real > &abs_tolerances)
Based on the residuals, determine if the iterative process converged or not.
virtual void scale(const Number factor)=0
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
void min(const T &r, T &o, Request &req) const
unsigned int number() const
std::string stringify(const T &t)
dof_id_type findPointDoFID(const MooseVariableFieldBase &variable, const MooseMesh &mesh, const Point &point)
Find the ID of the degree of freedom which corresponds to the variable and a given point on the mesh...
const SubdomainID ANY_BLOCK_ID
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual numeric_index_type row_start() const =0
IntRange< T > make_range(T beg, T end)
void constrainSystem(SparseMatrix< Number > &mx, NumericVector< Number > &rhs, const Real desired_value, const dof_id_type dof_id)
Implicitly constrain the system by adding a factor*(u-u_desired) to it at a desired dof value...
virtual void add(const numeric_index_type i, const Number value)=0
void limitSolutionUpdate(NumericVector< Number > &solution, const Real min_limit=std::numeric_limits< Real >::epsilon(), const Real max_limit=1e10)
Limit a solution to its minimum and maximum bounds: $u = min(max(u, min_limit), max_limit)$.
void relaxSolutionUpdate(NumericVector< Number > &vec_new, const NumericVector< Number > &vec_old, const Real relaxation_factor)
Relax the update on a solution field using the following approach: $u = u_{old}+ (u - u_{old})$...
auto index_range(const T &sizable)