libMesh
static_condensation.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 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 
37 namespace 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 {
54  _size_one_mat.resize(1, 1);
55  _scp = std::make_unique<StaticCondensationPreconditioner>(*this);
56 }
57 
59 
61 {
62  libmesh_not_implemented();
63 }
64 
65 std::unique_ptr<SparseMatrix<Number>> StaticCondensation::zero_clone() const
66 {
67  libmesh_not_implemented();
68 }
69 
70 std::unique_ptr<SparseMatrix<Number>> StaticCondensation::clone() const
71 {
72  libmesh_not_implemented();
73 }
74 
76 {
78 
79  _elem_to_matrix_data.clear();
80  _reduced_sys_mat.reset();
81  _reduced_sol.reset();
82  _reduced_rhs.reset();
83  _reduced_solver.reset();
85  _have_cached_values = false;
86  _sc_is_initialized = false;
87 }
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 
116 {
118 }
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 {
188  if (!_have_cached_values)
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 
198  DenseMatrix<Number> shim;
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 
265 {
267  _current_elem_id = elem.id();
268 }
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);
288  EigenMatrix * mat;
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 
355 Real StaticCondensation::l1_norm() const { libmesh_not_implemented(); }
356 
357 Real StaticCondensation::linfty_norm() const { libmesh_not_implemented(); }
358 
359 void StaticCondensation::print_personal(std::ostream &) const { libmesh_not_implemented(); }
360 
361 void StaticCondensation::get_diagonal(NumericVector<Number> &) const { libmesh_not_implemented(); }
362 
363 void 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 
477 void 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 
487 namespace 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 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 Number operator()(const numeric_index_type i, const numeric_index_type j) const override
virtual void close() override
Calls the SparseMatrix&#39;s internal assembly routines, ensuring that the values are consistent across p...
Eigen::Matrix< Number, Eigen::Dynamic, Eigen::Dynamic > EigenMatrix
virtual bool initialized() const
A class holding degree of freedom information pertinent to static condensation.
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 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, filling both elem_dof_values_vec and elem_dof_values.
dof_id_type end_dof(const processor_id_type proc) const
Definition: dof_map_base.h:191
void init()
Size the element matrices.
virtual void clear() noexcept override
clear() is called from the destructor, so it should not throw.
virtual std::unique_ptr< SparseMatrix< Number > > clone() const override
unsigned int n_threads()
Definition: libmesh_base.h:96
void set_current_elem(const Elem &elem)
Set the current element.
StaticCondensationDofMap & _reduced_dof_map
virtual void zero() override
Set all entries to 0.
std::vector< dof_id_type > _reduced_nnz
Number of on-diagonal nonzeros per row in the reduced system.
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
Access multiple components at once.
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...
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.
Definition: linear_solver.C:59
This class allows to use a PETSc shell matrix as a PetscMatrix.
dof_id_type n_dofs() const
Definition: dof_map_base.h:105
std::unique_ptr< LinearSolver< Number > > _reduced_solver
The solver for the uncondensed degrees of freedom.
void setup()
A no-op to be consistent with shimming from the StaticCondenstionPreconditioner.
ParallelType _parallel_type
The parallel type to use for the reduced matrix.
const std::vector< dof_id_type > & get_n_oz() const
The number of off-processor nonzeros in my portion of the global matrix.
Eigen::Matrix< Number, Eigen::Dynamic, 1 > EigenVector
virtual bool initialized() const override
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.
std::vector< dof_id_type > _reduced_noz
Number of off-diagonal nonzeros per row in the reduced system.
std::unique_ptr< NumericVector< Number > > _reduced_sol
solution for the uncondensed degrees of freedom
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
MeshBase & mesh
SparsityPattern::Build const * _sp
The sparsity pattern associated with this object.
const Parallel::Communicator & comm() const
virtual numeric_index_type n() const override
unsigned int m() const
dof_id_type n_dofs(const unsigned int vn) const
Definition: dof_map.h:668
const Parallel::Communicator & _communicator
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...
The libMesh namespace provides an interface to certain functionality in the library.
dof_id_type _current_elem_id
The current element ID.
bool in_threads
A boolean which is true iff we are in a Threads:: function It may be useful to assert(!Threadsin_thre...
Definition: threads.C:32
virtual Real l1_norm() const override
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.
This is the MeshBase class.
Definition: mesh_base.h:75
virtual void zero()=0
Set all entries to zero.
std::unordered_map< dof_id_type, DofData > _elem_to_dof_data
A map from element ID to Schur complement data.
void dont_condense_vars(const std::unordered_set< unsigned int > &vars)
Add vars to the list of variables not to condense.
virtual numeric_index_type row_stop() const override
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 numeric_index_type m() const override
SolverPackage default_solver_package()
Definition: libmesh.C:1117
virtual numeric_index_type row_start() const override
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:179
processor_id_type n_processors() const
void libmesh_ignore(const Args &...)
void dont_condense_vars(const std::unordered_set< unsigned int > &vars)
Add vars to the list of variables not to condense.
virtual void add(const numeric_index_type i, const numeric_index_type j, const Number value) override
Add value to the element (i,j).
void apply(const NumericVector< Number > &full_rhs, NumericVector< Number > &full_sol)
Perform our three stages, forward_elimination(), a solve() on the condensed system, and finally a backwards_substitution()
dof_id_type id() const
Definition: dof_object.h:828
void min(const T &r, T &o, Request &req) const
dof_id_type numeric_index_type
Definition: id_types.h:99
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:96
std::vector< dof_id_type > _local_uncondensed_dofs
All the uncondensed degrees of freedom (numbered in the "full" uncondensed + condensed space)...
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 void clear() noexcept override
Restores the SparseMatrix<T> to a pristine state.
libmesh_assert(ctx)
DenseMatrix< Number > _size_one_mat
Helper data member for adding individual matrix elements.
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:482
std::unordered_map< dof_id_type, MatrixData > _elem_to_matrix_data
A map from element ID to Schur complement data.
virtual void get_diagonal(NumericVector< Number > &dest) const override
Copies the diagonal part of the matrix into dest.
virtual void set(const numeric_index_type i, const numeric_index_type j, const Number value) override
Set the element (i,j) to value.
bool _uncondensed_dofs_only
whether this matrix represents uncondensed dofs only.
std::unique_ptr< SparseMatrix< Number > > _reduced_sys_mat
global sparse matrix for the uncondensed degrees of freedom
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 close()=0
Calls the NumericVector&#39;s internal assembly routines, ensuring that the values are consistent across ...
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.
const std::vector< dof_id_type > & get_n_nz() const
The number of on-processor nonzeros in my portion of the global matrix.
std::unique_ptr< NumericVector< Number > > _reduced_rhs
RHS corresponding to the uncondensed degrees of freedom.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void max(const T &r, T &o, Request &req) const
virtual Real linfty_norm() const override
std::unique_ptr< StaticCondensationPreconditioner > _scp
Preconditioner object which will call back to us for the preconditioning action.
static const bool value
Definition: xdr_io.C:54
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
Definition: dense_matrix.h:895
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:140
virtual SparseMatrix< Number > & operator=(const SparseMatrix< Number > &) override
This looks like a copy assignment operator, but note that, unlike normal copy assignment operators...
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...
The DofObject defines an abstract base class for objects that have degrees of freedom associated with...
Definition: dof_object.h:54
dof_id_type n_local_dofs() const
Definition: dof_map_base.h:115
This class provides a nice interface to the PETSc C-based AIJ data structures for parallel...
Definition: petsc_matrix.h:61
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:1605
virtual std::unique_ptr< SparseMatrix< Number > > zero_clone() const override
bool _have_cached_values
Whether we have cached values via add_XXX()
std::unique_ptr< SparsityPattern::Build > _reduced_sp
Owned storage of the reduced system sparsity pattern.
virtual void get_transpose(SparseMatrix< Number > &dest) const override
Copies the transpose of the matrix into dest, which may be *this.
StaticCondensation(const MeshBase &mesh, System &system, const DofMap &full_dof_map, StaticCondensationDofMap &reduced_dof_map)
virtual bool closed() const override
bool initialized() const
Whether we are initialized.
const std::string & name() const
Definition: system.h:2342
dof_id_type first_dof(const processor_id_type proc) const
Definition: dof_map_base.h:185
SolverPackage
Defines an enum for various linear solver packages.
unsigned int n() const
virtual SolverPackage solver_package() override
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:117
std::unique_ptr< NumericVector< Number > > _ghosted_full_sol
This is a ghosted representation of the full (uncondensed + condensed) solution. Note that...
uint8_t dof_id_type
Definition: id_types.h:67
ParallelType
Defines an enum for parallel data structure types.
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.
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.
bool _sc_is_initialized
Whether our object has been initialized.