18 #include "libmesh/enum_parallel_type.h" 19 #include "libmesh/static_condensation.h" 21 #if defined(LIBMESH_HAVE_EIGEN) && defined(LIBMESH_HAVE_PETSC) 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" 35 #include <unordered_set> 41 const DofMap & full_dof_map,
46 _full_dof_map(full_dof_map),
47 _reduced_dof_map(reduced_dof_map),
49 _sc_is_initialized(false),
50 _have_cached_values(false),
52 _uncondensed_dofs_only(false)
55 _scp = std::make_unique<StaticCondensationPreconditioner>(*this);
62 libmesh_not_implemented();
67 libmesh_not_implemented();
72 libmesh_not_implemented();
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();
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);
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());
199 std::vector<dof_id_type> reduced_space_indices;
203 reduced_space_indices.clear();
210 matrix_data.AccFactor = matrix_data.Acc.partialPivLu();
211 result -= matrix_data.Auc * matrix_data.AccFactor.solve(matrix_data.Acu);
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());
240 matrix_data.Acc.setZero();
241 matrix_data.Acu.setZero();
242 matrix_data.Auc.setZero();
243 matrix_data.Auu.setZero();
279 const std::vector<numeric_index_type> & rows,
280 const std::vector<numeric_index_type> & cols)
282 if (rows.empty() || cols.empty())
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)
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 " 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");
306 libmesh_assert(dof_data.uncondensed_global_to_local_map.find(global_index) ==
307 dof_data.uncondensed_global_to_local_map.end());
309 return std::make_pair(index_is_condensed, index_it->second);
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);
322 mat = &matrix_data.Acc;
324 mat = &matrix_data.Acu;
329 mat = &matrix_data.Auc;
331 mat = &matrix_data.Auu;
333 (*mat)(local_i, local_j) += dm(i, j);
340 const std::vector<numeric_index_type> & dof_indices)
342 this->
add_matrix(dm, dof_indices, dof_indices);
347 libmesh_not_implemented();
352 libmesh_not_implemented();
366 std::vector<numeric_index_type> &,
367 std::vector<Number> &)
const 369 libmesh_not_implemented();
373 const std::vector<dof_id_type> & elem_dof_indices,
374 std::vector<Number> & elem_dof_values_vec,
377 global_vector.
get(elem_dof_indices, elem_dof_values_vec);
378 elem_dof_values.resize(elem_dof_indices.size());
380 elem_dof_values(i) = elem_dof_values_vec[i];
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;
392 std::vector<dof_id_type> reduced_space_indices;
393 for (
auto elem :
_mesh.active_local_element_ptr_range())
396 reduced_space_indices.clear();
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)
406 elem_condensed_dofs[local_dof] = global_dof;
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);
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);
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;
426 for (
auto elem :
_mesh.active_local_element_ptr_range())
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)
435 elem_condensed_dofs[local_dof] = global_dof;
437 for (
const auto & [global_dof, local_dof] : dof_data.uncondensed_global_to_local_map)
440 elem_uncondensed_dofs[local_dof] = global_dof;
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);
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);
464 full_parallel_sol.
zero();
485 #include "libmesh/dof_map.h" 491 const DofMap & full_dof_map,
496 "Static condensation requires configuring libMesh with PETSc and Eigen support");
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'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
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
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.
This class allows to use a PETSc shell matrix as a PetscMatrix.
dof_id_type n_dofs() const
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.
SparsityPattern::Build const * _sp
The sparsity pattern associated with this object.
const Parallel::Communicator & comm() const
virtual numeric_index_type n() const override
dof_id_type n_dofs(const unsigned int vn) const
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...
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.
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()
virtual numeric_index_type row_start() const override
This class handles the numbering of degrees of freedom on a mesh.
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()
void min(const T &r, T &o, Request &req) const
dof_id_type numeric_index_type
Manages consistently variables, degrees of freedom, and coefficient vectors.
std::vector< dof_id_type > _local_uncondensed_dofs
All the uncondensed degrees of freedom (numbered in the "full" uncondensed + condensed space)...
virtual ~StaticCondensation()
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.
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.
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.
const DofMap & _full_dof_map
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'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.
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
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...
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...
dof_id_type n_local_dofs() const
This class provides a nice interface to the PETSc C-based AIJ data structures for parallel...
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
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
dof_id_type first_dof(const processor_id_type proc) const
SolverPackage
Defines an enum for various linear solver packages.
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...
std::unique_ptr< NumericVector< Number > > _ghosted_full_sol
This is a ghosted representation of the full (uncondensed + condensed) solution. Note that...
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.