libMesh
Loading...
Searching...
No Matches
static_condensation.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18#include "libmesh/enum_parallel_type.h"
19#include "libmesh/static_condensation.h"
20
21#if defined(LIBMESH_HAVE_EIGEN) && defined(LIBMESH_HAVE_PETSC)
22
23#include "libmesh/mesh_base.h"
24#include "libmesh/dof_map.h"
25#include "libmesh/elem.h"
26#include "libmesh/int_range.h"
27#include "libmesh/numeric_vector.h"
28#include "libmesh/linear_solver.h"
29#include "libmesh/static_condensation_preconditioner.h"
30#include "libmesh/system.h"
31#include "libmesh/petsc_matrix.h"
32#include "libmesh/equation_systems.h"
33#include "libmesh/static_condensation_dof_map.h"
34#include "timpi/parallel_sync.h"
35#include <unordered_set>
36
37namespace libMesh
38{
40 System & system,
41 const DofMap & full_dof_map,
42 StaticCondensationDofMap & reduced_dof_map)
43 : PetscMatrixShellMatrix<Number>(full_dof_map.comm()),
44 _mesh(mesh),
45 _system(system),
46 _full_dof_map(full_dof_map),
47 _reduced_dof_map(reduced_dof_map),
48 _current_elem_id(DofObject::invalid_id),
49 _sc_is_initialized(false),
50 _have_cached_values(false),
51 _parallel_type(INVALID_PARALLELIZATION),
52 _uncondensed_dofs_only(false)
53{
55 _scp = std::make_unique<StaticCondensationPreconditioner>(*this);
56}
57
59
61{
62 libmesh_not_implemented();
63}
64
65std::unique_ptr<SparseMatrix<Number>> StaticCondensation::zero_clone() const
66{
67 libmesh_not_implemented();
68}
69
70std::unique_ptr<SparseMatrix<Number>> StaticCondensation::clone() const
71{
72 libmesh_not_implemented();
73}
74
88
90 const numeric_index_type n,
91 const numeric_index_type m_l,
92 const numeric_index_type n_l,
93 const numeric_index_type nnz,
94 const numeric_index_type noz,
95 const numeric_index_type blocksize)
96{
97 if (!this->initialized())
98 {
99 PetscMatrixShellMatrix<Number>::init(m, n, m_l, n_l, nnz, noz, blocksize);
100 _parallel_type = ((m == m_l) && (this->n_processors() > 1)) ? SERIAL : PARALLEL;
101 this->init();
102 }
103}
104
106{
107 if (!this->initialized())
108 {
110 _parallel_type = type;
111 this->init();
112 }
113}
114
119
121{
122 if (this->initialized())
123 return;
124
126
127 // This API is public, so it can be called without going through the other init overloads which
128 // would give us an indication of what kind of parallel type the user wants. If we've gotten no
129 // indication so far, we will default to parallel
133
134 for (const auto & [elem_id, dof_data] : _reduced_dof_map._elem_to_dof_data)
135 {
136 auto & matrix_data = _elem_to_matrix_data[elem_id];
137
138 const auto condensed_dof_size = dof_data.condensed_global_to_local_map.size();
139 const auto uncondensed_dof_size = dof_data.uncondensed_global_to_local_map.size();
140
141 matrix_data.Acc.setZero(condensed_dof_size, condensed_dof_size);
142 matrix_data.Acu.setZero(condensed_dof_size, uncondensed_dof_size);
143 matrix_data.Auc.setZero(uncondensed_dof_size, condensed_dof_size);
144 matrix_data.Auu.setZero(uncondensed_dof_size, uncondensed_dof_size);
145 }
146
147 //
148 // Build the reduced system data
149 //
150 const auto n = _reduced_dof_map.n_dofs();
151 const auto n_local =
154 _reduced_solver->init((_system.name() + "_condensed_").c_str());
156 // Init the RHS vector so we can conveniently get processor row offsets
157 _reduced_rhs->init(n, n_local);
158
159 // Initialize the reduced system matrix
162 if (auto * const petsc_mat = dynamic_cast<PetscMatrix<Number> *>(_reduced_sys_mat.get()))
163 {
164 // Optimization for PETSc. This is critical for problems in which there are SCALAR dofs that
165 // introduce dense rows to avoid allocating a dense matrix
166 petsc_mat->init(
168 }
169 else
170 {
171 const auto & nnz = _sp->get_n_nz();
172 const auto & noz = _sp->get_n_oz();
173 const auto nz = nnz.empty() ? dof_id_type(0) : *std::max_element(nnz.begin(), nnz.end());
174 const auto oz = noz.empty() ? dof_id_type(0) : *std::max_element(noz.begin(), noz.end());
175 _reduced_sys_mat->init(n, n, n_local, n_local, nz, oz);
176 }
177
178 // Build ghosted full solution vector. Note that this is, in general, *not equal* to the system
179 // solution, e.g. this may correspond to the solution for the Newton *update*
181
182 _sc_is_initialized = true;
183}
184
186{
189 {
190 bool closed = _reduced_sys_mat->closed();
191 // closed is not collective
193 if (!closed)
194 _reduced_sys_mat->close();
195 return;
196 }
197
199 std::vector<dof_id_type> reduced_space_indices;
200 for (auto & [elem_id, matrix_data] : _elem_to_matrix_data)
201 {
202 const auto & dof_data = libmesh_map_find(_reduced_dof_map._elem_to_dof_data, elem_id);
203 reduced_space_indices.clear();
204
205 // The result matrix is either a Schur complement or it's simply the result of summing element
206 // matrices of the uncondensed degrees of freedom
207 EigenMatrix result = matrix_data.Auu;
209 {
210 matrix_data.AccFactor = matrix_data.Acc.partialPivLu();
211 result -= matrix_data.Auc * matrix_data.AccFactor.solve(matrix_data.Acu);
212 }
213 shim.resize(result.rows(), result.cols());
214 for (const auto i : make_range(result.rows()))
215 for (const auto j : make_range(result.cols()))
216 shim(i, j) = result(i, j);
217 for (const auto & var_reduced_space_indices : dof_data.reduced_space_indices)
218 reduced_space_indices.insert(reduced_space_indices.end(),
219 var_reduced_space_indices.begin(),
220 var_reduced_space_indices.end());
221 _reduced_sys_mat->add_matrix(shim, reduced_space_indices);
222 }
223
224 _reduced_sys_mat->close();
225
226 _have_cached_values = false;
227}
228
230{
231 return _reduced_sys_mat->closed() && !_have_cached_values;
232}
233
235{
236 _reduced_sys_mat->zero();
237 for (auto & [elem_id, matrix_data] : _elem_to_matrix_data)
238 {
239 libmesh_ignore(elem_id);
240 matrix_data.Acc.setZero();
241 matrix_data.Acu.setZero();
242 matrix_data.Auc.setZero();
243 matrix_data.Auu.setZero();
244 }
245}
246
248
250
252
254
256 const numeric_index_type full_j,
257 const Number val)
258{
259 const auto reduced_i = _reduced_dof_map.get_reduced_from_global_constraint_dof(full_i);
260 const auto reduced_j = _reduced_dof_map.get_reduced_from_global_constraint_dof(full_j);
261 _reduced_sys_mat->set(reduced_i, reduced_j, val);
262}
263
269
271 const numeric_index_type j,
272 const Number value)
273{
274 _size_one_mat(0, 0) = value;
275 this->add_matrix(_size_one_mat, {i}, {j});
276}
277
279 const std::vector<numeric_index_type> & rows,
280 const std::vector<numeric_index_type> & cols)
281{
282 if (rows.empty() || cols.empty())
283 return;
284
286 auto & matrix_data = libmesh_map_find(_elem_to_matrix_data, _current_elem_id);
287 const auto & dof_data = libmesh_map_find(_reduced_dof_map._elem_to_dof_data, _current_elem_id);
289
290 auto info_from_index = [&dof_data](const auto global_index) {
291 auto index_it = dof_data.condensed_global_to_local_map.find(global_index);
292 const bool index_is_condensed = index_it != dof_data.condensed_global_to_local_map.end();
293 if (!index_is_condensed)
294 {
295 index_it = dof_data.uncondensed_global_to_local_map.find(global_index);
296 if (index_it == dof_data.uncondensed_global_to_local_map.end())
297 libmesh_error_msg("Failed to find the global index "
298 << global_index
299 << " in our current element's degree of freedom information. One way "
300 "this can happen is when using a discontinuous Galerkin method, "
301 "adding element matrices to both + and - sides of a face");
302 }
303 else
304 // We found the dof in the condensed container. Let's assert that it's not also in the
305 // uncondensed container
306 libmesh_assert(dof_data.uncondensed_global_to_local_map.find(global_index) ==
307 dof_data.uncondensed_global_to_local_map.end());
308
309 return std::make_pair(index_is_condensed, index_it->second);
310 };
311
312 for (const auto i : make_range(dm.m()))
313 for (const auto j : make_range(dm.n()))
314 {
315 const auto global_i = rows[i];
316 const auto global_j = cols[j];
317 const auto [i_is_condensed, local_i] = info_from_index(global_i);
318 const auto [j_is_condensed, local_j] = info_from_index(global_j);
319 if (i_is_condensed)
320 {
321 if (j_is_condensed)
322 mat = &matrix_data.Acc;
323 else
324 mat = &matrix_data.Acu;
325 }
326 else
327 {
328 if (j_is_condensed)
329 mat = &matrix_data.Auc;
330 else
331 mat = &matrix_data.Auu;
332 }
333 (*mat)(local_i, local_j) += dm(i, j);
334 }
335
336 _have_cached_values = true;
337}
338
340 const std::vector<numeric_index_type> & dof_indices)
341{
342 this->add_matrix(dm, dof_indices, dof_indices);
343}
344
346{
347 libmesh_not_implemented();
348}
349
351{
352 libmesh_not_implemented();
353}
354
355Real StaticCondensation::l1_norm() const { libmesh_not_implemented(); }
356
357Real StaticCondensation::linfty_norm() const { libmesh_not_implemented(); }
358
359void StaticCondensation::print_personal(std::ostream &) const { libmesh_not_implemented(); }
360
361void StaticCondensation::get_diagonal(NumericVector<Number> &) const { libmesh_not_implemented(); }
362
363void StaticCondensation::get_transpose(SparseMatrix<Number> &) const { libmesh_not_implemented(); }
364
366 std::vector<numeric_index_type> &,
367 std::vector<Number> &) const
368{
369 libmesh_not_implemented();
370}
371
373 const std::vector<dof_id_type> & elem_dof_indices,
374 std::vector<Number> & elem_dof_values_vec,
375 EigenVector & elem_dof_values)
376{
377 global_vector.get(elem_dof_indices, elem_dof_values_vec);
378 elem_dof_values.resize(elem_dof_indices.size());
379 for (const auto i : index_range(elem_dof_indices))
380 elem_dof_values(i) = elem_dof_values_vec[i];
381}
382
384{
385 std::vector<dof_id_type> elem_condensed_dofs;
386 std::vector<Number> elem_condensed_rhs_vec;
387 EigenVector elem_condensed_rhs, elem_uncondensed_rhs;
388
389 full_rhs.create_subvector(
390 *_reduced_rhs, _reduced_dof_map._local_uncondensed_dofs, /*all_global_entries=*/false);
391
392 std::vector<dof_id_type> reduced_space_indices;
393 for (auto elem : _mesh.active_local_element_ptr_range())
394 {
395 auto & matrix_data = libmesh_map_find(_elem_to_matrix_data, elem->id());
396 reduced_space_indices.clear();
397 const auto & dof_data = libmesh_map_find(_reduced_dof_map._elem_to_dof_data, elem->id());
398 for (const auto & var_reduced_space_indices : dof_data.reduced_space_indices)
399 reduced_space_indices.insert(reduced_space_indices.end(),
400 var_reduced_space_indices.begin(),
401 var_reduced_space_indices.end());
402 elem_condensed_dofs.resize(dof_data.condensed_global_to_local_map.size());
403 for (const auto & [global_dof, local_dof] : dof_data.condensed_global_to_local_map)
404 {
405 libmesh_assert(local_dof < elem_condensed_dofs.size());
406 elem_condensed_dofs[local_dof] = global_dof;
407 }
408
409 set_local_vectors(full_rhs, elem_condensed_dofs, elem_condensed_rhs_vec, elem_condensed_rhs);
410 elem_uncondensed_rhs = -matrix_data.Auc * matrix_data.AccFactor.solve(elem_condensed_rhs);
411
412 libmesh_assert(cast_int<std::size_t>(elem_uncondensed_rhs.size()) ==
413 reduced_space_indices.size());
414 _reduced_rhs->add_vector(elem_uncondensed_rhs.data(), reduced_space_indices);
415 }
416 _reduced_rhs->close();
417}
418
420 NumericVector<Number> & full_sol)
421{
422 std::vector<dof_id_type> elem_condensed_dofs, elem_uncondensed_dofs;
423 std::vector<Number> elem_condensed_rhs_vec, elem_uncondensed_sol_vec;
424 EigenVector elem_condensed_rhs, elem_uncondensed_sol, elem_condensed_sol;
425
426 for (auto elem : _mesh.active_local_element_ptr_range())
427 {
428 auto & matrix_data = libmesh_map_find(_elem_to_matrix_data, elem->id());
429 const auto & dof_data = libmesh_map_find(_reduced_dof_map._elem_to_dof_data, elem->id());
430 elem_condensed_dofs.resize(dof_data.condensed_global_to_local_map.size());
431 elem_uncondensed_dofs.resize(dof_data.uncondensed_global_to_local_map.size());
432 for (const auto & [global_dof, local_dof] : dof_data.condensed_global_to_local_map)
433 {
434 libmesh_assert(local_dof < elem_condensed_dofs.size());
435 elem_condensed_dofs[local_dof] = global_dof;
436 }
437 for (const auto & [global_dof, local_dof] : dof_data.uncondensed_global_to_local_map)
438 {
439 libmesh_assert(local_dof < elem_uncondensed_dofs.size());
440 elem_uncondensed_dofs[local_dof] = global_dof;
441 }
442
443 set_local_vectors(full_rhs, elem_condensed_dofs, elem_condensed_rhs_vec, elem_condensed_rhs);
445 elem_uncondensed_dofs,
446 elem_uncondensed_sol_vec,
447 elem_uncondensed_sol);
448
449 elem_condensed_sol =
450 matrix_data.AccFactor.solve(elem_condensed_rhs - matrix_data.Acu * elem_uncondensed_sol);
451 full_sol.insert(elem_condensed_sol.data(), elem_condensed_dofs);
452 }
453
454 full_sol.close();
455}
456
458 NumericVector<Number> & full_parallel_sol)
459{
460 forward_elimination(full_rhs);
461 // Apparently PETSc will send us the yvec without zeroing it ahead of time. This can be a poor
462 // initial guess for the Krylov solve as well as lead to bewildered users who expect their initial
463 // residual norm to equal the norm of the RHS
464 full_parallel_sol.zero();
467 // Must restore to the full solution because during backwards substitution we will need to be able
468 // to read ghosted dofs and we don't support ghosting of subvectors
469 full_parallel_sol.restore_subvector(std::move(_reduced_sol),
471 *_ghosted_full_sol = full_parallel_sol;
472 backwards_substitution(full_rhs, full_parallel_sol);
473}
474
476
477void StaticCondensation::dont_condense_vars(const std::unordered_set<unsigned int> & vars)
478{
480}
481
482}
483#else
484
485#include "libmesh/dof_map.h"
486
487namespace libMesh
488{
490 const System &,
491 const DofMap & full_dof_map,
493 : SparseMatrix<Number>(full_dof_map.comm())
494{
495 libmesh_error_msg(
496 "Static condensation requires configuring libMesh with PETSc and Eigen support");
497}
498}
499
500#endif // LIBMESH_HAVE_EIGEN && LIBMESH_HAVE_PETSC
void max(const T &r, T &o, Request &req) const
void min(const T &r, T &o, Request &req) const
Defines a dense matrix for use in Finite Element-type computations.
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
dof_id_type n_dofs() const
dof_id_type first_dof(const processor_id_type proc) const
dof_id_type end_dof(const processor_id_type proc) const
dof_id_type n_local_dofs() const
This class handles the numbering of degrees of freedom on a mesh.
Definition dof_map.h:181
dof_id_type n_dofs(const unsigned int vn) const
Definition dof_map.h:776
The DofObject defines an abstract base class for objects that have degrees of freedom associated with...
Definition dof_object.h:55
static constexpr dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition dof_object.h:473
dof_id_type id() const
Definition dof_object.h:819
This is the base class from which all geometric element types are derived.
Definition elem.h:96
static std::unique_ptr< LinearSolver< T > > build(const libMesh::Parallel::Communicator &comm_in, const SolverPackage solver_package=libMesh::default_solver_package())
Builds a LinearSolver using the linear solver package specified by solver_package.
This is the MeshBase class.
Definition mesh_base.h:81
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
virtual std::unique_ptr< NumericVector< T > > get_subvector(const std::vector< numeric_index_type > &)
Creates a view into this vector using the indices in rows.
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
Access multiple components at once.
virtual void create_subvector(NumericVector< T > &, const std::vector< numeric_index_type > &, bool=true) const
Fills in subvector from this vector using the indices in rows.
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
virtual void insert(const T *v, const std::vector< numeric_index_type > &dof_indices)
Inserts the entries of v in *this at the locations specified by v.
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, SolverPackage solver_package=libMesh::default_solver_package(), ParallelType parallel_type=AUTOMATIC)
Builds a NumericVector on the processors in communicator comm using the linear solver package specifi...
virtual void zero()=0
Set all entries to zero.
virtual void restore_subvector(std::unique_ptr< NumericVector< T > >, const std::vector< numeric_index_type > &)
Restores a view into this vector using the indices in rows.
const Parallel::Communicator & _communicator
const Parallel::Communicator & comm() const
processor_id_type n_processors() const
virtual void clear() noexcept override
clear() is called from the destructor, so it should not throw.
This class allows to use a PETSc shell matrix as a PetscMatrix.
virtual void init(const numeric_index_type m, const numeric_index_type n, const numeric_index_type m_l, const numeric_index_type n_l, const numeric_index_type=30, const numeric_index_type=10, const numeric_index_type blocksize=1) override
Initialize SparseMatrix with the specified sizes.
This class provides a nice interface to the PETSc C-based AIJ data structures for parallel,...
Generic sparse matrix.
static std::unique_ptr< SparseMatrix< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package(), const MatrixBuildType matrix_build_type=MatrixBuildType::AUTOMATIC)
Builds a SparseMatrix<T> using the linear solver package specified by solver_package.
virtual bool initialized() const
SparsityPattern::Build const * _sp
The sparsity pattern associated with this object.
const std::vector< dof_id_type > & get_n_oz() const
The number of off-processor nonzeros in my portion of the global matrix.
const std::vector< dof_id_type > & get_n_nz() const
The number of on-processor nonzeros in my portion of the global matrix.
A class holding degree of freedom information pertinent to static condensation.
void dont_condense_vars(const std::unordered_set< unsigned int > &vars)
Add vars to the list of variables not to condense.
dof_id_type get_reduced_from_global_constraint_dof(dof_id_type full_dof) const
Retrieve the dof index in the reduced system corresponding to the provided dof index in the full syst...
std::vector< dof_id_type > _local_uncondensed_dofs
All the uncondensed degrees of freedom (numbered in the "full" uncondensed + condensed space).
std::unique_ptr< SparsityPattern::Build > _reduced_sp
Owned storage of the reduced system sparsity pattern.
std::unordered_map< dof_id_type, DofData > _elem_to_dof_data
A map from element ID to Schur complement data.
std::vector< dof_id_type > _reduced_noz
Number of off-diagonal nonzeros per row in the reduced system.
std::vector< dof_id_type > _reduced_nnz
Number of on-diagonal nonzeros per row in the reduced system.
bool initialized() const
Whether we are initialized.
virtual numeric_index_type row_start() const override
virtual void set(const numeric_index_type i, const numeric_index_type j, const Number value) override
Set the element (i,j) to value.
StaticCondensation(const MeshBase &mesh, System &system, const DofMap &full_dof_map, StaticCondensationDofMap &reduced_dof_map)
virtual void get_diagonal(NumericVector< Number > &dest) const override
Copies the diagonal part of the matrix into dest.
static void set_local_vectors(const NumericVector< Number > &global_vector, const std::vector< dof_id_type > &elem_dof_indices, std::vector< Number > &elem_dof_values_vec, EigenVector &elem_dof_values)
Retrieves the degree of freedom values from global_vector corresponding to elem_dof_indices,...
DenseMatrix< Number > _size_one_mat
Helper data member for adding individual matrix elements.
void backwards_substitution(const NumericVector< Number > &full_rhs, NumericVector< Number > &full_sol)
After performing the solve with the _reduced_rhs and Schur complement matrix (_reduced_sys_mat) to de...
void set_current_elem(const Elem &elem)
Set the current element.
dof_id_type _current_elem_id
The current element ID.
virtual numeric_index_type n() const override
std::unique_ptr< LinearSolver< Number > > _reduced_solver
The solver for the uncondensed degrees of freedom.
virtual void clear() noexcept override
clear() is called from the destructor, so it should not throw.
virtual bool initialized() const override
ParallelType _parallel_type
The parallel type to use for the reduced matrix.
virtual numeric_index_type row_stop() const override
virtual void print_personal(std::ostream &os=libMesh::out) const override
Print the contents of the matrix to the screen in a package-personalized style, if available.
virtual SparseMatrix< Number > & operator=(const SparseMatrix< Number > &) override
This looks like a copy assignment operator, but note that, unlike normal copy assignment operators,...
virtual Real l1_norm() const override
virtual SolverPackage solver_package() override
std::unique_ptr< NumericVector< Number > > _ghosted_full_sol
This is a ghosted representation of the full (uncondensed + condensed) solution. Note that.
virtual void get_row(numeric_index_type i, std::vector< numeric_index_type > &indices, std::vector< Number > &values) const override
Get a row from the matrix.
virtual numeric_index_type m() const override
virtual Real linfty_norm() const override
virtual bool closed() const override
virtual std::unique_ptr< SparseMatrix< Number > > clone() const override
StaticCondensationDofMap & _reduced_dof_map
bool _uncondensed_dofs_only
whether this matrix represents uncondensed dofs only.
virtual std::unique_ptr< SparseMatrix< Number > > zero_clone() const override
std::unique_ptr< NumericVector< Number > > _reduced_rhs
RHS corresponding to the uncondensed degrees of freedom.
std::unordered_map< dof_id_type, MatrixData > _elem_to_matrix_data
A map from element ID to Schur complement data.
virtual void add_matrix(const DenseMatrix< Number > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols) override
Add the full matrix dm to the SparseMatrix.
std::unique_ptr< SparseMatrix< Number > > _reduced_sys_mat
global sparse matrix for the uncondensed degrees of freedom
void dont_condense_vars(const std::unordered_set< unsigned int > &vars)
Add vars to the list of variables not to condense.
std::unique_ptr< NumericVector< Number > > _reduced_sol
solution for the uncondensed degrees of freedom
virtual void get_transpose(SparseMatrix< Number > &dest) const override
Copies the transpose of the matrix into dest, which may be *this.
bool _have_cached_values
Whether we have cached values via add_XXX()
void init()
Size the element matrices.
std::unique_ptr< StaticCondensationPreconditioner > _scp
Preconditioner object which will call back to us for the preconditioning action.
void apply(const NumericVector< Number > &full_rhs, NumericVector< Number > &full_sol)
Perform our three stages, forward_elimination(), a solve() on the condensed system,...
virtual void close() override
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
virtual void add(const numeric_index_type i, const numeric_index_type j, const Number value) override
Add value to the element (i,j).
bool _sc_is_initialized
Whether our object has been initialized.
void forward_elimination(const NumericVector< Number > &full_rhs)
Takes an incoming "full" RHS from the solver, where full means the union of uncondensed and condennse...
virtual void zero() override
Set all entries to 0.
virtual Number operator()(const numeric_index_type i, const numeric_index_type j) const override
void setup()
A no-op to be consistent with shimming from the StaticCondenstionPreconditioner.
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition system.h:100
const std::string & name() const
Definition system.h:2385
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
Definition system.h:1667
MeshBase & mesh
bool in_threads
A boolean which is true iff we are in a Threads:: function It may be useful to assert(!...
Definition threads.C:33
The libMesh namespace provides an interface to certain functionality in the library.
Eigen::Matrix< Number, Eigen::Dynamic, Eigen::Dynamic > EigenMatrix
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition int_range.h:153
ParallelType
Defines an enum for parallel data structure types.
void libmesh_ignore(const Args &...)
SolverPackage default_solver_package()
Definition libmesh.C:1064
libmesh_assert(ctx)
dof_id_type numeric_index_type
Definition id_types.h:99
SolverPackage
Defines an enum for various linear solver packages.
Eigen::Matrix< Number, Eigen::Dynamic, 1 > EigenVector
uint8_t dof_id_type
Definition id_types.h:67
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176
unsigned int n_threads()
static const bool value
Definition xdr_io.C:55