libMesh::DofMap Class Reference

Manages the degrees of freedom (DOFs) in a simulation. More...

#include <dof_map.h>

Inheritance diagram for libMesh::DofMap:

Classes

class  AugmentSendList
 
class  AugmentSparsityPattern
 

Public Member Functions

 DofMap (const unsigned int sys_number, MeshBase &mesh)
 
 ~DofMap ()
 
void attach_matrix (SparseMatrix< Number > &matrix)
 
bool is_attached (SparseMatrix< Number > &matrix)
 
void distribute_dofs (MeshBase &)
 
void compute_sparsity (const MeshBase &)
 
void clear_sparsity ()
 
void remove_default_ghosting ()
 
void add_default_ghosting ()
 
void add_coupling_functor (GhostingFunctor &coupling_functor, bool to_mesh=true)
 
void remove_coupling_functor (GhostingFunctor &coupling_functor)
 
std::set< GhostingFunctor * >::const_iterator coupling_functors_begin () const
 
std::set< GhostingFunctor * >::const_iterator coupling_functors_end () const
 
DefaultCouplingdefault_coupling ()
 
void add_algebraic_ghosting_functor (GhostingFunctor &evaluable_functor, bool to_mesh=true)
 
void remove_algebraic_ghosting_functor (GhostingFunctor &evaluable_functor)
 
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_begin () const
 
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_end () const
 
DefaultCouplingdefault_algebraic_ghosting ()
 
void attach_extra_sparsity_object (DofMap::AugmentSparsityPattern &asp)
 
void attach_extra_sparsity_function (void(*func)(SparsityPattern::Graph &sparsity, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *), void *context=nullptr)
 
void attach_extra_send_list_object (DofMap::AugmentSendList &asl)
 
void attach_extra_send_list_function (void(*func)(std::vector< dof_id_type > &, void *), void *context=nullptr)
 
void prepare_send_list ()
 
const std::vector< dof_id_type > & get_send_list () const
 
const std::vector< dof_id_type > & get_n_nz () const
 
const std::vector< dof_id_type > & get_n_oz () const
 
void add_variable_group (const VariableGroup &var_group)
 
void set_error_on_cyclic_constraint (bool error_on_cyclic_constraint)
 
const VariableGroupvariable_group (const unsigned int c) const
 
const Variablevariable (const unsigned int c) const
 
Order variable_order (const unsigned int c) const
 
Order variable_group_order (const unsigned int vg) const
 
const FETypevariable_type (const unsigned int c) const
 
const FETypevariable_group_type (const unsigned int vg) const
 
unsigned int n_variable_groups () const
 
unsigned int n_variables () const
 
bool has_blocked_representation () const
 
unsigned int block_size () const
 
dof_id_type n_dofs () const
 
dof_id_type n_SCALAR_dofs () const
 
dof_id_type n_local_dofs () const
 
dof_id_type n_dofs_on_processor (const processor_id_type proc) const
 
dof_id_type first_dof (const processor_id_type proc) const
 
dof_id_type first_dof () const
 
dof_id_type first_old_dof (const processor_id_type proc) const
 
dof_id_type first_old_dof () const
 
dof_id_type last_dof (const processor_id_type proc) const
 
dof_id_type last_dof () const
 
dof_id_type end_dof (const processor_id_type proc) const
 
dof_id_type end_dof () const
 
processor_id_type dof_owner (const dof_id_type dof) const
 
dof_id_type end_old_dof (const processor_id_type proc) const
 
dof_id_type end_old_dof () const
 
void dof_indices (const Elem *const elem, std::vector< dof_id_type > &di) const
 
void dof_indices (const Elem *const elem, std::vector< dof_id_type > &di, const unsigned int vn, int p_level=-12345) const
 
void dof_indices (const Node *const node, std::vector< dof_id_type > &di) const
 
void dof_indices (const Node *const node, std::vector< dof_id_type > &di, const unsigned int vn) const
 
void SCALAR_dof_indices (std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
 
bool semilocal_index (dof_id_type dof_index) const
 
bool all_semilocal_indices (const std::vector< dof_id_type > &dof_indices) const
 
bool local_index (dof_id_type dof_index) const
 
template<typename DofObjectSubclass >
bool is_evaluable (const DofObjectSubclass &obj, unsigned int var_num=libMesh::invalid_uint) const
 
void set_implicit_neighbor_dofs (bool implicit_neighbor_dofs)
 
bool use_coupled_neighbor_dofs (const MeshBase &mesh) const
 
void extract_local_vector (const NumericVector< Number > &Ug, const std::vector< dof_id_type > &dof_indices, DenseVectorBase< Number > &Ue) const
 
void local_variable_indices (std::vector< dof_id_type > &idx, const MeshBase &mesh, unsigned int var_num) const
 
dof_id_type n_constrained_dofs () const
 
dof_id_type n_local_constrained_dofs () const
 
dof_id_type n_constrained_nodes () const
 
void create_dof_constraints (const MeshBase &, Real time=0)
 
void allgather_recursive_constraints (MeshBase &)
 
void scatter_constraints (MeshBase &)
 
void gather_constraints (MeshBase &mesh, std::set< dof_id_type > &unexpanded_dofs, bool look_for_constrainees)
 
void process_constraints (MeshBase &)
 
void check_for_cyclic_constraints ()
 
void add_constraint_row (const dof_id_type dof_number, const DofConstraintRow &constraint_row, const Number constraint_rhs, const bool forbid_constraint_overwrite)
 
void add_adjoint_constraint_row (const unsigned int qoi_index, const dof_id_type dof_number, const DofConstraintRow &constraint_row, const Number constraint_rhs, const bool forbid_constraint_overwrite)
 
void add_constraint_row (const dof_id_type dof_number, const DofConstraintRow &constraint_row, const bool forbid_constraint_overwrite=true)
 
DofConstraints::const_iterator constraint_rows_begin () const
 
DofConstraints::const_iterator constraint_rows_end () const
 
void stash_dof_constraints ()
 
void unstash_dof_constraints ()
 
NodeConstraints::const_iterator node_constraint_rows_begin () const
 
NodeConstraints::const_iterator node_constraint_rows_end () const
 
bool is_constrained_dof (const dof_id_type dof) const
 
bool has_heterogenous_adjoint_constraints (const unsigned int qoi_num) const
 
Number has_heterogenous_adjoint_constraint (const unsigned int qoi_num, const dof_id_type dof) const
 
DofConstraintValueMapget_primal_constraint_values ()
 
bool is_constrained_node (const Node *node) const
 
void print_dof_constraints (std::ostream &os=libMesh::out, bool print_nonlocal=false) const
 
std::string get_local_constraints (bool print_nonlocal=false) const
 
std::pair< Real, Realmax_constraint_error (const System &system, NumericVector< Number > *v=nullptr) const
 
void constrain_element_matrix (DenseMatrix< Number > &matrix, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
 
void constrain_element_matrix (DenseMatrix< Number > &matrix, std::vector< dof_id_type > &row_dofs, std::vector< dof_id_type > &col_dofs, bool asymmetric_constraint_rows=true) const
 
void constrain_element_vector (DenseVector< Number > &rhs, std::vector< dof_id_type > &dofs, bool asymmetric_constraint_rows=true) const
 
void constrain_element_matrix_and_vector (DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
 
void heterogenously_constrain_element_matrix_and_vector (DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true, int qoi_index=-1) const
 
void heterogenously_constrain_element_vector (const DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true, int qoi_index=-1) const
 
void constrain_element_dyad_matrix (DenseVector< Number > &v, DenseVector< Number > &w, std::vector< dof_id_type > &row_dofs, bool asymmetric_constraint_rows=true) const
 
void constrain_nothing (std::vector< dof_id_type > &dofs) const
 
void enforce_constraints_exactly (const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const
 
void enforce_adjoint_constraints_exactly (NumericVector< Number > &v, unsigned int q) const
 
void add_periodic_boundary (const PeriodicBoundaryBase &periodic_boundary)
 
void add_periodic_boundary (const PeriodicBoundaryBase &boundary, const PeriodicBoundaryBase &inverse_boundary)
 
bool is_periodic_boundary (const boundary_id_type boundaryid) const
 
PeriodicBoundariesget_periodic_boundaries ()
 
void add_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary)
 
void add_adjoint_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary, unsigned int q)
 
void remove_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary)
 
void remove_adjoint_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary, unsigned int q)
 
const DirichletBoundariesget_dirichlet_boundaries () const
 
DirichletBoundariesget_dirichlet_boundaries ()
 
bool has_adjoint_dirichlet_boundaries (unsigned int q) const
 
const DirichletBoundariesget_adjoint_dirichlet_boundaries (unsigned int q) const
 
DirichletBoundariesget_adjoint_dirichlet_boundaries (unsigned int q)
 
void old_dof_indices (const Elem *const elem, std::vector< dof_id_type > &di, const unsigned int vn=libMesh::invalid_uint) const
 
dof_id_type n_old_dofs () const
 
void constrain_p_dofs (unsigned int var, const Elem *elem, unsigned int s, unsigned int p)
 
void reinit (MeshBase &mesh)
 
void clear ()
 
void print_info (std::ostream &os=libMesh::out) const
 
std::string get_info () const
 
unsigned int sys_number () const
 
const Parallel::Communicatorcomm () const
 
processor_id_type n_processors () const
 
processor_id_type processor_id () const
 

Static Public Member Functions

static std::string get_info ()
 
static void print_info (std::ostream &out=libMesh::out)
 
static unsigned int n_objects ()
 
static void enable_print_counter_info ()
 
static void disable_print_counter_info ()
 

Public Attributes

CouplingMatrix_dof_coupling
 

Protected Types

typedef std::map< std::string, std::pair< unsigned int, unsigned int > > Counts
 

Protected Member Functions

void increment_constructor_count (const std::string &name)
 
void increment_destructor_count (const std::string &name)
 

Protected Attributes

const Parallel::Communicator_communicator
 

Static Protected Attributes

static Counts _counts
 
static Threads::atomic< unsigned int > _n_objects
 
static Threads::spin_mutex _mutex
 
static bool _enable_print_counter = true
 

Private Types

typedef DofObject *(DofMap::* dofobject_accessor) (MeshBase &mesh, dof_id_type i) const
 

Private Member Functions

void _dof_indices (const Elem &elem, int p_level, std::vector< dof_id_type > &di, const unsigned int vg, const unsigned int vig, const Node *const *nodes, unsigned int n_nodes #ifdef DEBUG, const unsigned int v, std::size_t &tot_size #endif) const
 
std::unique_ptr< SparsityPattern::Buildbuild_sparsity (const MeshBase &mesh) const
 
void invalidate_dofs (MeshBase &mesh) const
 
DofObjectnode_ptr (MeshBase &mesh, dof_id_type i) const
 
DofObjectelem_ptr (MeshBase &mesh, dof_id_type i) const
 
template<typename iterator_type >
void set_nonlocal_dof_objects (iterator_type objects_begin, iterator_type objects_end, MeshBase &mesh, dofobject_accessor objects)
 
void distribute_local_dofs_var_major (dof_id_type &next_free_dof, MeshBase &mesh)
 
void distribute_local_dofs_node_major (dof_id_type &next_free_dof, MeshBase &mesh)
 
void add_neighbors_to_send_list (MeshBase &mesh)
 
void build_constraint_matrix (DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
 
void build_constraint_matrix_and_vector (DenseMatrix< Number > &C, DenseVector< Number > &H, std::vector< dof_id_type > &elem_dofs, int qoi_index=-1, const bool called_recursively=false) const
 
void find_connected_dofs (std::vector< dof_id_type > &elem_dofs) const
 
void find_connected_dof_objects (std::vector< const DofObject *> &objs) const
 
void add_constraints_to_send_list ()
 
void check_dirichlet_bcid_consistency (const MeshBase &mesh, const DirichletBoundary &boundary) const
 

Static Private Member Functions

static void merge_ghost_functor_outputs (GhostingFunctor::map_type &elements_to_ghost, std::set< CouplingMatrix *> &temporary_coupling_matrices, const std::set< GhostingFunctor *>::iterator &gf_begin, const std::set< GhostingFunctor *>::iterator &gf_end, const MeshBase::const_element_iterator &elems_begin, const MeshBase::const_element_iterator &elems_end, processor_id_type p)
 

Private Attributes

bool _error_on_cyclic_constraint
 
std::vector< Variable_variables
 
std::vector< VariableGroup_variable_groups
 
std::vector< unsigned int > _variable_group_numbers
 
const unsigned int _sys_number
 
MeshBase_mesh
 
std::vector< SparseMatrix< Number > *> _matrices
 
std::vector< dof_id_type_first_df
 
std::vector< dof_id_type_end_df
 
std::vector< dof_id_type_first_scalar_df
 
std::vector< dof_id_type_send_list
 
AugmentSparsityPattern_augment_sparsity_pattern
 
void(* _extra_sparsity_function )(SparsityPattern::Graph &, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *)
 
void * _extra_sparsity_context
 
AugmentSendList_augment_send_list
 
void(* _extra_send_list_function )(std::vector< dof_id_type > &, void *)
 
void * _extra_send_list_context
 
std::unique_ptr< DefaultCoupling_default_coupling
 
std::unique_ptr< DefaultCoupling_default_evaluating
 
std::set< GhostingFunctor * > _algebraic_ghosting_functors
 
std::set< GhostingFunctor * > _coupling_functors
 
bool need_full_sparsity_pattern
 
std::unique_ptr< SparsityPattern::Build_sp
 
std::vector< dof_id_type > * _n_nz
 
std::vector< dof_id_type > * _n_oz
 
dof_id_type _n_dfs
 
dof_id_type _n_SCALAR_dofs
 
dof_id_type _n_old_dfs
 
std::vector< dof_id_type_first_old_df
 
std::vector< dof_id_type_end_old_df
 
std::vector< dof_id_type_first_old_scalar_df
 
DofConstraints _dof_constraints
 
DofConstraints _stashed_dof_constraints
 
DofConstraintValueMap _primal_constraint_values
 
AdjointDofConstraintValues _adjoint_constraint_values
 
NodeConstraints _node_constraints
 
std::unique_ptr< PeriodicBoundaries_periodic_boundaries
 
std::unique_ptr< DirichletBoundaries_dirichlet_boundaries
 
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
 
bool _implicit_neighbor_dofs_initialized
 
bool _implicit_neighbor_dofs
 

Friends

class SparsityPattern::Build
 

Detailed Description

Manages the degrees of freedom (DOFs) in a simulation.

This class handles the numbering of degrees of freedom on a mesh. For systems of equations the class supports a fixed number of variables. The degrees of freedom are numbered such that sequential, contiguous blocks belong to distinct processors. This is so that the resulting data structures will work well with parallel linear algebra packages.

Author
Benjamin S. Kirk
Date
2002-2007

Definition at line 176 of file dof_map.h.

Member Typedef Documentation

◆ Counts

typedef std::map<std::string, std::pair<unsigned int, unsigned int> > libMesh::ReferenceCounter::Counts
protectedinherited

Data structure to log the information. The log is identified by the class name.

Definition at line 117 of file reference_counter.h.

◆ dofobject_accessor

typedef DofObject*(DofMap::* libMesh::DofMap::dofobject_accessor) (MeshBase &mesh, dof_id_type i) const
private

A member function type like node_ptr() or elem_ptr().

Definition at line 1376 of file dof_map.h.

Constructor & Destructor Documentation

◆ DofMap()

libMesh::DofMap::DofMap ( const unsigned int  sys_number,
MeshBase mesh 
)
explicit

Constructor. Requires the number of the system for which we will be numbering degrees of freedom & the parent object we are contained in, which defines our communication space.

Definition at line 130 of file dof_map.C.

References _default_coupling, _default_evaluating, _matrices, _mesh, _periodic_boundaries, add_algebraic_ghosting_functor(), and add_coupling_functor().

131  :
132  ParallelObject (mesh.comm()),
133  _dof_coupling(nullptr),
135  _variables(),
138  _sys_number(number),
139  _mesh(mesh),
140  _matrices(),
141  _first_df(),
142  _end_df(),
144  _send_list(),
145  _augment_sparsity_pattern(nullptr),
146  _extra_sparsity_function(nullptr),
147  _extra_sparsity_context(nullptr),
148  _augment_send_list(nullptr),
149  _extra_send_list_function(nullptr),
150  _extra_send_list_context(nullptr),
151  _default_coupling(new DefaultCoupling()),
152  _default_evaluating(new DefaultCoupling()),
154  _n_nz(nullptr),
155  _n_oz(nullptr),
156  _n_dfs(0),
157  _n_SCALAR_dofs(0)
158 #ifdef LIBMESH_ENABLE_AMR
159  , _n_old_dfs(0),
160  _first_old_df(),
161  _end_old_df(),
163 #endif
164 #ifdef LIBMESH_ENABLE_CONSTRAINTS
165  , _dof_constraints()
169 #endif
170 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
172 #endif
173 #ifdef LIBMESH_ENABLE_PERIODIC
174  , _periodic_boundaries(new PeriodicBoundaries)
175 #endif
176 #ifdef LIBMESH_ENABLE_DIRICHLET
177  , _dirichlet_boundaries(new DirichletBoundaries)
179 #endif
182 {
183  _matrices.clear();
184 
185  _default_coupling->set_mesh(&_mesh);
186  _default_evaluating->set_mesh(&_mesh);
187  _default_evaluating->set_n_levels(1);
188 
189 #ifdef LIBMESH_ENABLE_PERIODIC
190  _default_coupling->set_periodic_boundaries(_periodic_boundaries.get());
191  _default_evaluating->set_periodic_boundaries(_periodic_boundaries.get());
192 #endif
193 
196 }
std::vector< VariableGroup > _variable_groups
Definition: dof_map.h:1503
ParallelObject(const Parallel::Communicator &comm_in)
bool _error_on_cyclic_constraint
Definition: dof_map.h:1493
bool _implicit_neighbor_dofs_initialized
Definition: dof_map.h:1736
const unsigned int _sys_number
Definition: dof_map.h:1513
bool _implicit_neighbor_dofs
Definition: dof_map.h:1737
void * _extra_sparsity_context
Definition: dof_map.h:1564
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1547
MeshBase & mesh
AugmentSparsityPattern * _augment_sparsity_pattern
Definition: dof_map.h:1552
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Definition: dof_map.h:1721
std::vector< dof_id_type > _end_old_df
Definition: dof_map.h:1672
void add_coupling_functor(GhostingFunctor &coupling_functor, bool to_mesh=true)
Definition: dof_map.C:1809
std::vector< dof_id_type > _first_old_df
Definition: dof_map.h:1667
std::vector< dof_id_type > _first_scalar_df
Definition: dof_map.h:1541
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1691
std::vector< dof_id_type > * _n_nz
Definition: dof_map.h:1638
AugmentSendList * _augment_send_list
Definition: dof_map.h:1569
std::vector< dof_id_type > * _n_oz
Definition: dof_map.h:1644
bool need_full_sparsity_pattern
Definition: dof_map.h:1624
std::vector< dof_id_type > _first_old_scalar_df
Definition: dof_map.h:1678
void(* _extra_sparsity_function)(SparsityPattern::Graph &, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *)
Definition: dof_map.h:1557
dof_id_type _n_SCALAR_dofs
Definition: dof_map.h:1655
DofConstraints _dof_constraints
Definition: dof_map.h:1687
CouplingMatrix * _dof_coupling
Definition: dof_map.h:1319
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1727
void * _extra_send_list_context
Definition: dof_map.h:1579
std::vector< SparseMatrix< Number > *> _matrices
Definition: dof_map.h:1525
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Definition: dof_map.h:1707
std::unique_ptr< DefaultCoupling > _default_coupling
Definition: dof_map.h:1587
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1689
std::vector< Variable > _variables
Definition: dof_map.h:1498
DofConstraints _stashed_dof_constraints
Definition: dof_map.h:1687
dof_id_type _n_old_dfs
Definition: dof_map.h:1662
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1535
std::vector< dof_id_type > _first_df
Definition: dof_map.h:1530
void(* _extra_send_list_function)(std::vector< dof_id_type > &, void *)
Definition: dof_map.h:1574
MeshBase & _mesh
Definition: dof_map.h:1518
std::unique_ptr< DefaultCoupling > _default_evaluating
Definition: dof_map.h:1595
std::vector< unsigned int > _variable_group_numbers
Definition: dof_map.h:1508
void add_algebraic_ghosting_functor(GhostingFunctor &evaluable_functor, bool to_mesh=true)
Definition: dof_map.C:1829
dof_id_type _n_dfs
Definition: dof_map.h:1649
NodeConstraints _node_constraints
Definition: dof_map.h:1698

◆ ~DofMap()

libMesh::DofMap::~DofMap ( )

Destructor.

Definition at line 201 of file dof_map.C.

References _adjoint_dirichlet_boundaries, _default_coupling, _default_evaluating, _mesh, clear(), and libMesh::MeshBase::remove_ghosting_functor().

202 {
203  this->clear();
204 
205  // clear() resets all but the default DofMap-based functors. We
206  // need to remove those from the mesh too before we die.
209 
210 #ifdef LIBMESH_ENABLE_DIRICHLET
211  for (auto & bnd : _adjoint_dirichlet_boundaries)
212  delete bnd;
213 #endif
214 }
void remove_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: mesh_base.C:281
void clear()
Definition: dof_map.C:828
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1727
std::unique_ptr< DefaultCoupling > _default_coupling
Definition: dof_map.h:1587
MeshBase & _mesh
Definition: dof_map.h:1518
std::unique_ptr< DefaultCoupling > _default_evaluating
Definition: dof_map.h:1595

Member Function Documentation

◆ _dof_indices()

void libMesh::DofMap::_dof_indices ( const Elem elem,
int  p_level,
std::vector< dof_id_type > &  di,
const unsigned int  vg,
const unsigned int  vig,
const Node *const *  nodes,
unsigned int n_nodes #ifdef  DEBUG,
const unsigned int  v,
std::size_t &tot_size #  endif 
) const
private

Helper function that gets the dof indices on the current element for a non-SCALAR type variable, where the variable is identified by its variable group number vg and its offset vig from the first variable in that group.

In DEBUG mode, the tot_size parameter will add up the total number of dof indices that should have been added to di, and v will be the variable number corresponding to vg and vig.

Definition at line 2209 of file dof_map.C.

References libMesh::Elem::active(), libMesh::Variable::active_on_subdomain(), libMesh::Elem::dim(), libMesh::DofObject::dof_number(), libMesh::FEInterface::extra_hanging_dofs(), libMesh::FEType::family, libMesh::Elem::infinite(), libMesh::DofObject::invalid_id, libMesh::Elem::is_vertex(), libMesh::LAGRANGE, libMesh::DofObject::n_comp_group(), libMesh::FEInterface::n_dofs(), libMesh::FEInterface::n_dofs_at_node(), libMesh::FEInterface::n_dofs_at_node_function(), libMesh::FEInterface::n_dofs_per_elem(), n_nodes, libMesh::DofObject::n_systems(), libMesh::FEType::order, libMesh::SUBDIVISION, libMesh::Elem::subdomain_id(), sys_number(), libMesh::Variable::type(), libMesh::Elem::type(), libMesh::DofObject::var_to_vg_and_offset(), and variable_group().

Referenced by dof_indices().

2222 {
2223  const VariableGroup & var = this->variable_group(vg);
2224 
2225  if (var.active_on_subdomain(elem.subdomain_id()))
2226  {
2227  const ElemType type = elem.type();
2228  const unsigned int sys_num = this->sys_number();
2229  const unsigned int dim = elem.dim();
2230 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2231  const bool is_inf = elem.infinite();
2232 #endif
2233 
2234  // Increase the polynomial order on p refined elements
2235  FEType fe_type = var.type();
2236  fe_type.order = static_cast<Order>(fe_type.order + p_level);
2237 
2238  const bool extra_hanging_dofs =
2240 
2241 #ifdef DEBUG
2242  // The number of dofs per element is non-static for subdivision FE
2243  if (fe_type.family == SUBDIVISION)
2244  tot_size += n_nodes;
2245  else
2246  tot_size += FEInterface::n_dofs(dim,fe_type,type);
2247 #endif
2248 
2249  const FEInterface::n_dofs_at_node_ptr ndan =
2251 
2252  // Get the node-based DOF numbers
2253  for (unsigned int n=0; n != n_nodes; n++)
2254  {
2255  const Node * node = nodes[n];
2256 
2257  // Cache the intermediate lookups that are common to every
2258  // component
2259 #ifdef DEBUG
2260  const std::pair<unsigned int, unsigned int>
2261  vg_and_offset = node->var_to_vg_and_offset(sys_num,v);
2262  libmesh_assert_equal_to (vg, vg_and_offset.first);
2263  libmesh_assert_equal_to (vig, vg_and_offset.second);
2264 #endif
2265  const unsigned int n_comp = node->n_comp_group(sys_num,vg);
2266 
2267  // There is a potential problem with h refinement. Imagine a
2268  // quad9 that has a linear FE on it. Then, on the hanging side,
2269  // it can falsely identify a DOF at the mid-edge node. This is why
2270  // we go through FEInterface instead of node->n_comp() directly.
2271  const unsigned int nc =
2272 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2273  is_inf ?
2274  FEInterface::n_dofs_at_node(dim, fe_type, type, n) :
2275 #endif
2276  ndan (type, fe_type.order, n);
2277 
2278  // If this is a non-vertex on a hanging node with extra
2279  // degrees of freedom, we use the non-vertex dofs (which
2280  // come in reverse order starting from the end, to
2281  // simplify p refinement)
2282  if (extra_hanging_dofs && !elem.is_vertex(n))
2283  {
2284  const int dof_offset = n_comp - nc;
2285 
2286  // We should never have fewer dofs than necessary on a
2287  // node unless we're getting indices on a parent element,
2288  // and we should never need the indices on such a node
2289  if (dof_offset < 0)
2290  {
2291  libmesh_assert(!elem.active());
2292  di.resize(di.size() + nc, DofObject::invalid_id);
2293  }
2294  else
2295  for (int i=n_comp-1; i>=dof_offset; i--)
2296  {
2297  const dof_id_type d =
2298  node->dof_number(sys_num, vg, vig, i, n_comp);
2299  libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2300  di.push_back(d);
2301  }
2302  }
2303  // If this is a vertex or an element without extra hanging
2304  // dofs, our dofs come in forward order coming from the
2305  // beginning
2306  else
2307  for (unsigned int i=0; i<nc; i++)
2308  {
2309  const dof_id_type d =
2310  node->dof_number(sys_num, vg, vig, i, n_comp);
2311  libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2312  di.push_back(d);
2313  }
2314  }
2315 
2316  // If there are any element-based DOF numbers, get them
2317  const unsigned int nc = FEInterface::n_dofs_per_elem(dim,
2318  fe_type,
2319  type);
2320  // We should never have fewer dofs than necessary on an
2321  // element unless we're getting indices on a parent element,
2322  // and we should never need those indices
2323  if (nc != 0)
2324  {
2325  const unsigned int n_comp = elem.n_comp_group(sys_num,vg);
2326  if (elem.n_systems() > sys_num && nc <= n_comp)
2327  {
2328  for (unsigned int i=0; i<nc; i++)
2329  {
2330  const dof_id_type d =
2331  elem.dof_number(sys_num, vg, vig, i, n_comp);
2332  libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2333 
2334  di.push_back(d);
2335  }
2336  }
2337  else
2338  {
2339  libmesh_assert(!elem.active() || fe_type.family == LAGRANGE || fe_type.family == SUBDIVISION);
2340  di.resize(di.size() + nc, DofObject::invalid_id);
2341  }
2342  }
2343  }
2344 }
static unsigned int n_dofs_per_elem(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:504
static unsigned int n_dofs(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:454
unsigned int sys_number() const
Definition: dof_map.h:1744
const dof_id_type n_nodes
Definition: tecplot_io.C:68
static bool extra_hanging_dofs(const FEType &fe_t)
static const dof_id_type invalid_id
Definition: dof_object.h:347
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:1752
static n_dofs_at_node_ptr n_dofs_at_node_function(const unsigned int dim, const FEType &fe_t)
Definition: fe_interface.C:493
static unsigned int n_dofs_at_node(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int n)
Definition: fe_interface.C:473
unsigned int(* n_dofs_at_node_ptr)(const ElemType, const Order, const unsigned int)
Definition: fe_interface.h:114
uint8_t dof_id_type
Definition: id_types.h:64

◆ add_adjoint_constraint_row()

void libMesh::DofMap::add_adjoint_constraint_row ( const unsigned int  qoi_index,
const dof_id_type  dof_number,
const DofConstraintRow constraint_row,
const Number  constraint_rhs,
const bool  forbid_constraint_overwrite 
)

Adds a copy of the user-defined row to the constraint matrix, using an inhomogeneous right-hand-side for the adjoint constraint equation.

forbid_constraint_overwrite here only tests for overwriting the rhs. This method should only be used when an equivalent constraint (with a potentially different rhs) already exists for the primal problem.

Definition at line 1373 of file dof_map_constraints.C.

1378 {
1379  // Optionally allow the user to overwrite constraints. Defaults to false.
1380  if (forbid_constraint_overwrite)
1381  {
1382  if (!this->is_constrained_dof(dof_number))
1383  libmesh_error_msg("ERROR: DOF " << dof_number << " has no corresponding primal constraint!");
1384 #ifndef NDEBUG
1385  // No way to do this without a non-normalized tolerance?
1386 
1387  // // If the user passed in more than just the rhs, let's check the
1388  // // coefficients for consistency
1389  // if (!constraint_row.empty())
1390  // {
1391  // DofConstraintRow row = _dof_constraints[dof_number];
1392  // for (const auto & pr : row)
1393  // libmesh_assert(constraint_row.find(pr.first)->second == pr.second);
1394  // }
1395  //
1396  // if (_adjoint_constraint_values[qoi_index].find(dof_number) !=
1397  // _adjoint_constraint_values[qoi_index].end())
1398  // libmesh_assert_equal_to(_adjoint_constraint_values[qoi_index][dof_number],
1399  // constraint_rhs);
1400 
1401 #endif
1402  }
1403 
1404  // Creates the map of rhs values if it doesn't already exist; then
1405  // adds the current value to that map
1406 
1407  // We don't get insert_or_assign until C++17 so we make do.
1408  std::pair<DofConstraintValueMap::iterator, bool> rhs_it =
1409  _adjoint_constraint_values[qoi_index].insert(std::make_pair(dof_number,
1410  constraint_rhs));
1411  if (!rhs_it.second)
1412  rhs_it.first->second = constraint_rhs;
1413 }
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1691
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1829

◆ add_adjoint_dirichlet_boundary()

void libMesh::DofMap::add_adjoint_dirichlet_boundary ( const DirichletBoundary dirichlet_boundary,
unsigned int  q 
)

Adds a copy of the specified Dirichlet boundary to the system, corresponding to the adjoint problem defined by Quantity of Interest q.

Definition at line 4279 of file dof_map_constraints.C.

4281 {
4282  unsigned int old_size = cast_int<unsigned int>
4284  for (unsigned int i = old_size; i <= qoi_index; ++i)
4286 
4287  _adjoint_dirichlet_boundaries[qoi_index]->push_back
4288  (new DirichletBoundary(dirichlet_boundary));
4289 }
Class for specifying Dirichlet boundary conditions as constraints.
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1727

◆ add_algebraic_ghosting_functor()

void libMesh::DofMap::add_algebraic_ghosting_functor ( GhostingFunctor evaluable_functor,
bool  to_mesh = true 
)

Adds a functor which can specify algebraic ghosting requirements for use with distributed vectors. Degrees of freedom on other processors which match the elements and variables returned by these functors will be added to the send_list, and the elements on other processors will be ghosted on a distributed mesh, so that the elements can always be found and the solutions on them will always be evaluable.

GhostingFunctor memory must be managed by the code which calls this function; the GhostingFunctor lifetime is expected to extend until either the functor is removed or the DofMap is destructed.

When to_mesh is true, the coupling_functor is also added to our associated mesh, to ensure that evaluable elements do not get lost during mesh distribution. (if evaluable elements were already lost there's no getting them back after the fact, sorry)

If to_mesh is false, no change to mesh ghosting is made; the Mesh must already have ghosting functor(s) specifying a superset of evaluable_functor or this is a horrible bug.

Definition at line 1829 of file dof_map.C.

References _algebraic_ghosting_functors, _mesh, and libMesh::MeshBase::add_ghosting_functor().

Referenced by add_default_ghosting(), clear(), and DofMap().

1831 {
1832  _algebraic_ghosting_functors.insert(&evaluable_functor);
1833  if (to_mesh)
1834  _mesh.add_ghosting_functor(evaluable_functor);
1835 }
std::set< GhostingFunctor * > _algebraic_ghosting_functors
Definition: dof_map.h:1605
MeshBase & _mesh
Definition: dof_map.h:1518
void add_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: mesh_base.h:823

◆ add_constraint_row() [1/2]

void libMesh::DofMap::add_constraint_row ( const dof_id_type  dof_number,
const DofConstraintRow constraint_row,
const Number  constraint_rhs,
const bool  forbid_constraint_overwrite 
)

Adds a copy of the user-defined row to the constraint matrix, using an inhomogeneous right-hand-side for the constraint equation.

Definition at line 1350 of file dof_map_constraints.C.

Referenced by add_constraint_row().

1354 {
1355  // Optionally allow the user to overwrite constraints. Defaults to false.
1356  if (forbid_constraint_overwrite)
1357  if (this->is_constrained_dof(dof_number))
1358  libmesh_error_msg("ERROR: DOF " << dof_number << " was already constrained!");
1359 
1360  // We don't get insert_or_assign until C++17 so we make do.
1361  std::pair<DofConstraints::iterator, bool> it =
1362  _dof_constraints.insert(std::make_pair(dof_number, constraint_row));
1363  if (!it.second)
1364  it.first->second = constraint_row;
1365 
1366  std::pair<DofConstraintValueMap::iterator, bool> rhs_it =
1367  _primal_constraint_values.insert(std::make_pair(dof_number, constraint_rhs));
1368  if (!rhs_it.second)
1369  rhs_it.first->second = constraint_rhs;
1370 }
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1829
DofConstraints _dof_constraints
Definition: dof_map.h:1687
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1689

◆ add_constraint_row() [2/2]

void libMesh::DofMap::add_constraint_row ( const dof_id_type  dof_number,
const DofConstraintRow constraint_row,
const bool  forbid_constraint_overwrite = true 
)
inline

Adds a copy of the user-defined row to the constraint matrix, using a homogeneous right-hand-side for the constraint equation. By default, produces an error if the DOF was already constrained.

Definition at line 894 of file dof_map.h.

References add_constraint_row().

897  { add_constraint_row(dof_number, constraint_row, 0., forbid_constraint_overwrite); }
void add_constraint_row(const dof_id_type dof_number, const DofConstraintRow &constraint_row, const Number constraint_rhs, const bool forbid_constraint_overwrite)

◆ add_constraints_to_send_list()

void libMesh::DofMap::add_constraints_to_send_list ( )
private

Adds entries to the _send_list vector corresponding to DoFs which are dependencies for constraint equations on the current processor.

Definition at line 4163 of file dof_map_constraints.C.

4164 {
4165  // This function must be run on all processors at once
4166  parallel_object_only();
4167 
4168  // Return immediately if there's nothing to gather
4169  if (this->n_processors() == 1)
4170  return;
4171 
4172  // We might get to return immediately if none of the processors
4173  // found any constraints
4174  unsigned int has_constraints = !_dof_constraints.empty();
4175  this->comm().max(has_constraints);
4176  if (!has_constraints)
4177  return;
4178 
4179  for (const auto & i : _dof_constraints)
4180  {
4181  dof_id_type constrained_dof = i.first;
4182 
4183  // We only need the dependencies of our own constrained dofs
4184  if (!this->local_index(constrained_dof))
4185  continue;
4186 
4187  const DofConstraintRow & constraint_row = i.second;
4188  for (const auto & j : constraint_row)
4189  {
4190  dof_id_type constraint_dependency = j.first;
4191 
4192  // No point in adding one of our own dofs to the send_list
4193  if (this->local_index(constraint_dependency))
4194  continue;
4195 
4196  _send_list.push_back(constraint_dependency);
4197  }
4198  }
4199 }
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1547
const Parallel::Communicator & comm() const
processor_id_type n_processors() const
DofConstraints _dof_constraints
Definition: dof_map.h:1687
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
Definition: dof_map.h:97
uint8_t dof_id_type
Definition: id_types.h:64
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:738

◆ add_coupling_functor()

void libMesh::DofMap::add_coupling_functor ( GhostingFunctor coupling_functor,
bool  to_mesh = true 
)

Adds a functor which can specify coupling requirements for creation of sparse matrices. Degree of freedom pairs which match the elements and variables returned by these functors will be added to the sparsity pattern, and the degrees of freedom which live on other processors will be added to the send_list for use on ghosted vectors, and the elements which live on other processors will be ghosted on a distributed mesh.

GhostingFunctor memory must be managed by the code which calls this function; the GhostingFunctor lifetime is expected to extend until either the functor is removed or the DofMap is destructed.

When to_mesh is true, the coupling_functor is also added to our associated mesh, to ensure that coupled elements do not get lost during mesh distribution. (if coupled elements were already lost there's no getting them back after the fact, sorry)

If to_mesh is false, no change to mesh ghosting is made; the Mesh must already have ghosting functor(s) specifying a superset of coupling_functor or this is a horrible bug.

Definition at line 1809 of file dof_map.C.

References _coupling_functors, _mesh, and libMesh::MeshBase::add_ghosting_functor().

Referenced by add_default_ghosting(), clear(), and DofMap().

1811 {
1812  _coupling_functors.insert(&coupling_functor);
1813  if (to_mesh)
1814  _mesh.add_ghosting_functor(coupling_functor);
1815 }
std::set< GhostingFunctor * > _coupling_functors
Definition: dof_map.h:1618
MeshBase & _mesh
Definition: dof_map.h:1518
void add_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: mesh_base.h:823

◆ add_default_ghosting()

void libMesh::DofMap::add_default_ghosting ( )

Add the default functor(s) for coupling and algebraic ghosting. User-added ghosting functors will be unaffected.

Definition at line 1800 of file dof_map.C.

References add_algebraic_ghosting_functor(), add_coupling_functor(), default_algebraic_ghosting(), and default_coupling().

Referenced by libMesh::EquationSystems::enable_default_ghosting().

1801 {
1802  this->add_coupling_functor(this->default_coupling());
1804 }
DefaultCoupling & default_coupling()
Definition: dof_map.h:329
DefaultCoupling & default_algebraic_ghosting()
Definition: dof_map.h:379
void add_coupling_functor(GhostingFunctor &coupling_functor, bool to_mesh=true)
Definition: dof_map.C:1809
void add_algebraic_ghosting_functor(GhostingFunctor &evaluable_functor, bool to_mesh=true)
Definition: dof_map.C:1829

◆ add_dirichlet_boundary()

void libMesh::DofMap::add_dirichlet_boundary ( const DirichletBoundary dirichlet_boundary)

Adds a copy of the specified Dirichlet boundary to the system.

Definition at line 4273 of file dof_map_constraints.C.

Referenced by libMesh::DifferentiableSystem::add_dot_var_dirichlet_bcs().

4274 {
4275  _dirichlet_boundaries->push_back(new DirichletBoundary(dirichlet_boundary));
4276 }
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Definition: dof_map.h:1721
Class for specifying Dirichlet boundary conditions as constraints.

◆ add_neighbors_to_send_list()

void libMesh::DofMap::add_neighbors_to_send_list ( MeshBase mesh)
private

Adds entries to the _send_list vector corresponding to DoFs on elements neighboring the current processor.

Definition at line 1499 of file dof_map.C.

References _send_list, algebraic_ghosting_functors_begin(), algebraic_ghosting_functors_end(), coupling_functors_begin(), coupling_functors_end(), dof_indices(), local_index(), merge_ghost_functor_outputs(), mesh, n_variables(), libMesh::ParallelObject::processor_id(), and libMesh::DofObject::processor_id().

Referenced by distribute_dofs().

1500 {
1501  LOG_SCOPE("add_neighbors_to_send_list()", "DofMap");
1502 
1503  const unsigned int n_var = this->n_variables();
1504 
1505  MeshBase::const_element_iterator local_elem_it
1506  = mesh.active_local_elements_begin();
1507  const MeshBase::const_element_iterator local_elem_end
1508  = mesh.active_local_elements_end();
1509 
1510  GhostingFunctor::map_type elements_to_send;
1511 
1512  // Man, I wish we had guaranteed unique_ptr availability...
1513  std::set<CouplingMatrix *> temporary_coupling_matrices;
1514 
1515  // We need to add dofs to the send list if they've been directly
1516  // requested by an algebraic ghosting functor or they've been
1517  // indirectly requested by a coupling functor.
1518  this->merge_ghost_functor_outputs(elements_to_send,
1519  temporary_coupling_matrices,
1522  local_elem_it, local_elem_end, mesh.processor_id());
1523 
1524  this->merge_ghost_functor_outputs(elements_to_send,
1525  temporary_coupling_matrices,
1526  this->coupling_functors_begin(),
1527  this->coupling_functors_end(),
1528  local_elem_it, local_elem_end, mesh.processor_id());
1529 
1530  // Making a list of non-zero coupling matrix columns is an
1531  // O(N_var^2) operation. We cache it so we only have to do it once
1532  // per CouplingMatrix and not once per element.
1533  std::map<const CouplingMatrix *, std::vector<unsigned int>>
1534  column_variable_lists;
1535 
1536  for (auto & pr : elements_to_send)
1537  {
1538  const Elem * const partner = pr.first;
1539 
1540  // We asked ghosting functors not to give us local elements
1541  libmesh_assert_not_equal_to
1542  (partner->processor_id(), this->processor_id());
1543 
1544  const CouplingMatrix * ghost_coupling = pr.second;
1545 
1546  // Loop over any present coupling matrix column variables if we
1547  // have a coupling matrix, or just add all variables to
1548  // send_list if not.
1549  if (ghost_coupling)
1550  {
1551  libmesh_assert_equal_to (ghost_coupling->size(), n_var);
1552 
1553  // Try to find a cached list of column variables.
1554  std::map<const CouplingMatrix *, std::vector<unsigned int>>::const_iterator
1555  column_variable_list = column_variable_lists.find(ghost_coupling);
1556 
1557  // If we didn't find it, then we need to create it.
1558  if (column_variable_list == column_variable_lists.end())
1559  {
1560  std::pair<std::map<const CouplingMatrix *, std::vector<unsigned int>>::iterator, bool>
1561  inserted_variable_list_pair = column_variable_lists.insert(std::make_pair(ghost_coupling,
1562  std::vector<unsigned int>()));
1563  column_variable_list = inserted_variable_list_pair.first;
1564 
1565  std::vector<unsigned int> & new_variable_list =
1566  inserted_variable_list_pair.first->second;
1567 
1568  std::vector<unsigned char> has_variable(n_var, false);
1569 
1570  for (unsigned int vi = 0; vi != n_var; ++vi)
1571  {
1572  ConstCouplingRow ccr(vi, *ghost_coupling);
1573 
1574  for (const auto & vj : ccr)
1575  has_variable[vj] = true;
1576  }
1577  for (unsigned int vj = 0; vj != n_var; ++vj)
1578  {
1579  if (has_variable[vj])
1580  new_variable_list.push_back(vj);
1581  }
1582  }
1583 
1584  const std::vector<unsigned int> & variable_list =
1585  column_variable_list->second;
1586 
1587  for (const auto & vj : variable_list)
1588  {
1589  std::vector<dof_id_type> di;
1590  this->dof_indices (partner, di, vj);
1591 
1592  // Insert the remote DOF indices into the send list
1593  for (auto d : di)
1594  if (!this->local_index(d))
1595  _send_list.push_back(d);
1596  }
1597  }
1598  else
1599  {
1600  std::vector<dof_id_type> di;
1601  this->dof_indices (partner, di);
1602 
1603  // Insert the remote DOF indices into the send list
1604  for (const auto & dof : di)
1605  if (!this->local_index(dof))
1606  _send_list.push_back(dof);
1607  }
1608 
1609  }
1610 
1611  // We're now done with any merged coupling matrices we had to create.
1612  for (auto & mat : temporary_coupling_matrices)
1613  delete mat;
1614 
1615  //-------------------------------------------------------------------------
1616  // Our coupling functors added dofs from neighboring elements to the
1617  // send list, but we may still need to add non-local dofs from local
1618  // elements.
1619  //-------------------------------------------------------------------------
1620 
1621  // Loop over the active local elements, adding all active elements
1622  // that neighbor an active local element to the send list.
1623  for ( ; local_elem_it != local_elem_end; ++local_elem_it)
1624  {
1625  const Elem * elem = *local_elem_it;
1626 
1627  std::vector<dof_id_type> di;
1628  this->dof_indices (elem, di);
1629 
1630  // Insert the remote DOF indices into the send list
1631  for (const auto & dof : di)
1632  if (!this->local_index(dof))
1633  _send_list.push_back(dof);
1634  }
1635 }
std::set< GhostingFunctor * >::const_iterator coupling_functors_begin() const
Definition: dof_map.h:317
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition: dof_map.C:1930
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1547
MeshBase & mesh
unsigned int n_variables() const
Definition: dof_map.h:541
std::unordered_map< const Elem *, const CouplingMatrix * > map_type
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_end() const
Definition: dof_map.h:373
std::set< GhostingFunctor * >::const_iterator coupling_functors_end() const
Definition: dof_map.h:323
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_begin() const
Definition: dof_map.h:367
processor_id_type processor_id() const
static void merge_ghost_functor_outputs(GhostingFunctor::map_type &elements_to_ghost, std::set< CouplingMatrix *> &temporary_coupling_matrices, const std::set< GhostingFunctor *>::iterator &gf_begin, const std::set< GhostingFunctor *>::iterator &gf_end, const MeshBase::const_element_iterator &elems_begin, const MeshBase::const_element_iterator &elems_end, processor_id_type p)
Definition: dof_map.C:1432
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:738

◆ add_periodic_boundary() [1/2]

void libMesh::DofMap::add_periodic_boundary ( const PeriodicBoundaryBase periodic_boundary)

Adds a copy of the specified periodic boundary to the system.

Definition at line 4393 of file dof_map_constraints.C.

References libMesh::PeriodicBoundaryBase::clone(), libMesh::PeriodicBoundaryBase::merge(), libMesh::PeriodicBoundaryBase::myboundary, and libMesh::PeriodicBoundaryBase::pairedboundary.

4394 {
4395  // See if we already have a periodic boundary associated myboundary...
4396  PeriodicBoundaryBase * existing_boundary = _periodic_boundaries->boundary(periodic_boundary.myboundary);
4397 
4398  if (existing_boundary == nullptr)
4399  {
4400  // ...if not, clone the input (and its inverse) and add them to the PeriodicBoundaries object
4401  PeriodicBoundaryBase * boundary = periodic_boundary.clone().release();
4402  PeriodicBoundaryBase * inverse_boundary = periodic_boundary.clone(PeriodicBoundaryBase::INVERSE).release();
4403 
4404  // _periodic_boundaries takes ownership of the pointers
4405  _periodic_boundaries->insert(std::make_pair(boundary->myboundary, boundary));
4406  _periodic_boundaries->insert(std::make_pair(inverse_boundary->myboundary, inverse_boundary));
4407  }
4408  else
4409  {
4410  // ...otherwise, merge this object's variable IDs with the existing boundary object's.
4411  existing_boundary->merge(periodic_boundary);
4412 
4413  // Do the same merging process for the inverse boundary. Note: the inverse better already exist!
4414  PeriodicBoundaryBase * inverse_boundary = _periodic_boundaries->boundary(periodic_boundary.pairedboundary);
4415  libmesh_assert(inverse_boundary);
4416  inverse_boundary->merge(periodic_boundary);
4417  }
4418 }
void merge(const PeriodicBoundaryBase &pb)
virtual std::unique_ptr< PeriodicBoundaryBase > clone(TransformationType t=FORWARD) const =0
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Definition: dof_map.h:1707
Base class for all PeriodicBoundary implementations.

◆ add_periodic_boundary() [2/2]

void libMesh::DofMap::add_periodic_boundary ( const PeriodicBoundaryBase boundary,
const PeriodicBoundaryBase inverse_boundary 
)

Add a periodic boundary pair

Parameters
boundary- primary boundary
inverse_boundary- inverse boundary

Definition at line 4423 of file dof_map_constraints.C.

References libMesh::PeriodicBoundaryBase::clone(), libMesh::PeriodicBoundaryBase::myboundary, and libMesh::PeriodicBoundaryBase::pairedboundary.

4425 {
4426  libmesh_assert_equal_to (boundary.myboundary, inverse_boundary.pairedboundary);
4427  libmesh_assert_equal_to (boundary.pairedboundary, inverse_boundary.myboundary);
4428 
4429  // Allocate copies on the heap. The _periodic_boundaries object will manage this memory.
4430  // Note: this also means that the copy constructor for the PeriodicBoundary (or user class
4431  // derived therefrom) must be implemented!
4432  // PeriodicBoundary * p_boundary = new PeriodicBoundary(boundary);
4433  // PeriodicBoundary * p_inverse_boundary = new PeriodicBoundary(inverse_boundary);
4434 
4435  // We can't use normal copy construction since this leads to slicing with derived classes.
4436  // Use clone() "virtual constructor" instead. But, this *requires* user to override the clone()
4437  // method. Note also that clone() allocates memory. In this case, the _periodic_boundaries object
4438  // takes responsibility for cleanup.
4439  PeriodicBoundaryBase * p_boundary = boundary.clone().release();
4440  PeriodicBoundaryBase * p_inverse_boundary = inverse_boundary.clone().release();
4441 
4442  // Add the periodic boundary and its inverse to the PeriodicBoundaries data structure. The
4443  // PeriodicBoundaries data structure takes ownership of the pointers.
4444  _periodic_boundaries->insert(std::make_pair(p_boundary->myboundary, p_boundary));
4445  _periodic_boundaries->insert(std::make_pair(p_inverse_boundary->myboundary, p_inverse_boundary));
4446 }
virtual std::unique_ptr< PeriodicBoundaryBase > clone(TransformationType t=FORWARD) const =0
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Definition: dof_map.h:1707
Base class for all PeriodicBoundary implementations.

◆ add_variable_group()

void libMesh::DofMap::add_variable_group ( const VariableGroup var_group)

Add an unknown of order order and finite element type type to the system of equations. Add a group of unknowns of order order and finite element type type to the system of equations.

Definition at line 245 of file dof_map.C.

References _variable_group_numbers, _variable_groups, _variables, and libMesh::VariableGroup::n_variables().

246 {
247  const unsigned int vg = cast_int<unsigned int>(_variable_groups.size());
248 
249  _variable_groups.push_back(var_group);
250 
251  VariableGroup & new_var_group = _variable_groups.back();
252 
253  for (unsigned int var=0; var<new_var_group.n_variables(); var++)
254  {
255  _variables.push_back (new_var_group(var));
256  _variable_group_numbers.push_back (vg);
257  }
258 }
std::vector< VariableGroup > _variable_groups
Definition: dof_map.h:1503
std::vector< Variable > _variables
Definition: dof_map.h:1498
std::vector< unsigned int > _variable_group_numbers
Definition: dof_map.h:1508

◆ algebraic_ghosting_functors_begin()

std::set<GhostingFunctor *>::const_iterator libMesh::DofMap::algebraic_ghosting_functors_begin ( ) const
inline

Beginning of range of algebraic ghosting functors

Definition at line 367 of file dof_map.h.

References _algebraic_ghosting_functors.

Referenced by add_neighbors_to_send_list().

368  { return _algebraic_ghosting_functors.begin(); }
std::set< GhostingFunctor * > _algebraic_ghosting_functors
Definition: dof_map.h:1605

◆ algebraic_ghosting_functors_end()

std::set<GhostingFunctor *>::const_iterator libMesh::DofMap::algebraic_ghosting_functors_end ( ) const
inline

End of range of algebraic ghosting functors

Definition at line 373 of file dof_map.h.

References _algebraic_ghosting_functors.

Referenced by add_neighbors_to_send_list().

374  { return _algebraic_ghosting_functors.end(); }
std::set< GhostingFunctor * > _algebraic_ghosting_functors
Definition: dof_map.h:1605

◆ all_semilocal_indices()

bool libMesh::DofMap::all_semilocal_indices ( const std::vector< dof_id_type > &  dof_indices) const
Returns
true if all degree of freedom indices in dof_indices are either local indices or in the send_list.
Note
This is an O(logN) operation for a send_list of size N; we don't cache enough information for O(1) right now.

Definition at line 2400 of file dof_map.C.

References semilocal_index().

Referenced by is_evaluable().

2401 {
2402  // We're all semilocal unless we find a counterexample
2403  for (const auto & di : dof_indices_in)
2404  if (!this->semilocal_index(di))
2405  return false;
2406 
2407  return true;
2408 }
bool semilocal_index(dof_id_type dof_index) const
Definition: dof_map.C:2384

◆ allgather_recursive_constraints()

void libMesh::DofMap::allgather_recursive_constraints ( MeshBase mesh)

Gathers constraint equation dependencies from other processors

Definition at line 2595 of file dof_map_constraints.C.

References libMesh::MeshBase::active_not_local_elements_begin(), libMesh::MeshBase::active_not_local_elements_end(), libMesh::as_range(), data, libMesh::DofObject::dof_number(), libMesh::DofObject::id(), libMesh::index_range(), libMesh::MeshBase::is_serial(), libMesh::libmesh_isnan(), mesh, libMesh::DofObject::n_comp(), n_nodes, n_vars, libMesh::DofObject::n_vars(), libMesh::MeshBase::node_ptr(), libMesh::DofObject::processor_id(), libMesh::Parallel::pull_parallel_vector_data(), libMesh::Parallel::push_parallel_vector_data(), libMesh::Real, libMesh::TypeVector< T >::size(), and libMesh::Parallel::wait().

2596 {
2597  // This function must be run on all processors at once
2598  parallel_object_only();
2599 
2600  // Return immediately if there's nothing to gather
2601  if (this->n_processors() == 1)
2602  return;
2603 
2604  // We might get to return immediately if none of the processors
2605  // found any constraints
2606  unsigned int has_constraints = !_dof_constraints.empty()
2607 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2608  || !_node_constraints.empty()
2609 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
2610  ;
2611  this->comm().max(has_constraints);
2612  if (!has_constraints)
2613  return;
2614 
2615  // If we have heterogenous adjoint constraints we need to
2616  // communicate those too.
2617  const unsigned int max_qoi_num =
2618  _adjoint_constraint_values.empty() ?
2619  0 : _adjoint_constraint_values.rbegin()->first;
2620 
2621  // We might have calculated constraints for constrained dofs
2622  // which have support on other processors.
2623  // Push these out first.
2624  {
2625  std::map<processor_id_type, std::set<dof_id_type>> pushed_ids;
2626 
2627 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2628  std::map<processor_id_type, std::set<dof_id_type>> pushed_node_ids;
2629 #endif
2630 
2631  const unsigned int sys_num = this->sys_number();
2632 
2633  // Collect the constraints to push to each processor
2634  for (auto & elem : as_range(mesh.active_not_local_elements_begin(),
2636  {
2637  const unsigned short n_nodes = elem->n_nodes();
2638 
2639  // Just checking dof_indices on the foreign element isn't
2640  // enough. Consider a central hanging node between a coarse
2641  // Q2/Q1 element and its finer neighbors on a higher-ranked
2642  // processor. The coarse element's processor will own the node,
2643  // and will thereby own the pressure dof on that node, despite
2644  // the fact that that pressure dof doesn't directly exist on the
2645  // coarse element!
2646  //
2647  // So, we loop through dofs manually.
2648 
2649  {
2650  const unsigned int n_vars = elem->n_vars(sys_num);
2651  for (unsigned int v=0; v != n_vars; ++v)
2652  {
2653  const unsigned int n_comp = elem->n_comp(sys_num,v);
2654  for (unsigned int c=0; c != n_comp; ++c)
2655  {
2656  const unsigned int id =
2657  elem->dof_number(sys_num,v,c);
2658  if (this->is_constrained_dof(id))
2659  pushed_ids[elem->processor_id()].insert(id);
2660  }
2661  }
2662  }
2663 
2664  for (unsigned short n = 0; n != n_nodes; ++n)
2665  {
2666  const Node & node = elem->node_ref(n);
2667  const unsigned int n_vars = node.n_vars(sys_num);
2668  for (unsigned int v=0; v != n_vars; ++v)
2669  {
2670  const unsigned int n_comp = node.n_comp(sys_num,v);
2671  for (unsigned int c=0; c != n_comp; ++c)
2672  {
2673  const unsigned int id =
2674  node.dof_number(sys_num,v,c);
2675  if (this->is_constrained_dof(id))
2676  pushed_ids[elem->processor_id()].insert(id);
2677  }
2678  }
2679  }
2680 
2681 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2682  for (unsigned short n = 0; n != n_nodes; ++n)
2683  if (this->is_constrained_node(elem->node_ptr(n)))
2684  pushed_node_ids[elem->processor_id()].insert(elem->node_id(n));
2685 #endif
2686  }
2687 
2688  // Rewrite those id sets as vectors for sending and receiving,
2689  // then find the corresponding data for each id, then push it all.
2690  std::map<processor_id_type, std::vector<dof_id_type>>
2691  pushed_id_vecs, received_id_vecs;
2692  for (auto & p : pushed_ids)
2693  pushed_id_vecs[p.first].assign(p.second.begin(), p.second.end());
2694 
2695  std::map<processor_id_type, std::vector<std::vector<std::pair<dof_id_type,Real>>>>
2696  pushed_keys_vals, received_keys_vals;
2697  std::map<processor_id_type, std::vector<std::vector<Number>>> pushed_rhss, received_rhss;
2698  for (auto & p : pushed_id_vecs)
2699  {
2700  auto & keys_vals = pushed_keys_vals[p.first];
2701  keys_vals.reserve(p.second.size());
2702 
2703  auto & rhss = pushed_rhss[p.first];
2704  rhss.reserve(p.second.size());
2705  for (auto & pushed_id : p.second)
2706  {
2707  const DofConstraintRow & row = _dof_constraints[pushed_id];
2708  keys_vals.emplace_back(row.begin(), row.end());
2709 
2710  rhss.push_back(std::vector<Number>(max_qoi_num+1));
2711  std::vector<Number> & rhs = rhss.back();
2712  DofConstraintValueMap::const_iterator rhsit =
2713  _primal_constraint_values.find(pushed_id);
2714  rhs[max_qoi_num] =
2715  (rhsit == _primal_constraint_values.end()) ?
2716  0 : rhsit->second;
2717  for (unsigned int q = 0; q != max_qoi_num; ++q)
2718  {
2719  AdjointDofConstraintValues::const_iterator adjoint_map_it =
2721 
2722  if (adjoint_map_it == _adjoint_constraint_values.end())
2723  continue;
2724 
2725  const DofConstraintValueMap & constraint_map =
2726  adjoint_map_it->second;
2727 
2728  DofConstraintValueMap::const_iterator adj_rhsit =
2729  constraint_map.find(pushed_id);
2730 
2731  rhs[q] =
2732  (adj_rhsit == constraint_map.end()) ?
2733  0 : adj_rhsit->second;
2734  }
2735  }
2736  }
2737 
2738  auto ids_action_functor =
2739  [& received_id_vecs]
2740  (processor_id_type pid,
2741  const std::vector<dof_id_type> & data)
2742  {
2743  received_id_vecs[pid] = data;
2744  };
2745 
2747  (this->comm(), pushed_id_vecs, ids_action_functor);
2748 
2749  auto keys_vals_action_functor =
2750  [& received_keys_vals]
2751  (processor_id_type pid,
2752  const std::vector<std::vector<std::pair<dof_id_type,Real>>> & data)
2753  {
2754  received_keys_vals[pid] = data;
2755  };
2756 
2758  (this->comm(), pushed_keys_vals, keys_vals_action_functor);
2759 
2760  auto rhss_action_functor =
2761  [& received_rhss]
2762  (processor_id_type pid,
2763  const std::vector<std::vector<Number>> & data)
2764  {
2765  received_rhss[pid] = data;
2766  };
2767 
2769  (this->comm(), pushed_rhss, rhss_action_functor);
2770 
2771  // Now we have all the DofConstraint rows and rhs values received
2772  // from others, so add the DoF constraints that we've been sent
2773 
2774 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2775  std::map<processor_id_type, std::vector<dof_id_type>>
2776  pushed_node_id_vecs, received_node_id_vecs;
2777  for (auto & p : pushed_node_ids)
2778  pushed_node_id_vecs[p.first].assign(p.second.begin(), p.second.end());
2779 
2780  std::map<processor_id_type, std::vector<std::vector<std::pair<dof_id_type,Real>>>>
2781  pushed_node_keys_vals, received_node_keys_vals;
2782  std::map<processor_id_type, std::vector<Point>> pushed_offsets, received_offsets;
2783 
2784  for (auto & p : pushed_node_id_vecs)
2785  {
2786  auto & node_keys_vals = pushed_node_keys_vals[p.first];
2787  node_keys_vals.reserve(p.second.size());
2788 
2789  auto & offsets = pushed_offsets[p.first];
2790  offsets.reserve(p.second.size());
2791 
2792  for (auto & pushed_node_id : p.second)
2793  {
2794  const Node * node = mesh.node_ptr(pushed_node_id);
2795  NodeConstraintRow & row = _node_constraints[node].first;
2796  const std::size_t row_size = row.size();
2797  node_keys_vals.push_back
2798  (std::vector<std::pair<dof_id_type,Real>>());
2799  std::vector<std::pair<dof_id_type,Real>> & this_node_kv =
2800  node_keys_vals.back();
2801  this_node_kv.reserve(row_size);
2802  for (const auto & j : row)
2803  this_node_kv.push_back
2804  (std::make_pair(j.first->id(), j.second));
2805 
2806  offsets.push_back(_node_constraints[node].second);
2807  }
2808  }
2809 
2810  auto node_ids_action_functor =
2811  [& received_node_id_vecs]
2812  (processor_id_type pid,
2813  const std::vector<dof_id_type> & data)
2814  {
2815  received_node_id_vecs[pid] = data;
2816  };
2817 
2819  (this->comm(), pushed_node_id_vecs, node_ids_action_functor);
2820 
2821  auto node_keys_vals_action_functor =
2822  [& received_node_keys_vals]
2823  (processor_id_type pid,
2824  const std::vector<std::vector<std::pair<dof_id_type,Real>>> & data)
2825  {
2826  received_node_keys_vals[pid] = data;
2827  };
2828 
2830  (this->comm(), pushed_node_keys_vals,
2831  node_keys_vals_action_functor);
2832 
2833  auto node_offsets_action_functor =
2834  [& received_offsets]
2835  (processor_id_type pid,
2836  const std::vector<Point> & data)
2837  {
2838  received_offsets[pid] = data;
2839  };
2840 
2842  (this->comm(), pushed_offsets, node_offsets_action_functor);
2843 
2844 #endif
2845 
2846  // Add all the dof constraints that I've been sent
2847  for (auto & p : received_id_vecs)
2848  {
2849  const processor_id_type pid = p.first;
2850  const auto & pushed_ids_to_me = p.second;
2851  libmesh_assert(received_keys_vals.count(pid));
2852  libmesh_assert(received_rhss.count(pid));
2853  const auto & pushed_keys_vals_to_me = received_keys_vals.at(pid);
2854  const auto & pushed_rhss_to_me = received_rhss.at(pid);
2855 
2856  libmesh_assert_equal_to (pushed_ids_to_me.size(),
2857  pushed_keys_vals_to_me.size());
2858  libmesh_assert_equal_to (pushed_ids_to_me.size(),
2859  pushed_rhss_to_me.size());
2860 
2861  for (auto i : index_range(pushed_ids_to_me))
2862  {
2863  dof_id_type constrained = pushed_ids_to_me[i];
2864 
2865  // If we don't already have a constraint for this dof,
2866  // add the one we were sent
2867  if (!this->is_constrained_dof(constrained))
2868  {
2869  DofConstraintRow & row = _dof_constraints[constrained];
2870  for (auto & kv : pushed_keys_vals_to_me[i])
2871  row[kv.first] = kv.second;
2872 
2873  const Number primal_rhs = pushed_rhss_to_me[i][max_qoi_num];
2874 
2875  if (libmesh_isnan(primal_rhs))
2876  libmesh_assert(pushed_keys_vals_to_me[i].empty());
2877 
2878  if (primal_rhs != Number(0))
2879  _primal_constraint_values[constrained] = primal_rhs;
2880  else
2881  _primal_constraint_values.erase(constrained);
2882 
2883  for (unsigned int q = 0; q != max_qoi_num; ++q)
2884  {
2885  AdjointDofConstraintValues::iterator adjoint_map_it =
2887 
2888  const Number adj_rhs = pushed_rhss_to_me[i][q];
2889 
2890  if ((adjoint_map_it == _adjoint_constraint_values.end()) &&
2891  adj_rhs == Number(0))
2892  continue;
2893 
2894  if (adjoint_map_it == _adjoint_constraint_values.end())
2895  adjoint_map_it = _adjoint_constraint_values.insert
2896  (std::make_pair(q,DofConstraintValueMap())).first;
2897 
2898  DofConstraintValueMap & constraint_map =
2899  adjoint_map_it->second;
2900 
2901  if (adj_rhs != Number(0))
2902  constraint_map[constrained] = adj_rhs;
2903  else
2904  constraint_map.erase(constrained);
2905  }
2906  }
2907  }
2908  }
2909 
2910 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2911  // Add all the node constraints that I've been sent
2912  for (auto & p : received_node_id_vecs)
2913  {
2914  const processor_id_type pid = p.first;
2915  const auto & pushed_node_ids_to_me = p.second;
2916  libmesh_assert(received_node_keys_vals.count(pid));
2917  libmesh_assert(received_offsets.count(pid));
2918  const auto & pushed_node_keys_vals_to_me = received_node_keys_vals.at(pid);
2919  const auto & pushed_offsets_to_me = received_offsets.at(pid);
2920 
2921  libmesh_assert_equal_to (pushed_node_ids_to_me.size(),
2922  pushed_node_keys_vals_to_me.size());
2923  libmesh_assert_equal_to (pushed_node_ids_to_me.size(),
2924  pushed_offsets_to_me.size());
2925 
2926  for (auto i : index_range(pushed_node_ids_to_me))
2927  {
2928  dof_id_type constrained_id = pushed_node_ids_to_me[i];
2929 
2930  // If we don't already have a constraint for this node,
2931  // add the one we were sent
2932  const Node * constrained = mesh.node_ptr(constrained_id);
2933  if (!this->is_constrained_node(constrained))
2934  {
2935  NodeConstraintRow & row = _node_constraints[constrained].first;
2936  for (auto & kv : pushed_node_keys_vals_to_me[i])
2937  {
2938  const Node * key_node = mesh.node_ptr(kv.first);
2939  libmesh_assert(key_node);
2940  row[key_node] = kv.second;
2941  }
2942  _node_constraints[constrained].second = pushed_offsets_to_me[i];
2943  }
2944  }
2945  }
2946 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
2947  }
2948 
2949  // Now start checking for any other constraints we need
2950  // to know about, requesting them recursively.
2951 
2952  // Create sets containing the DOFs and nodes we already depend on
2953  typedef std::set<dof_id_type> DoF_RCSet;
2954  DoF_RCSet unexpanded_dofs;
2955 
2956  for (const auto & i : _dof_constraints)
2957  unexpanded_dofs.insert(i.first);
2958 
2959  // Gather all the dof constraints we need
2960  this->gather_constraints(mesh, unexpanded_dofs, false);
2961 
2962  // Gather all the node constraints we need
2963 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2964  typedef std::set<const Node *> Node_RCSet;
2965  Node_RCSet unexpanded_nodes;
2966 
2967  for (const auto & i : _node_constraints)
2968  unexpanded_nodes.insert(i.first);
2969 
2970  // We have to keep recursing while the unexpanded set is
2971  // nonempty on *any* processor
2972  bool unexpanded_set_nonempty = !unexpanded_nodes.empty();
2973  this->comm().max(unexpanded_set_nonempty);
2974 
2975  // We may be receiving packed_range sends out of order with
2976  // parallel_sync tags, so make sure they're received correctly.
2977  Parallel::MessageTag range_tag = this->comm().get_unique_tag(14142);
2978 
2979  while (unexpanded_set_nonempty)
2980  {
2981  // Let's make sure we don't lose sync in this loop.
2982  parallel_object_only();
2983 
2984  // Request sets
2985  Node_RCSet node_request_set;
2986 
2987  // Request sets to send to each processor
2988  std::map<processor_id_type, std::vector<dof_id_type>>
2989  requested_node_ids;
2990 
2991  // And the sizes of each
2992  std::map<processor_id_type, dof_id_type> node_ids_on_proc;
2993 
2994  // Fill (and thereby sort and uniq!) the main request sets
2995  for (const auto & i : unexpanded_nodes)
2996  {
2997  NodeConstraintRow & row = _node_constraints[i].first;
2998  for (const auto & j : row)
2999  {
3000  const Node * const node = j.first;
3001  libmesh_assert(node);
3002 
3003  // If it's non-local and we haven't already got a
3004  // constraint for it, we might need to ask for one
3005  if ((node->processor_id() != this->processor_id()) &&
3006  !_node_constraints.count(node))
3007  node_request_set.insert(node);
3008  }
3009  }
3010 
3011  // Clear the unexpanded constraint sets; we're about to expand
3012  // them
3013  unexpanded_nodes.clear();
3014 
3015  // Count requests by processor
3016  for (const auto & node : node_request_set)
3017  {
3018  libmesh_assert(node);
3019  libmesh_assert_less (node->processor_id(), this->n_processors());
3020  node_ids_on_proc[node->processor_id()]++;
3021  }
3022 
3023  for (processor_id_type p = 0; p != this->n_processors(); ++p)
3024  if (node_ids_on_proc.count(p))
3025  requested_node_ids[p].reserve(node_ids_on_proc[p]);
3026 
3027  // Prepare each processor's request set
3028  for (const auto & node : node_request_set)
3029  requested_node_ids[node->processor_id()].push_back(node->id());
3030 
3031  typedef std::vector<std::pair<dof_id_type, Real>> row_datum;
3032 
3033  // We may need to send nodes ahead of data about them
3034  std::vector<Parallel::Request> packed_range_sends;
3035 
3036  auto node_row_gather_functor =
3037  [this,
3038  & mesh,
3039  & packed_range_sends,
3040  & range_tag]
3041  (processor_id_type pid,
3042  const std::vector<dof_id_type> & ids,
3043  std::vector<row_datum> & data)
3044  {
3045  // Do we need to keep track of requested nodes to send
3046  // later?
3047  const bool dist_mesh = !mesh.is_serial();
3048 
3049  // FIXME - this could be an unordered set, given a
3050  // hash<pointers> specialization
3051  std::set<const Node *> nodes_requested;
3052 
3053  // Fill those requests
3054  const std::size_t query_size = ids.size();
3055 
3056  data.resize(query_size);
3057  for (std::size_t i=0; i != query_size; ++i)
3058  {
3059  dof_id_type constrained_id = ids[i];
3060  const Node * constrained_node = mesh.node_ptr(constrained_id);
3061  if (_node_constraints.count(constrained_node))
3062  {
3063  const NodeConstraintRow & row = _node_constraints[constrained_node].first;
3064  std::size_t row_size = row.size();
3065  data[i].reserve(row_size);
3066  for (const auto & j : row)
3067  {
3068  const Node * node = j.first;
3069  data[i].push_back(std::make_pair(node->id(), j.second));
3070 
3071  // If we're not sure whether our send
3072  // destination already has this node, let's give
3073  // it a copy.
3074  if (node->processor_id() != pid && dist_mesh)
3075  nodes_requested.insert(node);
3076 
3077  // We can have 0 nodal constraint
3078  // coefficients, where no Lagrange constraint
3079  // exists but non-Lagrange basis constraints
3080  // might.
3081  // libmesh_assert(j.second);
3082  }
3083  }
3084  else
3085  {
3086  // We have to distinguish "constraint with no
3087  // constraining nodes" (e.g. due to user node
3088  // constraint equations) from "no constraint".
3089  // We'll use invalid_id for the latter.
3090  data[i].push_back
3091  (std::make_pair(DofObject::invalid_id, Real(0)));
3092  }
3093  }
3094 
3095  // Constraining nodes might not even exist on our
3096  // correspondant's subset of a distributed mesh, so let's
3097  // make them exist.
3098  if (dist_mesh)
3099  {
3100  packed_range_sends.push_back(Parallel::Request());
3101  this->comm().send_packed_range
3102  (pid, &mesh, nodes_requested.begin(), nodes_requested.end(),
3103  packed_range_sends.back(), range_tag);
3104  }
3105  };
3106 
3107  typedef Point node_rhs_datum;
3108 
3109  auto node_rhs_gather_functor =
3110  [this,
3111  & mesh]
3113  const std::vector<dof_id_type> & ids,
3114  std::vector<node_rhs_datum> & data)
3115  {
3116  // Fill those requests
3117  const std::size_t query_size = ids.size();
3118 
3119  data.resize(query_size);
3120  for (std::size_t i=0; i != query_size; ++i)
3121  {
3122  dof_id_type constrained_id = ids[i];
3123  const Node * constrained_node = mesh.node_ptr(constrained_id);
3124  if (_node_constraints.count(constrained_node))
3125  data[i] = _node_constraints[constrained_node].second;
3126  else
3127  data[i](0) = std::numeric_limits<Real>::quiet_NaN();
3128  }
3129  };
3130 
3131  auto node_row_action_functor =
3132  [this,
3133  & mesh,
3134  & range_tag,
3135  & unexpanded_nodes]
3136  (processor_id_type pid,
3137  const std::vector<dof_id_type> & ids,
3138  const std::vector<row_datum> & data)
3139  {
3140  // Before we act on any new constraint rows, we may need to
3141  // make sure we have all the nodes involved!
3142  if (!mesh.is_serial())
3143  this->comm().receive_packed_range
3145  (Node**)nullptr, range_tag);
3146 
3147  // Add any new constraint rows we've found
3148  const std::size_t query_size = ids.size();
3149 
3150  for (std::size_t i=0; i != query_size; ++i)
3151  {
3152  const dof_id_type constrained_id = ids[i];
3153 
3154  // An empty row is an constraint with an empty row; for
3155  // no constraint we use a "no row" placeholder
3156  if (data[i].empty())
3157  {
3158  const Node * constrained_node = mesh.node_ptr(constrained_id);
3159  NodeConstraintRow & row = _node_constraints[constrained_node].first;
3160  row.clear();
3161  }
3162  else if (data[i][0].first != DofObject::invalid_id)
3163  {
3164  const Node * constrained_node = mesh.node_ptr(constrained_id);
3165  NodeConstraintRow & row = _node_constraints[constrained_node].first;
3166  row.clear();
3167  for (auto & pair : data[i])
3168  {
3169  const Node * key_node =
3170  mesh.node_ptr(pair.first);
3171  libmesh_assert(key_node);
3172  row[key_node] = pair.second;
3173  }
3174 
3175  // And prepare to check for more recursive constraints
3176  unexpanded_nodes.insert(constrained_node);
3177  }
3178  }
3179  };
3180 
3181  auto node_rhs_action_functor =
3182  [this,
3183  & mesh]
3185  const std::vector<dof_id_type> & ids,
3186  const std::vector<node_rhs_datum> & data)
3187  {
3188  // Add rhs data for any new node constraint rows we've found
3189  const std::size_t query_size = ids.size();
3190 
3191  for (std::size_t i=0; i != query_size; ++i)
3192  {
3193  dof_id_type constrained_id = ids[i];
3194  const Node * constrained_node = mesh.node_ptr(constrained_id);
3195 
3196  if (!libmesh_isnan(data[i](0)))
3197  _node_constraints[constrained_node].second = data[i];
3198  else
3199  _node_constraints.erase(constrained_node);
3200  }
3201  };
3202 
3203  // Now request node constraint rows from other processors
3204  row_datum * node_row_ex = nullptr;
3206  (this->comm(), requested_node_ids, node_row_gather_functor,
3207  node_row_action_functor, node_row_ex);
3208 
3209  // And request node constraint right hand sides from other procesors
3210  node_rhs_datum * node_rhs_ex = nullptr;
3212  (this->comm(), requested_node_ids, node_rhs_gather_functor,
3213  node_rhs_action_functor, node_rhs_ex);
3214 
3215  Parallel::wait(packed_range_sends);
3216 
3217  // We have to keep recursing while the unexpanded set is
3218  // nonempty on *any* processor
3219  unexpanded_set_nonempty = !unexpanded_nodes.empty();
3220  this->comm().max(unexpanded_set_nonempty);
3221  }
3222 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
3223 }
void wait(std::vector< Request > &r)
Definition: request.C:213
bool is_constrained_node(const Node *node) const
Definition: dof_map.h:1812
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:833
A geometric point in (x,y,z) space associated with a DOF.
Definition: node.h:52
unsigned int n_comp(const unsigned int s, const unsigned int var) const
Definition: dof_object.h:803
void send_packed_range(const unsigned int dest_processor_id, const Context *context, Iter range_begin, const Iter range_end, const MessageTag &tag=no_tag) const
MeshBase & mesh
void gather_constraints(MeshBase &mesh, std::set< dof_id_type > &unexpanded_dofs, bool look_for_constrainees)
IntRange< std::size_t > index_range(const std::vector< T > &vec)
Definition: int_range.h:104
uint8_t processor_id_type
Definition: id_types.h:99
void receive_packed_range(const unsigned int dest_processor_id, Context *context, OutputIter out, const T *output_type, const MessageTag &tag=any_tag) const
const Parallel::Communicator & comm() const
MessageTag get_unique_tag(int tagvalue) const
Definition: communicator.C:201
const unsigned int n_vars
Definition: tecplot_io.C:69
unsigned int sys_number() const
Definition: dof_map.h:1744
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1691
processor_id_type n_processors() const
virtual bool is_serial() const
Definition: mesh_base.h:154
const dof_id_type n_nodes
Definition: tecplot_io.C:68
dof_id_type id() const
Definition: dof_object.h:655
void pull_parallel_vector_data(const Communicator &comm, const MapToVectors &queries, RequestContainer &reqs, GatherFunctor &gather_data, ActionFunctor &act_on_data, const datum *example)
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
Definition: dof_object.h:768
SimpleRange< I > as_range(const std::pair< I, I > &p)
Definition: simple_range.h:57
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1829
static const dof_id_type invalid_id
Definition: dof_object.h:347
DofConstraints _dof_constraints
Definition: dof_map.h:1687
An output iterator for use with packed_range functions.
virtual element_iterator active_not_local_elements_end()=0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
bool libmesh_isnan(float a)
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1689
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
Definition: dof_map.h:97
virtual element_iterator active_not_local_elements_begin()=0
std::map< const Node *, Real, std::less< const Node * >, Threads::scalable_allocator< std::pair< const Node *const, Real > > > NodeConstraintRow
Definition: dof_map.h:145
void push_parallel_vector_data(const Communicator &comm, const MapToVectors &data, RequestContainer &reqs, ActionFunctor &act_on_data)
IterBase * data
virtual const Node * node_ptr(const dof_id_type i) const =0
processor_id_type processor_id() const
Real size() const
Definition: type_vector.h:901
processor_id_type processor_id() const
Definition: dof_object.h:717
A geometric point in (x,y,z) space.
Definition: point.h:38
uint8_t dof_id_type
Definition: id_types.h:64
NodeConstraints _node_constraints
Definition: dof_map.h:1698

◆ attach_extra_send_list_function()

void libMesh::DofMap::attach_extra_send_list_function ( void(*)(std::vector< dof_id_type > &, void *)  func,
void *  context = nullptr 
)
inline

Attach a function pointer to use as a callback to populate the send_list with extra entries.

Definition at line 429 of file dof_map.h.

References _extra_send_list_context, and _extra_send_list_function.

void * _extra_send_list_context
Definition: dof_map.h:1579
void(* _extra_send_list_function)(std::vector< dof_id_type > &, void *)
Definition: dof_map.h:1574

◆ attach_extra_send_list_object()

void libMesh::DofMap::attach_extra_send_list_object ( DofMap::AugmentSendList asl)
inline

Attach an object to populate the send_list with extra entries. This should only add to the send list, but no checking is done to enforce this behavior.

This is an advanced function... use at your own peril!

Definition at line 420 of file dof_map.h.

References _augment_send_list.

421  {
422  _augment_send_list = &asl;
423  }
AugmentSendList * _augment_send_list
Definition: dof_map.h:1569

◆ attach_extra_sparsity_function()

void libMesh::DofMap::attach_extra_sparsity_function ( void(*)(SparsityPattern::Graph &sparsity, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *)  func,
void *  context = nullptr 
)
inline

Attach a function pointer to use as a callback to populate the sparsity pattern with extra entries.

Care must be taken that when adding entries they are sorted into the Rows

Further, you must modify n_nz and n_oz properly!

This is an advanced function... use at your own peril!

Definition at line 406 of file dof_map.h.

References _extra_sparsity_context, and _extra_sparsity_function.

void * _extra_sparsity_context
Definition: dof_map.h:1564
void(* _extra_sparsity_function)(SparsityPattern::Graph &, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *)
Definition: dof_map.h:1557

◆ attach_extra_sparsity_object()

void libMesh::DofMap::attach_extra_sparsity_object ( DofMap::AugmentSparsityPattern asp)
inline

Attach an object to use to populate the sparsity pattern with extra entries.

Care must be taken that when adding entries they are sorted into the Rows

Further, you must modify n_nz and n_oz properly!

This is an advanced function... use at your own peril!

Definition at line 391 of file dof_map.h.

References _augment_sparsity_pattern.

392  {
394  }
AugmentSparsityPattern * _augment_sparsity_pattern
Definition: dof_map.h:1552

◆ attach_matrix()

void libMesh::DofMap::attach_matrix ( SparseMatrix< Number > &  matrix)

Additional matrices may be handled with this DofMap. They are initialized to the same sparsity structure as the major matrix.

Definition at line 262 of file dof_map.C.

References _matrices, _n_nz, _n_oz, _sp, libMesh::SparseMatrix< T >::attach_dof_map(), libMesh::ParallelObject::comm(), libMesh::Parallel::Communicator::max(), libMesh::SparseMatrix< T >::need_full_sparsity_pattern(), need_full_sparsity_pattern, and libMesh::SparseMatrix< T >::update_sparsity_pattern().

Referenced by libMesh::EigenSystem::init_matrices(), and libMesh::ImplicitSystem::init_matrices().

263 {
264  parallel_object_only();
265 
266  // We shouldn't be trying to re-attach the same matrices repeatedly
267  libmesh_assert (std::find(_matrices.begin(), _matrices.end(),
268  &matrix) == _matrices.end());
269 
270  _matrices.push_back(&matrix);
271 
272  matrix.attach_dof_map (*this);
273 
274  // If we've already computed sparsity, then it's too late
275  // to wait for "compute_sparsity" to help with sparse matrix
276  // initialization, and we need to handle this matrix individually
277  bool computed_sparsity_already =
278  ((_n_nz && !_n_nz->empty()) ||
279  (_n_oz && !_n_oz->empty()));
280  this->comm().max(computed_sparsity_already);
281  if (computed_sparsity_already &&
283  {
284  // We'd better have already computed the full sparsity pattern
285  // if we need it here
286  libmesh_assert(need_full_sparsity_pattern);
287  libmesh_assert(_sp.get());
288 
289  matrix.update_sparsity_pattern (_sp->sparsity_pattern);
290  }
291 
292  if (matrix.need_full_sparsity_pattern())
294 }
std::unique_ptr< SparsityPattern::Build > _sp
Definition: dof_map.h:1630
const Parallel::Communicator & comm() const
std::vector< dof_id_type > * _n_nz
Definition: dof_map.h:1638
std::vector< dof_id_type > * _n_oz
Definition: dof_map.h:1644
bool need_full_sparsity_pattern
Definition: dof_map.h:1624
std::vector< SparseMatrix< Number > *> _matrices
Definition: dof_map.h:1525
void attach_dof_map(const DofMap &dof_map)
virtual bool need_full_sparsity_pattern() const
virtual void update_sparsity_pattern(const SparsityPattern::Graph &)

◆ block_size()

unsigned int libMesh::DofMap::block_size ( ) const
inline
Returns
The block size, if the variables are amenable to block storage. Otherwise 1.

Definition at line 562 of file dof_map.h.

References has_blocked_representation(), and n_variables().

563  {
564 #ifdef LIBMESH_ENABLE_BLOCKED_STORAGE
565  return (this->has_blocked_representation() ? this->n_variables() : 1);
566 #else
567  return 1;
568 #endif
569  }
unsigned int n_variables() const
Definition: dof_map.h:541
bool has_blocked_representation() const
Definition: dof_map.h:549

◆ build_constraint_matrix()

void libMesh::DofMap::build_constraint_matrix ( DenseMatrix< Number > &  C,
std::vector< dof_id_type > &  elem_dofs,
const bool  called_recursively = false 
) const
private

Build the constraint matrix C associated with the element degree of freedom indices elem_dofs. The optional parameter called_recursively should be left at the default value false. This is used to handle the special case of an element's degrees of freedom being constrained in terms of other, local degrees of freedom. The usual case is for an elements DOFs to be constrained by some other, external DOFs.

Definition at line 2346 of file dof_map_constraints.C.

References libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::resize(), and libMesh::DenseMatrix< T >::right_multiply().

2349 {
2350  LOG_SCOPE_IF("build_constraint_matrix()", "DofMap", !called_recursively);
2351 
2352  // Create a set containing the DOFs we already depend on
2353  typedef std::set<dof_id_type> RCSet;
2354  RCSet dof_set;
2355 
2356  bool we_have_constraints = false;
2357 
2358  // Next insert any other dofs the current dofs might be constrained
2359  // in terms of. Note that in this case we may not be done: Those
2360  // may in turn depend on others. So, we need to repeat this process
2361  // in that case until the system depends only on unconstrained
2362  // degrees of freedom.
2363  for (const auto & dof : elem_dofs)
2364  if (this->is_constrained_dof(dof))
2365  {
2366  we_have_constraints = true;
2367 
2368  // If the DOF is constrained
2369  DofConstraints::const_iterator
2370  pos = _dof_constraints.find(dof);
2371 
2372  libmesh_assert (pos != _dof_constraints.end());
2373 
2374  const DofConstraintRow & constraint_row = pos->second;
2375 
2376  // Constraint rows in p refinement may be empty
2377  //libmesh_assert (!constraint_row.empty());
2378 
2379  for (const auto & item : constraint_row)
2380  dof_set.insert (item.first);
2381  }
2382 
2383  // May be safe to return at this point
2384  // (but remember to stop the perflog)
2385  if (!we_have_constraints)
2386  return;
2387 
2388  for (const auto & dof : elem_dofs)
2389  dof_set.erase (dof);
2390 
2391  // If we added any DOFS then we need to do this recursively.
2392  // It is possible that we just added a DOF that is also
2393  // constrained!
2394  //
2395  // Also, we need to handle the special case of an element having DOFs
2396  // constrained in terms of other, local DOFs
2397  if (!dof_set.empty() || // case 1: constrained in terms of other DOFs
2398  !called_recursively) // case 2: constrained in terms of our own DOFs
2399  {
2400  const unsigned int old_size =
2401  cast_int<unsigned int>(elem_dofs.size());
2402 
2403  // Add new dependency dofs to the end of the current dof set
2404  elem_dofs.insert(elem_dofs.end(),
2405  dof_set.begin(), dof_set.end());
2406 
2407  // Now we can build the constraint matrix.
2408  // Note that resize also zeros for a DenseMatrix<Number>.
2409  C.resize (old_size,
2410  cast_int<unsigned int>(elem_dofs.size()));
2411 
2412  // Create the C constraint matrix.
2413  for (unsigned int i=0; i != old_size; i++)
2414  if (this->is_constrained_dof(elem_dofs[i]))
2415  {
2416  // If the DOF is constrained
2417  DofConstraints::const_iterator
2418  pos = _dof_constraints.find(elem_dofs[i]);
2419 
2420  libmesh_assert (pos != _dof_constraints.end());
2421 
2422  const DofConstraintRow & constraint_row = pos->second;
2423 
2424  // p refinement creates empty constraint rows
2425  // libmesh_assert (!constraint_row.empty());
2426 
2427  for (const auto & item : constraint_row)
2428  for (unsigned int j=0,
2429  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2430  j != n_elem_dofs; j++)
2431  if (elem_dofs[j] == item.first)
2432  C(i,j) = item.second;
2433  }
2434  else
2435  {
2436  C(i,i) = 1.;
2437  }
2438 
2439  // May need to do this recursively. It is possible
2440  // that we just replaced a constrained DOF with another
2441  // constrained DOF.
2442  DenseMatrix<Number> Cnew;
2443 
2444  this->build_constraint_matrix (Cnew, elem_dofs, true);
2445 
2446  if ((C.n() == Cnew.m()) &&
2447  (Cnew.n() == elem_dofs.size())) // If the constraint matrix
2448  C.right_multiply(Cnew); // is constrained...
2449 
2450  libmesh_assert_equal_to (C.n(), elem_dofs.size());
2451  }
2452 }
unsigned int m() const
virtual void right_multiply(const DenseMatrixBase< T > &M2) override
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1829
DofConstraints _dof_constraints
Definition: dof_map.h:1687
void resize(const unsigned int new_m, const unsigned int new_n)
Definition: dense_matrix.h:792
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
Definition: dof_map.h:97
void build_constraint_matrix(DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
unsigned int n() const

◆ build_constraint_matrix_and_vector()

void libMesh::DofMap::build_constraint_matrix_and_vector ( DenseMatrix< Number > &  C,
DenseVector< Number > &  H,
std::vector< dof_id_type > &  elem_dofs,
int  qoi_index = -1,
const bool  called_recursively = false 
) const
private

Build the constraint matrix C and the forcing vector H associated with the element degree of freedom indices elem_dofs. The optional parameter called_recursively should be left at the default value false. This is used to handle the special case of an element's degrees of freedom being constrained in terms of other, local degrees of freedom. The usual case is for an elements DOFs to be constrained by some other, external DOFs and/or Dirichlet conditions.

The forcing vector will depend on which solution's heterogenous constraints are being applied. For the default qoi_index this will be the primal solution; for qoi_index >= 0 the corresponding adjoint solution's constraints will be used.

Definition at line 2456 of file dof_map_constraints.C.

References libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::resize(), libMesh::DenseMatrix< T >::resize(), libMesh::DenseMatrix< T >::right_multiply(), and libMesh::DenseMatrix< T >::vector_mult_add().

Referenced by extract_local_vector().

2461 {
2462  LOG_SCOPE_IF("build_constraint_matrix_and_vector()", "DofMap", !called_recursively);
2463 
2464  // Create a set containing the DOFs we already depend on
2465  typedef std::set<dof_id_type> RCSet;
2466  RCSet dof_set;
2467 
2468  bool we_have_constraints = false;
2469 
2470  // Next insert any other dofs the current dofs might be constrained
2471  // in terms of. Note that in this case we may not be done: Those
2472  // may in turn depend on others. So, we need to repeat this process
2473  // in that case until the system depends only on unconstrained
2474  // degrees of freedom.
2475  for (const auto & dof : elem_dofs)
2476  if (this->is_constrained_dof(dof))
2477  {
2478  we_have_constraints = true;
2479 
2480  // If the DOF is constrained
2481  DofConstraints::const_iterator
2482  pos = _dof_constraints.find(dof);
2483 
2484  libmesh_assert (pos != _dof_constraints.end());
2485 
2486  const DofConstraintRow & constraint_row = pos->second;
2487 
2488  // Constraint rows in p refinement may be empty
2489  //libmesh_assert (!constraint_row.empty());
2490 
2491  for (const auto & item : constraint_row)
2492  dof_set.insert (item.first);
2493  }
2494 
2495  // May be safe to return at this point
2496  // (but remember to stop the perflog)
2497  if (!we_have_constraints)
2498  return;
2499 
2500  for (const auto & dof : elem_dofs)
2501  dof_set.erase (dof);
2502 
2503  // If we added any DOFS then we need to do this recursively.
2504  // It is possible that we just added a DOF that is also
2505  // constrained!
2506  //
2507  // Also, we need to handle the special case of an element having DOFs
2508  // constrained in terms of other, local DOFs
2509  if (!dof_set.empty() || // case 1: constrained in terms of other DOFs
2510  !called_recursively) // case 2: constrained in terms of our own DOFs
2511  {
2512  const DofConstraintValueMap * rhs_values = nullptr;
2513  if (qoi_index < 0)
2514  rhs_values = &_primal_constraint_values;
2515  else
2516  {
2517  const AdjointDofConstraintValues::const_iterator
2518  it = _adjoint_constraint_values.find(qoi_index);
2519  if (it != _adjoint_constraint_values.end())
2520  rhs_values = &it->second;
2521  }
2522 
2523  const unsigned int old_size =
2524  cast_int<unsigned int>(elem_dofs.size());
2525 
2526  // Add new dependency dofs to the end of the current dof set
2527  elem_dofs.insert(elem_dofs.end(),
2528  dof_set.begin(), dof_set.end());
2529 
2530  // Now we can build the constraint matrix and vector.
2531  // Note that resize also zeros for a DenseMatrix and DenseVector
2532  C.resize (old_size,
2533  cast_int<unsigned int>(elem_dofs.size()));
2534  H.resize (old_size);
2535 
2536  // Create the C constraint matrix.
2537  for (unsigned int i=0; i != old_size; i++)
2538  if (this->is_constrained_dof(elem_dofs[i]))
2539  {
2540  // If the DOF is constrained
2541  DofConstraints::const_iterator
2542  pos = _dof_constraints.find(elem_dofs[i]);
2543 
2544  libmesh_assert (pos != _dof_constraints.end());
2545 
2546  const DofConstraintRow & constraint_row = pos->second;
2547 
2548  // p refinement creates empty constraint rows
2549  // libmesh_assert (!constraint_row.empty());
2550 
2551  for (const auto & item : constraint_row)
2552  for (unsigned int j=0,
2553  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2554  j != n_elem_dofs; j++)
2555  if (elem_dofs[j] == item.first)
2556  C(i,j) = item.second;
2557 
2558  if (rhs_values)
2559  {
2560  DofConstraintValueMap::const_iterator rhsit =
2561  rhs_values->find(elem_dofs[i]);
2562  if (rhsit != rhs_values->end())
2563  H(i) = rhsit->second;
2564  }
2565  }
2566  else
2567  {
2568  C(i,i) = 1.;
2569  }
2570 
2571  // May need to do this recursively. It is possible
2572  // that we just replaced a constrained DOF with another
2573  // constrained DOF.
2574  DenseMatrix<Number> Cnew;
2575  DenseVector<Number> Hnew;
2576 
2577  this->build_constraint_matrix_and_vector (Cnew, Hnew, elem_dofs,
2578  qoi_index, true);
2579 
2580  if ((C.n() == Cnew.m()) && // If the constraint matrix
2581  (Cnew.n() == elem_dofs.size())) // is constrained...
2582  {
2583  // If x = Cy + h and y = Dz + g
2584  // Then x = (CD)z + (Cg + h)
2585  C.vector_mult_add(H, 1, Hnew);
2586 
2587  C.right_multiply(Cnew);
2588  }
2589 
2590  libmesh_assert_equal_to (C.n(), elem_dofs.size());
2591  }
2592 }
void build_constraint_matrix_and_vector(DenseMatrix< Number > &C, DenseVector< Number > &H, std::vector< dof_id_type > &elem_dofs, int qoi_index=-1, const bool called_recursively=false) const
void resize(const unsigned int n)
Definition: dense_vector.h:355
unsigned int m() const
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1691
void vector_mult_add(DenseVector< T > &dest, const T factor, const DenseVector< T > &arg) const
virtual void right_multiply(const DenseMatrixBase< T > &M2) override
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1829
DofConstraints _dof_constraints
Definition: dof_map.h:1687
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1689
void resize(const unsigned int new_m, const unsigned int new_n)
Definition: dense_matrix.h:792
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
Definition: dof_map.h:97
unsigned int n() const

◆ build_sparsity()

std::unique_ptr< SparsityPattern::Build > libMesh::DofMap::build_sparsity ( const MeshBase mesh) const
private

Builds a sparsity pattern

Definition at line 58 of file dof_map.C.

References _augment_sparsity_pattern, _coupling_functors, _dof_coupling, _extra_sparsity_context, _extra_sparsity_function, libMesh::DofMap::AugmentSparsityPattern::augment_sparsity_pattern(), mesh, n_dofs_on_processor(), need_full_sparsity_pattern, libMesh::out, libMesh::Threads::parallel_reduce(), and use_coupled_neighbor_dofs().

Referenced by compute_sparsity().

59 {
60  libmesh_assert (mesh.is_prepared());
61 
62  LOG_SCOPE("build_sparsity()", "DofMap");
63 
64  // Compute the sparsity structure of the global matrix. This can be
65  // fed into a PetscMatrix to allocate exactly the number of nonzeros
66  // necessary to store the matrix. This algorithm should be linear
67  // in the (# of elements)*(# nodes per element)
68 
69  // We can be more efficient in the threaded sparsity pattern assembly
70  // if we don't need the exact pattern. For some sparse matrix formats
71  // a good upper bound will suffice.
72 
73  // See if we need to include sparsity pattern entries for coupling
74  // between neighbor dofs
75  bool implicit_neighbor_dofs = this->use_coupled_neighbor_dofs(mesh);
76 
77  // We can compute the sparsity pattern in parallel on multiple
78  // threads. The goal is for each thread to compute the full sparsity
79  // pattern for a subset of elements. These sparsity patterns can
80  // be efficiently merged in the SparsityPattern::Build::join()
81  // method, especially if there is not too much overlap between them.
82  // Even better, if the full sparsity pattern is not needed then
83  // the number of nonzeros per row can be estimated from the
84  // sparsity patterns created on each thread.
85  std::unique_ptr<SparsityPattern::Build> sp
86  (new SparsityPattern::Build (mesh,
87  *this,
88  this->_dof_coupling,
89  this->_coupling_functors,
90  implicit_neighbor_dofs,
92 
93  Threads::parallel_reduce (ConstElemRange (mesh.active_local_elements_begin(),
94  mesh.active_local_elements_end()), *sp);
95 
96  sp->parallel_sync();
97 
98 #ifndef NDEBUG
99  // Avoid declaring these variables unless asserts are enabled.
100  const processor_id_type proc_id = mesh.processor_id();
101  const dof_id_type n_dofs_on_proc = this->n_dofs_on_processor(proc_id);
102 #endif
103  libmesh_assert_equal_to (sp->sparsity_pattern.size(), n_dofs_on_proc);
104 
105  // Check to see if we have any extra stuff to add to the sparsity_pattern
107  {
109  {
110  libmesh_here();
111  libMesh::out << "WARNING: You have specified both an extra sparsity function and object.\n"
112  << " Are you sure this is what you meant to do??"
113  << std::endl;
114  }
115 
117  (sp->sparsity_pattern, sp->n_nz,
118  sp->n_oz, _extra_sparsity_context);
119  }
120 
123  (sp->sparsity_pattern, sp->n_nz, sp->n_oz);
124 
125  return std::unique_ptr<SparsityPattern::Build>(sp.release());
126 }
dof_id_type n_dofs_on_processor(const processor_id_type proc) const
Definition: dof_map.h:590
void * _extra_sparsity_context
Definition: dof_map.h:1564
MeshBase & mesh
uint8_t processor_id_type
Definition: id_types.h:99
AugmentSparsityPattern * _augment_sparsity_pattern
Definition: dof_map.h:1552
bool use_coupled_neighbor_dofs(const MeshBase &mesh) const
Definition: dof_map.C:1682
StoredRange< MeshBase::const_element_iterator, const Elem * > ConstElemRange
Definition: elem_range.h:34
bool need_full_sparsity_pattern
Definition: dof_map.h:1624
void(* _extra_sparsity_function)(SparsityPattern::Graph &, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *)
Definition: dof_map.h:1557
CouplingMatrix * _dof_coupling
Definition: dof_map.h:1319
virtual void augment_sparsity_pattern(SparsityPattern::Graph &sparsity, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz)=0
void parallel_reduce(const Range &range, Body &body)
Definition: threads_none.h:101
std::set< GhostingFunctor * > _coupling_functors
Definition: dof_map.h:1618
OStreamProxy out(std::cout)
uint8_t dof_id_type
Definition: id_types.h:64

◆ check_dirichlet_bcid_consistency()

void libMesh::DofMap::check_dirichlet_bcid_consistency ( const MeshBase mesh,
const DirichletBoundary boundary 
) const
private

Check that all the ids in dirichlet_bcids are actually present in the mesh. If not, this will throw an error.

Definition at line 4362 of file dof_map_constraints.C.

References libMesh::DirichletBoundary::b, bc_id, libMesh::ParallelObject::comm(), libMesh::BoundaryInfo::get_boundary_ids(), libMesh::MeshBase::get_boundary_info(), libMesh::Parallel::Communicator::max(), mesh, and libMesh::Parallel::Communicator::verify().

4364 {
4365  const std::set<boundary_id_type>& mesh_bcids = mesh.get_boundary_info().get_boundary_ids();
4366  const std::set<boundary_id_type>& dbc_bcids = boundary.b;
4367 
4368  // DirichletBoundary id sets should be consistent across all ranks
4369  libmesh_assert(mesh.comm().verify(dbc_bcids.size()));
4370 
4371  for (const auto & bc_id : dbc_bcids)
4372  {
4373  // DirichletBoundary id sets should be consistent across all ranks
4374  libmesh_assert(mesh.comm().verify(bc_id));
4375 
4376  bool found_bcid = (mesh_bcids.find(bc_id) != mesh_bcids.end());
4377 
4378  // On a distributed mesh, boundary id sets may *not* be
4379  // consistent across all ranks, since not all ranks see all
4380  // boundaries
4381  mesh.comm().max(found_bcid);
4382 
4383  if (!found_bcid)
4384  libmesh_error_msg("Could not find Dirichlet boundary id " << bc_id << " in mesh!");
4385  }
4386 }
MeshBase & mesh
const Parallel::Communicator & comm() const
const BoundaryInfo & get_boundary_info() const
Definition: mesh_base.h:131
boundary_id_type bc_id
Definition: xdr_io.C:51
const std::set< boundary_id_type > & get_boundary_ids() const
std::set< boundary_id_type > b

◆ check_for_cyclic_constraints()

void libMesh::DofMap::check_for_cyclic_constraints ( )

Throw an error if we detect and cyclic constraints, since these are not supported by libMesh and give erroneous results if they are present.

Definition at line 3334 of file dof_map_constraints.C.

References libMesh::Real.

3335 {
3336  // Create a set containing the DOFs we already depend on
3337  typedef std::set<dof_id_type> RCSet;
3338  RCSet unexpanded_set;
3339 
3340  // Use dof_constraints_copy in this method so that we don't
3341  // mess with _dof_constraints.
3342  DofConstraints dof_constraints_copy = _dof_constraints;
3343 
3344  for (const auto & i : dof_constraints_copy)
3345  unexpanded_set.insert(i.first);
3346 
3347  while (!unexpanded_set.empty())
3348  for (RCSet::iterator i = unexpanded_set.begin();
3349  i != unexpanded_set.end(); /* nothing */)
3350  {
3351  // If the DOF is constrained
3352  DofConstraints::iterator
3353  pos = dof_constraints_copy.find(*i);
3354 
3355  libmesh_assert (pos != dof_constraints_copy.end());
3356 
3357  DofConstraintRow & constraint_row = pos->second;
3358 
3359  // Comment out "rhs" parts of this method copied from process_constraints
3360  // DofConstraintValueMap::iterator rhsit =
3361  // _primal_constraint_values.find(*i);
3362  // Number constraint_rhs = (rhsit == _primal_constraint_values.end()) ?
3363  // 0 : rhsit->second;
3364 
3365  std::vector<dof_id_type> constraints_to_expand;
3366 
3367  for (const auto & item : constraint_row)
3368  if (item.first != *i && this->is_constrained_dof(item.first))
3369  {
3370  unexpanded_set.insert(item.first);
3371  constraints_to_expand.push_back(item.first);
3372  }
3373 
3374  for (const auto & expandable : constraints_to_expand)
3375  {
3376  const Real this_coef = constraint_row[expandable];
3377 
3378  DofConstraints::const_iterator
3379  subpos = dof_constraints_copy.find(expandable);
3380 
3381  libmesh_assert (subpos != dof_constraints_copy.end());
3382 
3383  const DofConstraintRow & subconstraint_row = subpos->second;
3384 
3385  for (const auto & item : subconstraint_row)
3386  {
3387  if (item.first == expandable)
3388  libmesh_error_msg("Cyclic constraint detected");
3389 
3390  constraint_row[item.first] += item.second * this_coef;
3391  }
3392 
3393  // Comment out "rhs" parts of this method copied from process_constraints
3394  // DofConstraintValueMap::const_iterator subrhsit =
3395  // _primal_constraint_values.find(expandable);
3396  // if (subrhsit != _primal_constraint_values.end())
3397  // constraint_rhs += subrhsit->second * this_coef;
3398 
3399  constraint_row.erase(expandable);
3400  }
3401 
3402  // Comment out "rhs" parts of this method copied from process_constraints
3403  // if (rhsit == _primal_constraint_values.end())
3404  // {
3405  // if (constraint_rhs != Number(0))
3406  // _primal_constraint_values[*i] = constraint_rhs;
3407  // else
3408  // _primal_constraint_values.erase(*i);
3409  // }
3410  // else
3411  // {
3412  // if (constraint_rhs != Number(0))
3413  // rhsit->second = constraint_rhs;
3414  // else
3415  // _primal_constraint_values.erase(rhsit);
3416  // }
3417 
3418  if (constraints_to_expand.empty())
3419  i = unexpanded_set.erase(i);
3420  else
3421  ++i;
3422  }
3423 }
DofConstraints _dof_constraints
Definition: dof_map.h:1687
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
Definition: dof_map.h:97

◆ clear()

void libMesh::DofMap::clear ( )

Free all new memory associated with the object, but restore its original state, with the mesh pointer and any default ghosting.

Definition at line 828 of file dof_map.C.

References _adjoint_constraint_values, _algebraic_ghosting_functors, _coupling_functors, _default_coupling, _default_evaluating, _dof_constraints, _dof_coupling, _end_df, _end_old_df, _first_df, _first_old_df, _first_old_scalar_df, _first_scalar_df, _matrices, _mesh, _n_dfs, _n_old_dfs, _primal_constraint_values, _send_list, _stashed_dof_constraints, _variable_group_numbers, _variable_groups, _variables, add_algebraic_ghosting_functor(), add_coupling_functor(), clear_sparsity(), need_full_sparsity_pattern, libMesh::MeshBase::remove_ghosting_functor(), and use_coupled_neighbor_dofs().

Referenced by ~DofMap().

829 {
830  // we don't want to clear
831  // the coupling matrix!
832  // It should not change...
833  //_dof_coupling->clear();
834  //
835  // But it would be inconsistent to leave our coupling settings
836  // through a clear()...
837  _dof_coupling = nullptr;
838 
839  // Reset ghosting functor statuses
840  {
841  for (const auto & gf : _coupling_functors)
842  {
843  libmesh_assert(gf);
845  }
846  this->_coupling_functors.clear();
847 
848  // Go back to default coupling
849 
850  _default_coupling->set_dof_coupling(this->_dof_coupling);
851  _default_coupling->set_n_levels(this->use_coupled_neighbor_dofs(this->_mesh));
852 
854  }
855 
856 
857  {
858  for (const auto & gf : _algebraic_ghosting_functors)
859  {
860  libmesh_assert(gf);
862  }
863  this->_algebraic_ghosting_functors.clear();
864 
865  // Go back to default send_list generation
866 
867  // _default_evaluating->set_dof_coupling(this->_dof_coupling);
868  _default_evaluating->set_n_levels(1);
870  }
871 
872  _variables.clear();
873  _variable_groups.clear();
874  _variable_group_numbers.clear();
875  _first_df.clear();
876  _end_df.clear();
877  _first_scalar_df.clear();
878  _send_list.clear();
879  this->clear_sparsity();
881 
882 #ifdef LIBMESH_ENABLE_AMR
883 
884  _dof_constraints.clear();
885  _stashed_dof_constraints.clear();
888  _n_old_dfs = 0;
889  _first_old_df.clear();
890  _end_old_df.clear();
891  _first_old_scalar_df.clear();
892 
893 #endif
894 
895  _matrices.clear();
896 
897  _n_dfs = 0;
898 }
std::vector< VariableGroup > _variable_groups
Definition: dof_map.h:1503
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1547
void remove_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: mesh_base.C:281
std::set< GhostingFunctor * > _algebraic_ghosting_functors
Definition: dof_map.h:1605
std::vector< dof_id_type > _end_old_df
Definition: dof_map.h:1672
bool use_coupled_neighbor_dofs(const MeshBase &mesh) const
Definition: dof_map.C:1682
void add_coupling_functor(GhostingFunctor &coupling_functor, bool to_mesh=true)
Definition: dof_map.C:1809
std::vector< dof_id_type > _first_old_df
Definition: dof_map.h:1667
std::vector< dof_id_type > _first_scalar_df
Definition: dof_map.h:1541
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1691
bool need_full_sparsity_pattern
Definition: dof_map.h:1624
std::vector< dof_id_type > _first_old_scalar_df
Definition: dof_map.h:1678
DofConstraints _dof_constraints
Definition: dof_map.h:1687
CouplingMatrix * _dof_coupling
Definition: dof_map.h:1319
std::vector< SparseMatrix< Number > *> _matrices
Definition: dof_map.h:1525
std::unique_ptr< DefaultCoupling > _default_coupling
Definition: dof_map.h:1587
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1689
std::vector< Variable > _variables
Definition: dof_map.h:1498
DofConstraints _stashed_dof_constraints
Definition: dof_map.h:1687
dof_id_type _n_old_dfs
Definition: dof_map.h:1662
void clear_sparsity()
Definition: dof_map.C:1771
std::set< GhostingFunctor * > _coupling_functors
Definition: dof_map.h:1618
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1535
std::vector< dof_id_type > _first_df
Definition: dof_map.h:1530
MeshBase & _mesh
Definition: dof_map.h:1518
std::unique_ptr< DefaultCoupling > _default_evaluating
Definition: dof_map.h:1595
std::vector< unsigned int > _variable_group_numbers
Definition: dof_map.h:1508
void add_algebraic_ghosting_functor(GhostingFunctor &evaluable_functor, bool to_mesh=true)
Definition: dof_map.C:1829
dof_id_type _n_dfs
Definition: dof_map.h:1649

◆ clear_sparsity()

void libMesh::DofMap::clear_sparsity ( )

Clears the sparsity pattern

Definition at line 1771 of file dof_map.C.

References _n_nz, _n_oz, _sp, and need_full_sparsity_pattern.

Referenced by clear(), libMesh::EigenSystem::reinit(), and libMesh::ImplicitSystem::reinit().

1772 {
1774  {
1775  libmesh_assert(_sp.get());
1776  libmesh_assert(!_n_nz || _n_nz == &_sp->n_nz);
1777  libmesh_assert(!_n_oz || _n_oz == &_sp->n_oz);
1778  _sp.reset();
1779  }
1780  else
1781  {
1782  libmesh_assert(!_sp.get());
1783  delete _n_nz;
1784  delete _n_oz;
1785  }
1786  _n_nz = nullptr;
1787  _n_oz = nullptr;
1788 }
std::unique_ptr< SparsityPattern::Build > _sp
Definition: dof_map.h:1630
std::vector< dof_id_type > * _n_nz
Definition: dof_map.h:1638
std::vector< dof_id_type > * _n_oz
Definition: dof_map.h:1644
bool need_full_sparsity_pattern
Definition: dof_map.h:1624

◆ comm()

const Parallel::Communicator& libMesh::ParallelObject::comm ( ) const
inlineinherited
Returns
A reference to the Parallel::Communicator object used by this mesh.

Definition at line 89 of file parallel_object.h.

References libMesh::ParallelObject::_communicator.

Referenced by libMesh::__libmesh_petsc_diff_solver_jacobian(), libMesh::__libmesh_petsc_diff_solver_monitor(), libMesh::__libmesh_petsc_diff_solver_residual(), libMesh::__libmesh_tao_equality_constraints(), libMesh::__libmesh_tao_equality_constraints_jacobian(), libMesh::__libmesh_tao_gradient(), libMesh::__libmesh_tao_hessian(), libMesh::__libmesh_tao_inequality_constraints(), libMesh::__libmesh_tao_inequality_constraints_jacobian(), libMesh::__libmesh_tao_objective(), libMesh::MeshRefinement::_coarsen_elements(), libMesh::ExactSolution::_compute_error(), libMesh::UniformRefinementEstimator::_estimate_error(), libMesh::BoundaryInfo::_find_id_maps(), libMesh::SlepcEigenSolver< T >::_petsc_shell_matrix_get_diagonal(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_get_diagonal(), libMesh::SlepcEigenSolver< T >::_petsc_shell_matrix_mult(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_mult(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_mult_add(), libMesh::EquationSystems::_read_impl(), libMesh::MeshRefinement::_refine_elements(), libMesh::MeshRefinement::_smooth_flags(), libMesh::PetscDMWrapper::add_dofs_helper(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::ImplicitSystem::add_matrix(), libMesh::System::add_vector(), libMesh::UnstructuredMesh::all_second_order(), libMesh::MeshTools::Modification::all_tri(), libMesh::LaplaceMeshSmoother::allgather_graph(), libMesh::FEMSystem::assemble_qoi(), libMesh::MeshCommunication::assign_global_indices(), attach_matrix(), libMesh::MeshTools::Generation::build_extrusion(), libMesh::BoundaryInfo::build_node_list_from_side_list(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::EquationSystems::build_parallel_solution_vector(), libMesh::PetscDMWrapper::build_section(), libMesh::PetscDMWrapper::build_sf(), libMesh::MeshBase::cache_elem_dims(), libMesh::System::calculate_norm(), check_dirichlet_bcid_consistency(), libMesh::PetscDMWrapper::check_section_n_dofs(), libMesh::Nemesis_IO_Helper::compute_num_global_elem_blocks(), libMesh::Nemesis_IO_Helper::compute_num_global_nodesets(), libMesh::Nemesis_IO_Helper::compute_num_global_sidesets(), libMesh::Problem_Interface::computeF(), libMesh::Problem_Interface::computeJacobian(), libMesh::Problem_Interface::computePreconditioner(), libMesh::ExodusII_IO::copy_elemental_solution(), libMesh::MeshTools::correct_node_proc_ids(), libMesh::MeshTools::create_bounding_box(), libMesh::MeshTools::create_nodal_bounding_box(), libMesh::MeshRefinement::create_parent_error_vector(), libMesh::MeshTools::create_processor_bounding_box(), libMesh::MeshTools::create_subdomain_bounding_box(), libMesh::MeshCommunication::delete_remote_elements(), distribute_dofs(), DMlibMeshFunction(), DMlibMeshJacobian(), DMlibMeshSetSystem_libMesh(), DMVariableBounds_libMesh(), libMesh::MeshRefinement::eliminate_unrefined_patches(), libMesh::EpetraVector< T >::EpetraVector(), libMesh::WeightedPatchRecoveryErrorEstimator::estimate_error(), libMesh::PatchRecoveryErrorEstimator::estimate_error(), libMesh::JumpErrorEstimator::estimate_error(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::MeshRefinement::flag_elements_by_elem_fraction(), libMesh::MeshRefinement::flag_elements_by_error_fraction(), libMesh::MeshRefinement::flag_elements_by_nelem_target(), libMesh::CondensedEigenSystem::get_eigenpair(), get_info(), libMesh::ImplicitSystem::get_linear_solver(), libMesh::LocationMap< T >::init(), libMesh::TimeSolver::init(), libMesh::SystemSubsetBySubdomain::init(), libMesh::PetscDMWrapper::init_and_attach_petscdm(), libMesh::EigenSystem::init_data(), libMesh::EigenSystem::init_matrices(), libMesh::OptimizationSystem::initialize_equality_constraints_storage(), libMesh::OptimizationSystem::initialize_inequality_constraints_storage(), libMesh::MeshTools::libmesh_assert_consistent_distributed(), libMesh::MeshTools::libmesh_assert_consistent_distributed_nodes(), libMesh::MeshTools::libmesh_assert_contiguous_dof_ids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_new_node_procids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Elem >(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_topology_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_flags(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_object_ids(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_p_levels(), libMesh::MeshTools::libmesh_assert_valid_refinement_flags(), libMesh::MeshTools::libmesh_assert_valid_unique_ids(), libMesh::libmesh_petsc_snes_fd_residual(), libMesh::libmesh_petsc_snes_jacobian(), libMesh::libmesh_petsc_snes_mffd_residual(), libMesh::libmesh_petsc_snes_postcheck(), libMesh::libmesh_petsc_snes_residual(), libMesh::libmesh_petsc_snes_residual_helper(), libMesh::MeshRefinement::limit_level_mismatch_at_edge(), libMesh::MeshRefinement::limit_level_mismatch_at_node(), libMesh::MeshRefinement::limit_overrefined_boundary(), libMesh::MeshRefinement::limit_underrefined_boundary(), libMesh::MeshRefinement::make_coarsening_compatible(), libMesh::MeshCommunication::make_elems_parallel_consistent(), libMesh::MeshRefinement::make_flags_parallel_consistent(), libMesh::MeshCommunication::make_new_node_proc_ids_parallel_consistent(), libMesh::MeshCommunication::make_new_nodes_parallel_consistent(), libMesh::MeshCommunication::make_node_ids_parallel_consistent(), libMesh::MeshCommunication::make_node_proc_ids_parallel_consistent(), libMesh::MeshCommunication::make_node_unique_ids_parallel_consistent(), libMesh::MeshCommunication::make_nodes_parallel_consistent(), libMesh::MeshCommunication::make_p_levels_parallel_consistent(), libMesh::MeshRefinement::make_refinement_compatible(), libMesh::FEMSystem::mesh_position_set(), libMesh::DistributedMesh::n_active_elem(), libMesh::MeshTools::n_active_levels(), libMesh::BoundaryInfo::n_boundary_conds(), libMesh::BoundaryInfo::n_edge_conds(), libMesh::CondensedEigenSystem::n_global_non_condensed_dofs(), libMesh::MeshTools::n_levels(), libMesh::BoundaryInfo::n_nodeset_conds(), libMesh::MeshTools::n_p_levels(), libMesh::BoundaryInfo::n_shellface_conds(), libMesh::DistributedMesh::parallel_max_elem_id(), libMesh::DistributedMesh::parallel_max_node_id(), libMesh::ReplicatedMesh::parallel_max_unique_id(), libMesh::DistributedMesh::parallel_max_unique_id(), libMesh::DistributedMesh::parallel_n_elem(), libMesh::DistributedMesh::parallel_n_nodes(), libMesh::SparsityPattern::Build::parallel_sync(), libMesh::MeshTools::paranoid_n_levels(), libMesh::petsc_auto_fieldsplit(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), libMesh::MeshBase::prepare_for_use(), libMesh::Nemesis_IO::read(), libMesh::XdrIO::read(), libMesh::CheckpointIO::read_header(), libMesh::XdrIO::read_header(), libMesh::System::read_header(), libMesh::System::read_legacy_data(), libMesh::System::read_SCALAR_dofs(), libMesh::XdrIO::read_serialized_bc_names(), libMesh::XdrIO::read_serialized_bcs_helper(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::System::read_serialized_vector(), libMesh::MeshBase::recalculate_n_partitions(), libMesh::MeshRefinement::refine_and_coarsen_elements(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::CheckpointIO::select_split_config(), set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), libMesh::PetscDiffSolver::setup_petsc_data(), libMesh::LaplaceMeshSmoother::smooth(), libMesh::split_mesh(), libMesh::MeshBase::subdomain_ids(), libMesh::BoundaryInfo::sync(), libMesh::MeshRefinement::test_level_one(), libMesh::MeshRefinement::test_unflagged(), libMesh::MeshTools::total_weight(), libMesh::MeshRefinement::uniformly_coarsen(), libMesh::NameBasedIO::write(), libMesh::XdrIO::write(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), and libMesh::XdrIO::write_serialized_nodesets().

90  { return _communicator; }
const Parallel::Communicator & _communicator

◆ compute_sparsity()

void libMesh::DofMap::compute_sparsity ( const MeshBase mesh)

Computes the sparsity pattern for the matrices corresponding to proc_id and sends that data to Linear Algebra packages for preallocation of sparse matrices.

Definition at line 1739 of file dof_map.C.

References _matrices, _n_nz, _n_oz, _sp, build_sparsity(), and need_full_sparsity_pattern.

Referenced by libMesh::EigenSystem::init_matrices(), libMesh::ImplicitSystem::init_matrices(), libMesh::EigenSystem::reinit(), and libMesh::ImplicitSystem::reinit().

1740 {
1741  _sp = this->build_sparsity(mesh);
1742 
1743  // It is possible that some \p SparseMatrix implementations want to
1744  // see the sparsity pattern before we throw it away. If so, we
1745  // share a view of its arrays, and we pass it in to the matrices.
1747  {
1748  _n_nz = &_sp->n_nz;
1749  _n_oz = &_sp->n_oz;
1750 
1751  for (const auto & mat : _matrices)
1752  mat->update_sparsity_pattern (_sp->sparsity_pattern);
1753  }
1754  // If we don't need the full sparsity pattern anymore, steal the
1755  // arrays we do need and free the rest of the memory
1756  else
1757  {
1758  if (!_n_nz)
1759  _n_nz = new std::vector<dof_id_type>();
1760  _n_nz->swap(_sp->n_nz);
1761  if (!_n_oz)
1762  _n_oz = new std::vector<dof_id_type>();
1763  _n_oz->swap(_sp->n_oz);
1764 
1765  _sp.reset();
1766  }
1767 }
std::unique_ptr< SparsityPattern::Build > _sp
Definition: dof_map.h:1630
MeshBase & mesh
std::vector< dof_id_type > * _n_nz
Definition: dof_map.h:1638
std::vector< dof_id_type > * _n_oz
Definition: dof_map.h:1644
bool need_full_sparsity_pattern
Definition: dof_map.h:1624
std::unique_ptr< SparsityPattern::Build > build_sparsity(const MeshBase &mesh) const
Definition: dof_map.C:58
std::vector< SparseMatrix< Number > *> _matrices
Definition: dof_map.h:1525

◆ constrain_element_dyad_matrix()

void libMesh::DofMap::constrain_element_dyad_matrix ( DenseVector< Number > &  v,
DenseVector< Number > &  w,
std::vector< dof_id_type > &  row_dofs,
bool  asymmetric_constraint_rows = true 
) const
inline

Constrains a dyadic element matrix B = v w'. This method requires the element matrix to be square, in which case the elem_dofs correspond to the global DOF indices of both the rows and columns of the element matrix. For this case the rows and columns of the matrix necessarily correspond to variables of the same approximation order.

Definition at line 2012 of file dof_map_constraints.C.

References libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::size(), and libMesh::DenseMatrix< T >::vector_mult_transpose().

2016 {
2017  libmesh_assert_equal_to (v.size(), row_dofs.size());
2018  libmesh_assert_equal_to (w.size(), row_dofs.size());
2019 
2020  // check for easy return
2021  if (this->_dof_constraints.empty())
2022  return;
2023 
2024  // The constrained RHS is built up as R^T F.
2026 
2027  this->build_constraint_matrix (R, row_dofs);
2028 
2029  LOG_SCOPE("cnstrn_elem_dyad_mat()", "DofMap");
2030 
2031  // It is possible that the vector is not constrained at all.
2032  if ((R.m() == v.size()) &&
2033  (R.n() == row_dofs.size())) // if the RHS is constrained
2034  {
2035  // Compute the matrix-vector products
2036  DenseVector<Number> old_v(v);
2037  DenseVector<Number> old_w(w);
2038 
2039  // compute matrix/vector product
2040  R.vector_mult_transpose(v, old_v);
2041  R.vector_mult_transpose(w, old_w);
2042 
2043  libmesh_assert_equal_to (row_dofs.size(), v.size());
2044  libmesh_assert_equal_to (row_dofs.size(), w.size());
2045 
2046  /* Constrain only v, not w. */
2047 
2048  for (unsigned int i=0,
2049  n_row_dofs = cast_int<unsigned int>(row_dofs.size());
2050  i != n_row_dofs; i++)
2051  if (this->is_constrained_dof(row_dofs[i]))
2052  {
2053  // If the DOF is constrained
2054  libmesh_assert (_dof_constraints.find(row_dofs[i]) != _dof_constraints.end());
2055 
2056  v(i) = 0;
2057  }
2058  } // end if the RHS is constrained.
2059 }
virtual unsigned int size() const override
Definition: dense_vector.h:92
unsigned int m() const
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1829
DofConstraints _dof_constraints
Definition: dof_map.h:1687
void build_constraint_matrix(DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
unsigned int n() const

◆ constrain_element_matrix() [1/2]

void libMesh::DofMap::constrain_element_matrix ( DenseMatrix< Number > &  matrix,
std::vector< dof_id_type > &  elem_dofs,
bool  asymmetric_constraint_rows = true 
) const
inline

Constrains the element matrix. This method requires the element matrix to be square, in which case the elem_dofs correspond to the global DOF indices of both the rows and columns of the element matrix. For this case the rows and columns of the matrix necessarily correspond to variables of the same approximation order.

If asymmetric_constraint_rows is set to true (as it is by default), constraint row equations will be reinforced in a way which breaks matrix symmetry but makes inexact linear solver solutions more likely to satisfy hanging node constraints.

Definition at line 1545 of file dof_map_constraints.C.

References libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), and libMesh::DenseMatrix< T >::right_multiply().

1548 {
1549  libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
1550  libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
1551 
1552  // check for easy return
1553  if (this->_dof_constraints.empty())
1554  return;
1555 
1556  // The constrained matrix is built up as C^T K C.
1558 
1559 
1560  this->build_constraint_matrix (C, elem_dofs);
1561 
1562  LOG_SCOPE("constrain_elem_matrix()", "DofMap");
1563 
1564  // It is possible that the matrix is not constrained at all.
1565  if ((C.m() == matrix.m()) &&
1566  (C.n() == elem_dofs.size())) // It the matrix is constrained
1567  {
1568  // Compute the matrix-matrix-matrix product C^T K C
1569  matrix.left_multiply_transpose (C);
1570  matrix.right_multiply (C);
1571 
1572 
1573  libmesh_assert_equal_to (matrix.m(), matrix.n());
1574  libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
1575  libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
1576 
1577 
1578  for (unsigned int i=0,
1579  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
1580  i != n_elem_dofs; i++)
1581  // If the DOF is constrained
1582  if (this->is_constrained_dof(elem_dofs[i]))
1583  {
1584  for (unsigned int j=0; j<matrix.n(); j++)
1585  matrix(i,j) = 0.;
1586 
1587  matrix(i,i) = 1.;
1588 
1589  if (asymmetric_constraint_rows)
1590  {
1591  DofConstraints::const_iterator
1592  pos = _dof_constraints.find(elem_dofs[i]);
1593 
1594  libmesh_assert (pos != _dof_constraints.end());
1595 
1596  const DofConstraintRow & constraint_row = pos->second;
1597 
1598  // This is an overzealous assertion in the presence of
1599  // heterogenous constraints: we now can constrain "u_i = c"
1600  // with no other u_j terms involved.
1601  //
1602  // libmesh_assert (!constraint_row.empty());
1603 
1604  for (const auto & item : constraint_row)
1605  for (unsigned int j=0; j != n_elem_dofs; j++)
1606  if (elem_dofs[j] == item.first)
1607  matrix(i,j) = -item.second;
1608  }
1609  }
1610  } // end if is constrained...
1611 }
unsigned int m() const
virtual void right_multiply(const DenseMatrixBase< T > &M2) override
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1829
DofConstraints _dof_constraints
Definition: dof_map.h:1687
void left_multiply_transpose(const DenseMatrix< T > &A)
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
Definition: dof_map.h:97
void build_constraint_matrix(DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
unsigned int n() const

◆ constrain_element_matrix() [2/2]

void libMesh::DofMap::constrain_element_matrix ( DenseMatrix< Number > &  matrix,
std::vector< dof_id_type > &  row_dofs,
std::vector< dof_id_type > &  col_dofs,
bool  asymmetric_constraint_rows = true 
) const
inline

Constrains the element matrix. This method allows the element matrix to be non-square, in which case the row_dofs and col_dofs may be of different size and correspond to variables approximated in different spaces.

Definition at line 1878 of file dof_map_constraints.C.

References libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), and libMesh::DenseMatrix< T >::right_multiply().

1882 {
1883  libmesh_assert_equal_to (row_dofs.size(), matrix.m());
1884  libmesh_assert_equal_to (col_dofs.size(), matrix.n());
1885 
1886  // check for easy return
1887  if (this->_dof_constraints.empty())
1888  return;
1889 
1890  // The constrained matrix is built up as R^T K C.
1893 
1894  // Safeguard against the user passing us the same
1895  // object for row_dofs and col_dofs. If that is done
1896  // the calls to build_matrix would fail
1897  std::vector<dof_id_type> orig_row_dofs(row_dofs);
1898  std::vector<dof_id_type> orig_col_dofs(col_dofs);
1899 
1900  this->build_constraint_matrix (R, orig_row_dofs);
1901  this->build_constraint_matrix (C, orig_col_dofs);
1902 
1903  LOG_SCOPE("constrain_elem_matrix()", "DofMap");
1904 
1905  row_dofs = orig_row_dofs;
1906  col_dofs = orig_col_dofs;
1907 
1908  bool constraint_found = false;
1909 
1910  // K_constrained = R^T K C
1911 
1912  if ((R.m() == matrix.m()) &&
1913  (R.n() == row_dofs.size()))
1914  {
1915  matrix.left_multiply_transpose (R);
1916  constraint_found = true;
1917  }
1918 
1919  if ((C.m() == matrix.n()) &&
1920  (C.n() == col_dofs.size()))
1921  {
1922  matrix.right_multiply (C);
1923  constraint_found = true;
1924  }
1925 
1926  // It is possible that the matrix is not constrained at all.
1927  if (constraint_found)
1928  {
1929  libmesh_assert_equal_to (matrix.m(), row_dofs.size());
1930  libmesh_assert_equal_to (matrix.n(), col_dofs.size());
1931 
1932 
1933  for (unsigned int i=0,
1934  n_row_dofs = cast_int<unsigned int>(row_dofs.size());
1935  i != n_row_dofs; i++)
1936  if (this->is_constrained_dof(row_dofs[i]))
1937  {
1938  for (unsigned int j=0; j<matrix.n(); j++)
1939  {
1940  if (row_dofs[i] != col_dofs[j])
1941  matrix(i,j) = 0.;
1942  else // If the DOF is constrained
1943  matrix(i,j) = 1.;
1944  }
1945 
1946  if (asymmetric_constraint_rows)
1947  {
1948  DofConstraints::const_iterator
1949  pos = _dof_constraints.find(row_dofs[i]);
1950 
1951  libmesh_assert (pos != _dof_constraints.end());
1952 
1953  const DofConstraintRow & constraint_row = pos->second;
1954 
1955  libmesh_assert (!constraint_row.empty());
1956 
1957  for (const auto & item : constraint_row)
1958  for (unsigned int j=0,
1959  n_col_dofs = cast_int<unsigned int>(col_dofs.size());
1960  j != n_col_dofs; j++)
1961  if (col_dofs[j] == item.first)
1962  matrix(i,j) = -item.second;
1963  }
1964  }
1965  } // end if is constrained...
1966 }
unsigned int m() const
virtual void right_multiply(const DenseMatrixBase< T > &M2) override
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1829
DofConstraints _dof_constraints
Definition: dof_map.h:1687
void left_multiply_transpose(const DenseMatrix< T > &A)
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
Definition: dof_map.h:97
void build_constraint_matrix(DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
unsigned int n() const

◆ constrain_element_matrix_and_vector()

void libMesh::DofMap::constrain_element_matrix_and_vector ( DenseMatrix< Number > &  matrix,
DenseVector< Number > &  rhs,
std::vector< dof_id_type > &  elem_dofs,
bool  asymmetric_constraint_rows = true 
) const
inline

Constrains the element matrix and vector. This method requires the element matrix to be square, in which case the elem_dofs correspond to the global DOF indices of both the rows and columns of the element matrix. For this case the rows and columns of the matrix necessarily correspond to variables of the same approximation order.

Definition at line 1615 of file dof_map_constraints.C.

References libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::right_multiply(), libMesh::DenseVector< T >::size(), and libMesh::DenseMatrix< T >::vector_mult_transpose().

1619 {
1620  libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
1621  libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
1622  libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
1623 
1624  // check for easy return
1625  if (this->_dof_constraints.empty())
1626  return;
1627 
1628  // The constrained matrix is built up as C^T K C.
1629  // The constrained RHS is built up as C^T F
1631 
1632  this->build_constraint_matrix (C, elem_dofs);
1633 
1634  LOG_SCOPE("cnstrn_elem_mat_vec()", "DofMap");
1635 
1636  // It is possible that the matrix is not constrained at all.
1637  if ((C.m() == matrix.m()) &&
1638  (C.n() == elem_dofs.size())) // It the matrix is constrained
1639  {
1640  // Compute the matrix-matrix-matrix product C^T K C
1641  matrix.left_multiply_transpose (C);
1642  matrix.right_multiply (C);
1643 
1644 
1645  libmesh_assert_equal_to (matrix.m(), matrix.n());
1646  libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
1647  libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
1648 
1649 
1650  for (unsigned int i=0,
1651  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
1652  i != n_elem_dofs; i++)
1653  if (this->is_constrained_dof(elem_dofs[i]))
1654  {
1655  for (unsigned int j=0; j<matrix.n(); j++)
1656  matrix(i,j) = 0.;
1657 
1658  // If the DOF is constrained
1659  matrix(i,i) = 1.;
1660 
1661  // This will put a nonsymmetric entry in the constraint
1662  // row to ensure that the linear system produces the
1663  // correct value for the constrained DOF.
1664  if (asymmetric_constraint_rows)
1665  {
1666  DofConstraints::const_iterator
1667  pos = _dof_constraints.find(elem_dofs[i]);
1668 
1669  libmesh_assert (pos != _dof_constraints.end());
1670 
1671  const DofConstraintRow & constraint_row = pos->second;
1672 
1673  // p refinement creates empty constraint rows
1674  // libmesh_assert (!constraint_row.empty());
1675 
1676  for (const auto & item : constraint_row)
1677  for (unsigned int j=0; j != n_elem_dofs; j++)
1678  if (elem_dofs[j] == item.first)
1679  matrix(i,j) = -item.second;
1680  }
1681  }
1682 
1683 
1684  // Compute the matrix-vector product C^T F
1685  DenseVector<Number> old_rhs(rhs);
1686 
1687  // compute matrix/vector product
1688  C.vector_mult_transpose(rhs, old_rhs);
1689  } // end if is constrained...
1690 }
virtual unsigned int size() const override
Definition: dense_vector.h:92
unsigned int m() const
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
virtual void right_multiply(const DenseMatrixBase< T > &M2) override
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1829
DofConstraints _dof_constraints
Definition: dof_map.h:1687
void left_multiply_transpose(const DenseMatrix< T > &A)
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
Definition: dof_map.h:97
void build_constraint_matrix(DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
unsigned int n() const

◆ constrain_element_vector()

void libMesh::DofMap::constrain_element_vector ( DenseVector< Number > &  rhs,
std::vector< dof_id_type > &  dofs,
bool  asymmetric_constraint_rows = true 
) const
inline

Constrains the element vector.

Definition at line 1970 of file dof_map_constraints.C.

References libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::size(), and libMesh::DenseMatrix< T >::vector_mult_transpose().

1973 {
1974  libmesh_assert_equal_to (rhs.size(), row_dofs.size());
1975 
1976  // check for easy return
1977  if (this->_dof_constraints.empty())
1978  return;
1979 
1980  // The constrained RHS is built up as R^T F.
1982 
1983  this->build_constraint_matrix (R, row_dofs);
1984 
1985  LOG_SCOPE("constrain_elem_vector()", "DofMap");
1986 
1987  // It is possible that the vector is not constrained at all.
1988  if ((R.m() == rhs.size()) &&
1989  (R.n() == row_dofs.size())) // if the RHS is constrained
1990  {
1991  // Compute the matrix-vector product
1992  DenseVector<Number> old_rhs(rhs);
1993  R.vector_mult_transpose(rhs, old_rhs);
1994 
1995  libmesh_assert_equal_to (row_dofs.size(), rhs.size());
1996 
1997  for (unsigned int i=0,
1998  n_row_dofs = cast_int<unsigned int>(row_dofs.size());
1999  i != n_row_dofs; i++)
2000  if (this->is_constrained_dof(row_dofs[i]))
2001  {
2002  // If the DOF is constrained
2003  libmesh_assert (_dof_constraints.find(row_dofs[i]) != _dof_constraints.end());
2004 
2005  rhs(i) = 0;
2006  }
2007  } // end if the RHS is constrained.
2008 }
virtual unsigned int size() const override
Definition: dense_vector.h:92
unsigned int m() const
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1829
DofConstraints _dof_constraints
Definition: dof_map.h:1687
void build_constraint_matrix(DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
unsigned int n() const

◆ constrain_nothing()

void libMesh::DofMap::constrain_nothing ( std::vector< dof_id_type > &  dofs) const

Does not actually constrain anything, but modifies dofs in the same way as any of the constrain functions would do, i.e. adds those dofs in terms of which any of the existing dofs is constrained.

Definition at line 2063 of file dof_map_constraints.C.

2064 {
2065  // check for easy return
2066  if (this->_dof_constraints.empty())
2067  return;
2068 
2069  // All the work is done by \p build_constraint_matrix. We just need
2070  // a dummy matrix.
2072  this->build_constraint_matrix (R, dofs);
2073 }
DofConstraints _dof_constraints
Definition: dof_map.h:1687
void build_constraint_matrix(DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const

◆ constrain_p_dofs()

void libMesh::DofMap::constrain_p_dofs ( unsigned int  var,
const Elem elem,
unsigned int  s,
unsigned int  p 
)

Constrains degrees of freedom on side s of element elem which correspond to variable number var and to p refinement levels above p.

Definition at line 4208 of file dof_map_constraints.C.

References libMesh::Elem::dim(), libMesh::DofObject::dof_number(), libMesh::Elem::is_node_on_side(), libMesh::Elem::is_vertex(), libMesh::DofObject::n_comp(), n_nodes, libMesh::Elem::n_nodes(), libMesh::Elem::n_sides(), libMesh::Elem::node_ref(), libMesh::FEType::order, libMesh::Elem::p_level(), libMesh::Threads::spin_mtx, and libMesh::Elem::type().

Referenced by libMesh::FEGenericBase< FEOutputType< T >::type >::compute_periodic_constraints(), and libMesh::FEGenericBase< FEOutputType< T >::type >::compute_proj_constraints().

4212 {
4213  // We're constraining dofs on elem which correspond to p refinement
4214  // levels above p - this only makes sense if elem's p refinement
4215  // level is above p.
4216  libmesh_assert_greater (elem->p_level(), p);
4217  libmesh_assert_less (s, elem->n_sides());
4218 
4219  const unsigned int sys_num = this->sys_number();
4220  const unsigned int dim = elem->dim();
4221  ElemType type = elem->type();
4222  FEType low_p_fe_type = this->variable_type(var);
4223  FEType high_p_fe_type = this->variable_type(var);
4224  low_p_fe_type.order = static_cast<Order>(low_p_fe_type.order + p);
4225  high_p_fe_type.order = static_cast<Order>(high_p_fe_type.order +
4226  elem->p_level());
4227 
4228  const unsigned int n_nodes = elem->n_nodes();
4229  for (unsigned int n = 0; n != n_nodes; ++n)
4230  if (elem->is_node_on_side(n, s))
4231  {
4232  const Node & node = elem->node_ref(n);
4233  const unsigned int low_nc =
4234  FEInterface::n_dofs_at_node (dim, low_p_fe_type, type, n);
4235  const unsigned int high_nc =
4236  FEInterface::n_dofs_at_node (dim, high_p_fe_type, type, n);
4237 
4238  // since we may be running this method concurrently
4239  // on multiple threads we need to acquire a lock
4240  // before modifying the _dof_constraints object.
4241  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
4242 
4243  if (elem->is_vertex(n))
4244  {
4245  // Add "this is zero" constraint rows for high p vertex
4246  // dofs
4247  for (unsigned int i = low_nc; i != high_nc; ++i)
4248  {
4249  _dof_constraints[node.dof_number(sys_num,var,i)].clear();
4250  _primal_constraint_values.erase(node.dof_number(sys_num,var,i));
4251  }
4252  }
4253  else
4254  {
4255  const unsigned int total_dofs = node.n_comp(sys_num, var);
4256  libmesh_assert_greater_equal (total_dofs, high_nc);
4257  // Add "this is zero" constraint rows for high p
4258  // non-vertex dofs, which are numbered in reverse
4259  for (unsigned int j = low_nc; j != high_nc; ++j)
4260  {
4261  const unsigned int i = total_dofs - j - 1;
4262  _dof_constraints[node.dof_number(sys_num,var,i)].clear();
4263  _primal_constraint_values.erase(node.dof_number(sys_num,var,i));
4264  }
4265  }
4266  }
4267 }
Manages the family, order, etc. parameters for a given FE.
Definition: fe_type.h:179
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:833
A geometric point in (x,y,z) space associated with a DOF.
Definition: node.h:52
unsigned int n_comp(const unsigned int s, const unsigned int var) const
Definition: dof_object.h:803
const FEType & variable_type(const unsigned int c) const
Definition: dof_map.h:1792
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
unsigned int p_level() const
Definition: elem.h:2555
OrderWrapper order
Definition: fe_type.h:198
unsigned int sys_number() const
Definition: dof_map.h:1744
const dof_id_type n_nodes
Definition: tecplot_io.C:68
spin_mutex spin_mtx
Definition: threads.C:29
const Node & node_ref(const unsigned int i) const
Definition: elem.h:1979
virtual unsigned int n_nodes() const =0
DofConstraints _dof_constraints
Definition: dof_map.h:1687
static unsigned int n_dofs_at_node(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int n)
Definition: fe_interface.C:473
virtual unsigned int n_sides() const =0
virtual unsigned short dim() const =0
virtual bool is_vertex(const unsigned int i) const =0
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1689
virtual ElemType type() const =0

◆ constraint_rows_begin()

DofConstraints::const_iterator libMesh::DofMap::constraint_rows_begin ( ) const
inline
Returns
An iterator pointing to the first DoF constraint row.

Definition at line 902 of file dof_map.h.

References _dof_constraints.

903  { return _dof_constraints.begin(); }
DofConstraints _dof_constraints
Definition: dof_map.h:1687

◆ constraint_rows_end()

DofConstraints::const_iterator libMesh::DofMap::constraint_rows_end ( ) const
inline
Returns
An iterator pointing just past the last DoF constraint row.

Definition at line 908 of file dof_map.h.

References _dof_constraints.

909  { return _dof_constraints.end(); }
DofConstraints _dof_constraints
Definition: dof_map.h:1687

◆ coupling_functors_begin()

std::set<GhostingFunctor *>::const_iterator libMesh::DofMap::coupling_functors_begin ( ) const
inline

Beginning of range of coupling functors

Definition at line 317 of file dof_map.h.

References _coupling_functors.

Referenced by add_neighbors_to_send_list(), and libMesh::SparsityPattern::Build::operator()().

318  { return _coupling_functors.begin(); }
std::set< GhostingFunctor * > _coupling_functors
Definition: dof_map.h:1618

◆ coupling_functors_end()

std::set<GhostingFunctor *>::const_iterator libMesh::DofMap::coupling_functors_end ( ) const
inline

End of range of coupling functors

Definition at line 323 of file dof_map.h.

References _coupling_functors.

Referenced by add_neighbors_to_send_list(), and libMesh::SparsityPattern::Build::operator()().

324  { return _coupling_functors.end(); }
std::set< GhostingFunctor * > _coupling_functors
Definition: dof_map.h:1618

◆ create_dof_constraints()

void libMesh::DofMap::create_dof_constraints ( const MeshBase mesh,
Real  time = 0 
)

Rebuilds the raw degree of freedom and DofObject constraints. A time is specified for use in building time-dependent Dirichlet constraints.

Definition at line 1194 of file dof_map_constraints.C.

References libMesh::StoredRange< iterator_type, object_type >::empty(), libMesh::MeshBase::is_prepared(), libMesh::MeshBase::is_serial(), libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), libMesh::MeshBase::local_elements_begin(), libMesh::MeshBase::local_elements_end(), mesh, libMesh::MeshBase::mesh_dimension(), libMesh::MeshBase::n_elem(), libMesh::Threads::parallel_for(), libMesh::StoredRange< iterator_type, object_type >::reset(), and libMesh::MeshBase::sub_point_locator().

Referenced by libMesh::System::reinit_constraints().

1195 {
1196  parallel_object_only();
1197 
1198  LOG_SCOPE("create_dof_constraints()", "DofMap");
1199 
1200  libmesh_assert (mesh.is_prepared());
1201 
1202  // The user might have set boundary conditions after the mesh was
1203  // prepared; we should double-check that those boundary conditions
1204  // are still consistent.
1205 #ifdef DEBUG
1207 #endif
1208 
1209  // We might get constraint equations from AMR hanging nodes in 2D/3D
1210  // or from boundary conditions in any dimension
1211  const bool possible_local_constraints = false
1212  || !mesh.n_elem()
1213 #ifdef LIBMESH_ENABLE_AMR
1214  || mesh.mesh_dimension() > 1
1215 #endif
1216 #ifdef LIBMESH_ENABLE_PERIODIC
1217  || !_periodic_boundaries->empty()
1218 #endif
1219 #ifdef LIBMESH_ENABLE_DIRICHLET
1220  || !_dirichlet_boundaries->empty()
1221 #endif
1222  ;
1223 
1224  // Even if we don't have constraints, another processor might.
1225  bool possible_global_constraints = possible_local_constraints;
1226 #if defined(LIBMESH_ENABLE_PERIODIC) || defined(LIBMESH_ENABLE_DIRICHLET) || defined(LIBMESH_ENABLE_AMR)
1227  libmesh_assert(this->comm().verify(mesh.is_serial()));
1228 
1229  this->comm().max(possible_global_constraints);
1230 #endif
1231 
1232  if (!possible_global_constraints)
1233  {
1234  // Clear out any old constraints; maybe the user just deleted
1235  // their last remaining dirichlet/periodic/user constraint?
1236 #ifdef LIBMESH_ENABLE_CONSTRAINTS
1237  _dof_constraints.clear();
1238  _stashed_dof_constraints.clear();
1239  _primal_constraint_values.clear();
1241 #endif
1242 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
1243  _node_constraints.clear();
1244 #endif
1245 
1246  return;
1247  }
1248 
1249  // Here we build the hanging node constraints. This is done
1250  // by enforcing the condition u_a = u_b along hanging sides.
1251  // u_a = u_b is collocated at the nodes of side a, which gives
1252  // one row of the constraint matrix.
1253 
1254  // Processors only compute their local constraints
1257 
1258  // Global computation fails if we're using a FEMFunctionBase BC on a
1259  // ReplicatedMesh in parallel
1260  // ConstElemRange range (mesh.elements_begin(),
1261  // mesh.elements_end());
1262 
1263  // compute_periodic_constraints requires a point_locator() from our
1264  // Mesh, but point_locator() construction is parallel and threaded.
1265  // Rather than nest threads within threads we'll make sure it's
1266  // preconstructed.
1267 #ifdef LIBMESH_ENABLE_PERIODIC
1268  bool need_point_locator = !_periodic_boundaries->empty() && !range.empty();
1269 
1270  this->comm().max(need_point_locator);
1271 
1272  if (need_point_locator)
1274 #endif
1275 
1276 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
1277  // recalculate node constraints from scratch
1278  _node_constraints.clear();
1279 
1280  Threads::parallel_for (range,
1281  ComputeNodeConstraints (_node_constraints,
1282 #ifdef LIBMESH_ENABLE_PERIODIC
1284 #endif
1285  mesh));
1286 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
1287 
1288 
1289  // recalculate dof constraints from scratch
1290  _dof_constraints.clear();
1291  _stashed_dof_constraints.clear();
1292  _primal_constraint_values.clear();
1294 
1295  // Look at all the variables in the system. Reset the element
1296  // range at each iteration -- there is no need to reconstruct it.
1297  for (unsigned int variable_number=0; variable_number<this->n_variables();
1298  ++variable_number, range.reset())
1299  Threads::parallel_for (range,
1300  ComputeConstraints (_dof_constraints,
1301  *this,
1302 #ifdef LIBMESH_ENABLE_PERIODIC
1304 #endif
1305  mesh,
1306  variable_number));
1307 
1308 #ifdef LIBMESH_ENABLE_DIRICHLET
1309  for (DirichletBoundaries::iterator
1310  i = _dirichlet_boundaries->begin();
1311  i != _dirichlet_boundaries->end(); ++i, range.reset())
1312  {
1313  // Sanity check that the boundary ids associated with the DirichletBoundary
1314  // objects are actually present in the mesh
1315  this->check_dirichlet_bcid_consistency(mesh,**i);
1316 
1318  (range,
1319  ConstrainDirichlet(*this, mesh, time, **i,
1320  AddPrimalConstraint(*this))
1321  );
1322  }
1323 
1324  for (unsigned int qoi_index = 0,
1325  n_qois = cast_int<unsigned int>(_adjoint_dirichlet_boundaries.size());
1326  qoi_index != n_qois; ++qoi_index)
1327  {
1328  for (DirichletBoundaries::iterator
1329  i = _adjoint_dirichlet_boundaries[qoi_index]->begin();
1330  i != _adjoint_dirichlet_boundaries[qoi_index]->end();
1331  ++i, range.reset())
1332  {
1333  // Sanity check that the boundary ids associated with the DirichletBoundary
1334  // objects are actually present in the mesh
1335  this->check_dirichlet_bcid_consistency(mesh,**i);
1336 
1338  (range,
1339  ConstrainDirichlet(*this, mesh, time, **i,
1340  AddAdjointConstraint(*this, qoi_index))
1341  );
1342  }
1343  }
1344 
1345 #endif // LIBMESH_ENABLE_DIRICHLET
1346 }
void check_dirichlet_bcid_consistency(const MeshBase &mesh, const DirichletBoundary &boundary) const
bool is_prepared() const
Definition: mesh_base.h:147
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:496
void parallel_for(const Range &range, const Body &body)
Definition: threads_none.h:73
virtual element_iterator local_elements_begin()=0
MeshBase & mesh
unsigned int n_variables() const
Definition: dof_map.h:541
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Definition: dof_map.h:1721
const Parallel::Communicator & comm() const
Utility class for defining generic ranges for threading.
Definition: stored_range.h:52
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1691
virtual bool is_serial() const
Definition: mesh_base.h:154
virtual element_iterator local_elements_end()=0
void libmesh_assert_valid_boundary_ids(const MeshBase &mesh)
Definition: mesh_tools.C:1401
DofConstraints _dof_constraints
Definition: dof_map.h:1687
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1727
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Definition: dof_map.h:1707
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1689
DofConstraints _stashed_dof_constraints
Definition: dof_map.h:1687
unsigned int mesh_dimension() const
Definition: mesh_base.C:126
virtual dof_id_type n_elem() const =0
NodeConstraints _node_constraints
Definition: dof_map.h:1698

◆ default_algebraic_ghosting()

DefaultCoupling& libMesh::DofMap::default_algebraic_ghosting ( )
inline

Default algebraic ghosting functor

Definition at line 379 of file dof_map.h.

References _default_evaluating.

Referenced by add_default_ghosting(), and remove_default_ghosting().

379 { return *_default_evaluating; }
std::unique_ptr< DefaultCoupling > _default_evaluating
Definition: dof_map.h:1595

◆ default_coupling()

DefaultCoupling& libMesh::DofMap::default_coupling ( )
inline

Default coupling functor

Definition at line 329 of file dof_map.h.

References _default_coupling.

Referenced by add_default_ghosting(), and remove_default_ghosting().

329 { return *_default_coupling; }
std::unique_ptr< DefaultCoupling > _default_coupling
Definition: dof_map.h:1587

◆ disable_print_counter_info()

void libMesh::ReferenceCounter::disable_print_counter_info ( )
staticinherited

Definition at line 106 of file reference_counter.C.

References libMesh::ReferenceCounter::_enable_print_counter.

Referenced by libMesh::LibMeshInit::LibMeshInit().

107 {
108  _enable_print_counter = false;
109  return;
110 }

◆ distribute_dofs()

void libMesh::DofMap::distribute_dofs ( MeshBase mesh)

Distribute dofs on the current mesh. Also builds the send list for processor proc_id, which defaults to 0 for ease of use in serial applications.

Definition at line 902 of file dof_map.C.

References _algebraic_ghosting_functors, _coupling_functors, _end_df, _end_old_df, _first_df, _first_old_df, _first_old_scalar_df, _first_scalar_df, _n_dfs, _n_old_dfs, _send_list, add_neighbors_to_send_list(), libMesh::Parallel::Communicator::allgather(), libMesh::ParallelObject::comm(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), libMesh::DofObject::dof_number(), elem_ptr(), libMesh::MeshBase::elements_begin(), end_dof(), libMesh::FEType::family, first_dof(), libMesh::OrderWrapper::get_order(), libMesh::DofObject::invalid_id, invalidate_dofs(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), mesh, libMesh::DofObject::n_comp(), n_dofs(), libMesh::ParallelObject::n_processors(), n_SCALAR_dofs(), n_variables(), libMesh::DofObject::n_vars(), node_ptr(), libMesh::MeshBase::nodes_begin(), libMesh::on_command_line(), libMesh::FEType::order, libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), reinit(), libMesh::SCALAR, set_nonlocal_dof_objects(), sys_number(), libMesh::Variable::type(), and variable().

Referenced by libMesh::EquationSystems::allgather(), and libMesh::EquationSystems::reinit_solutions().

903 {
904  // This function must be run on all processors at once
905  parallel_object_only();
906 
907  // Log how long it takes to distribute the degrees of freedom
908  LOG_SCOPE("distribute_dofs()", "DofMap");
909 
910  libmesh_assert (mesh.is_prepared());
911 
912  const processor_id_type proc_id = this->processor_id();
913  const processor_id_type n_proc = this->n_processors();
914 
915  // libmesh_assert_greater (this->n_variables(), 0);
916  libmesh_assert_less (proc_id, n_proc);
917 
918  // re-init in case the mesh has changed
919  this->reinit(mesh);
920 
921  // By default distribute variables in a
922  // var-major fashion, but allow run-time
923  // specification
924  bool node_major_dofs = libMesh::on_command_line ("--node-major-dofs");
925 
926  // The DOF counter, will be incremented as we encounter
927  // new degrees of freedom
928  dof_id_type next_free_dof = 0;
929 
930  // Clear the send list before we rebuild it
931  _send_list.clear();
932 
933  // Set temporary DOF indices on this processor
934  if (node_major_dofs)
935  this->distribute_local_dofs_node_major (next_free_dof, mesh);
936  else
937  this->distribute_local_dofs_var_major (next_free_dof, mesh);
938 
939  // Get DOF counts on all processors
940  std::vector<dof_id_type> dofs_on_proc(n_proc, 0);
941  this->comm().allgather(next_free_dof, dofs_on_proc);
942 
943  // Resize and fill the _first_df and _end_df arrays
944 #ifdef LIBMESH_ENABLE_AMR
947 #endif
948 
949  _first_df.resize(n_proc);
950  _end_df.resize (n_proc);
951 
952  // Get DOF offsets
953  _first_df[0] = 0;
954  for (processor_id_type i=1; i < n_proc; ++i)
955  _first_df[i] = _end_df[i-1] = _first_df[i-1] + dofs_on_proc[i-1];
956  _end_df[n_proc-1] = _first_df[n_proc-1] + dofs_on_proc[n_proc-1];
957 
958  // Clear all the current DOF indices
959  // (distribute_dofs expects them cleared!)
960  this->invalidate_dofs(mesh);
961 
962  next_free_dof = _first_df[proc_id];
963 
964  // Set permanent DOF indices on this processor
965  if (node_major_dofs)
966  this->distribute_local_dofs_node_major (next_free_dof, mesh);
967  else
968  this->distribute_local_dofs_var_major (next_free_dof, mesh);
969 
970  libmesh_assert_equal_to (next_free_dof, _end_df[proc_id]);
971 
972  //------------------------------------------------------------
973  // At this point, all n_comp and dof_number values on local
974  // DofObjects should be correct, but a DistributedMesh might have
975  // incorrect values on non-local DofObjects. Let's request the
976  // correct values from each other processor.
977 
978  if (this->n_processors() > 1)
979  {
980  this->set_nonlocal_dof_objects(mesh.nodes_begin(),
981  mesh.nodes_end(),
983 
984  this->set_nonlocal_dof_objects(mesh.elements_begin(),
985  mesh.elements_end(),
987  }
988 
989 #ifdef DEBUG
990  {
991  const unsigned int
992  sys_num = this->sys_number();
993 
994  // Processors should all agree on DoF ids for the newly numbered
995  // system.
997 
998  // DoF processor ids should match DofObject processor ids
999  for (auto & node : mesh.node_ptr_range())
1000  {
1001  DofObject const * const dofobj = node;
1002  const processor_id_type obj_proc_id = dofobj->processor_id();
1003 
1004  for (unsigned int v=0; v != dofobj->n_vars(sys_num); ++v)
1005  for (unsigned int c=0; c != dofobj->n_comp(sys_num,v); ++c)
1006  {
1007  const dof_id_type dofid = dofobj->dof_number(sys_num,v,c);
1008  libmesh_assert_greater_equal (dofid, this->first_dof(obj_proc_id));
1009  libmesh_assert_less (dofid, this->end_dof(obj_proc_id));
1010  }
1011  }
1012 
1013  for (auto & elem : mesh.element_ptr_range())
1014  {
1015  DofObject const * const dofobj = elem;
1016  const processor_id_type obj_proc_id = dofobj->processor_id();
1017 
1018  for (unsigned int v=0; v != dofobj->n_vars(sys_num); ++v)
1019  for (unsigned int c=0; c != dofobj->n_comp(sys_num,v); ++c)
1020  {
1021  const dof_id_type dofid = dofobj->dof_number(sys_num,v,c);
1022  libmesh_assert_greater_equal (dofid, this->first_dof(obj_proc_id));
1023  libmesh_assert_less (dofid, this->end_dof(obj_proc_id));
1024  }
1025  }
1026  }
1027 #endif
1028 
1029  // Set the total number of degrees of freedom, then start finding
1030  // SCALAR degrees of freedom
1031 #ifdef LIBMESH_ENABLE_AMR
1032  _n_old_dfs = _n_dfs;
1034 #endif
1035  _n_dfs = _end_df[n_proc-1];
1036  _first_scalar_df.clear();
1038  dof_id_type current_SCALAR_dof_index = n_dofs() - n_SCALAR_dofs();
1039 
1040  // Calculate and cache the initial DoF indices for SCALAR variables.
1041  // This is an O(N_vars) calculation so we want to do it once per
1042  // renumbering rather than once per SCALAR_dof_indices() call
1043 
1044  for (unsigned int v=0; v<this->n_variables(); v++)
1045  if (this->variable(v).type().family == SCALAR)
1046  {
1047  _first_scalar_df[v] = current_SCALAR_dof_index;
1048  current_SCALAR_dof_index += this->variable(v).type().order.get_order();
1049  }
1050 
1051  // Allow our GhostingFunctor objects to reinit if necessary
1052  for (const auto & gf : _algebraic_ghosting_functors)
1053  {
1054  libmesh_assert(gf);
1055  gf->dofmap_reinit();
1056  }
1057 
1058  for (const auto & gf : _coupling_functors)
1059  {
1060  libmesh_assert(gf);
1061  gf->dofmap_reinit();
1062  }
1063 
1064  // Note that in the add_neighbors_to_send_list nodes on processor
1065  // boundaries that are shared by multiple elements are added for
1066  // each element.
1068 
1069  // Here we used to clean up that data structure; now System and
1070  // EquationSystems call that for us, after we've added constraint
1071  // dependencies to the send_list too.
1072  // this->sort_send_list ();
1073 }
FEFamily family
Definition: fe_type.h:204
void distribute_local_dofs_node_major(dof_id_type &next_free_dof, MeshBase &mesh)
Definition: dof_map.C:1163
dof_id_type n_SCALAR_dofs() const
Definition: dof_map.h:579
void allgather(const T &send, std::vector< T, A > &recv) const
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1547
MeshBase & mesh
uint8_t processor_id_type
Definition: id_types.h:99
unsigned int n_variables() const
Definition: dof_map.h:541
const Parallel::Communicator & comm() const
std::set< GhostingFunctor * > _algebraic_ghosting_functors
Definition: dof_map.h:1605
std::vector< dof_id_type > _end_old_df
Definition: dof_map.h:1672
OrderWrapper order
Definition: fe_type.h:198
std::vector< dof_id_type > _first_old_df
Definition: dof_map.h:1667
unsigned int sys_number() const
Definition: dof_map.h:1744
std::vector< dof_id_type > _first_scalar_df
Definition: dof_map.h:1541
processor_id_type n_processors() const
dof_id_type n_dofs() const
Definition: dof_map.h:574
void add_neighbors_to_send_list(MeshBase &mesh)
Definition: dof_map.C:1499
std::vector< dof_id_type > _first_old_scalar_df
Definition: dof_map.h:1678
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:1762
void libmesh_assert_valid_dof_ids(const MeshBase &mesh, unsigned int sysnum)
Definition: mesh_tools.C:1571
void set_nonlocal_dof_objects(iterator_type objects_begin, iterator_type objects_end, MeshBase &mesh, dofobject_accessor objects)
Definition: dof_map.C:321
static const dof_id_type invalid_id
Definition: dof_object.h:347
void reinit(MeshBase &mesh)
Definition: dof_map.C:474
dof_id_type end_dof() const
Definition: dof_map.h:644
int get_order() const
Definition: fe_type.h:78
DofObject * elem_ptr(MeshBase &mesh, dof_id_type i) const
Definition: dof_map.C:313
void invalidate_dofs(MeshBase &mesh) const
Definition: dof_map.C:813
dof_id_type first_dof() const
Definition: dof_map.h:602
dof_id_type _n_old_dfs
Definition: dof_map.h:1662
std::set< GhostingFunctor * > _coupling_functors
Definition: dof_map.h:1618
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1535
std::vector< dof_id_type > _first_df
Definition: dof_map.h:1530
DofObject * node_ptr(MeshBase &mesh, dof_id_type i) const
Definition: dof_map.C:306
bool on_command_line(std::string arg)
Definition: libmesh.C:876
processor_id_type processor_id() const
void distribute_local_dofs_var_major(dof_id_type &next_free_dof, MeshBase &mesh)
Definition: dof_map.C:1302
uint8_t dof_id_type
Definition: id_types.h:64
dof_id_type _n_dfs
Definition: dof_map.h:1649
const FEType & type() const
Definition: variable.h:119

◆ distribute_local_dofs_node_major()

void libMesh::DofMap::distribute_local_dofs_node_major ( dof_id_type next_free_dof,
MeshBase mesh 
)
private

Distributes the global degrees of freedom for dofs on this processor. In this format all the degrees of freedom at a node/element are in contiguous blocks. Starts at index next_free_dof, and increments it to the post-final index. If build_send_list is true, builds the send list. If false, clears and reserves the send list.

Note
The degrees of freedom for a given variable are not in contiguous blocks, as in the case of distribute_local_dofs_var_major.

Definition at line 1163 of file dof_map.C.

References _n_SCALAR_dofs, libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::OrderWrapper::get_order(), libMesh::DofObject::invalid_id, mesh, libMesh::DofObject::n_comp_group(), n_nodes, libMesh::ParallelObject::n_processors(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::FEType::order, libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), libMesh::SCALAR, libMesh::DofObject::set_vg_dof_base(), sys_number(), libMesh::Variable::type(), variable_group(), and libMesh::DofObject::vg_dof_base().

Referenced by distribute_dofs().

1165 {
1166  const unsigned int sys_num = this->sys_number();
1167  const unsigned int n_var_groups = this->n_variable_groups();
1168 
1169  // Our numbering here must be kept consistent with the numbering
1170  // scheme assumed by DofMap::local_variable_indices!
1171 
1172  //-------------------------------------------------------------------------
1173  // First count and assign temporary numbers to local dofs
1174  for (auto & elem : mesh.active_local_element_ptr_range())
1175  {
1176  // Only number dofs connected to active
1177  // elements on this processor.
1178  const unsigned int n_nodes = elem->n_nodes();
1179 
1180  // First number the nodal DOFS
1181  for (unsigned int n=0; n<n_nodes; n++)
1182  {
1183  Node & node = elem->node_ref(n);
1184 
1185  for (unsigned vg=0; vg<n_var_groups; vg++)
1186  {
1187  const VariableGroup & vg_description(this->variable_group(vg));
1188 
1189  if ((vg_description.type().family != SCALAR) &&
1190  (vg_description.active_on_subdomain(elem->subdomain_id())))
1191  {
1192  // assign dof numbers (all at once) if this is
1193  // our node and if they aren't already there
1194  if ((node.n_comp_group(sys_num,vg) > 0) &&
1195  (node.processor_id() == this->processor_id()) &&
1196  (node.vg_dof_base(sys_num,vg) ==
1198  {
1199  node.set_vg_dof_base(sys_num, vg,
1200  next_free_dof);
1201  next_free_dof += (vg_description.n_variables()*
1202  node.n_comp_group(sys_num,vg));
1203  //node.debug_buffer();
1204  }
1205  }
1206  }
1207  }
1208 
1209  // Now number the element DOFS
1210  for (unsigned vg=0; vg<n_var_groups; vg++)
1211  {
1212  const VariableGroup & vg_description(this->variable_group(vg));
1213 
1214  if ((vg_description.type().family != SCALAR) &&
1215  (vg_description.active_on_subdomain(elem->subdomain_id())))
1216  if (elem->n_comp_group(sys_num,vg) > 0)
1217  {
1218  libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg),
1220 
1221  elem->set_vg_dof_base(sys_num,
1222  vg,
1223  next_free_dof);
1224 
1225  next_free_dof += (vg_description.n_variables()*
1226  elem->n_comp(sys_num,vg));
1227  }
1228  }
1229  } // done looping over elements
1230 
1231 
1232  // we may have missed assigning DOFs to nodes that we own
1233  // but to which we have no connected elements matching our
1234  // variable restriction criterion. this will happen, for example,
1235  // if variable V is restricted to subdomain S. We may not own
1236  // any elements which live in S, but we may own nodes which are
1237  // *connected* to elements which do. in this scenario these nodes
1238  // will presently have unnumbered DOFs. we need to take care of
1239  // them here since we own them and no other processor will touch them.
1240  for (auto & node : mesh.local_node_ptr_range())
1241  for (unsigned vg=0; vg<n_var_groups; vg++)
1242  {
1243  const VariableGroup & vg_description(this->variable_group(vg));
1244 
1245  if (node->n_comp_group(sys_num,vg))
1246  if (node->vg_dof_base(sys_num,vg) == DofObject::invalid_id)
1247  {
1248  node->set_vg_dof_base (sys_num,
1249  vg,
1250  next_free_dof);
1251 
1252  next_free_dof += (vg_description.n_variables()*
1253  node->n_comp(sys_num,vg));
1254  }
1255  }
1256 
1257  // Finally, count up the SCALAR dofs
1258  this->_n_SCALAR_dofs = 0;
1259  for (unsigned vg=0; vg<n_var_groups; vg++)
1260  {
1261  const VariableGroup & vg_description(this->variable_group(vg));
1262 
1263  if (vg_description.type().family == SCALAR)
1264  {
1265  this->_n_SCALAR_dofs += (vg_description.n_variables()*
1266  vg_description.type().order.get_order());
1267  continue;
1268  }
1269  }
1270 
1271  // Only increment next_free_dof if we're on the processor
1272  // that holds this SCALAR variable
1273  if (this->processor_id() == (this->n_processors()-1))
1274  next_free_dof += _n_SCALAR_dofs;
1275 
1276 #ifdef DEBUG
1277  {
1278  // libMesh::out << "next_free_dof=" << next_free_dof << std::endl
1279  // << "_n_SCALAR_dofs=" << _n_SCALAR_dofs << std::endl;
1280 
1281  // Make sure we didn't miss any nodes
1282  MeshTools::libmesh_assert_valid_procids<Node>(mesh);
1283 
1284  for (auto & node : mesh.local_node_ptr_range())
1285  {
1286  unsigned int n_var_g = node->n_var_groups(this->sys_number());
1287  for (unsigned int vg=0; vg != n_var_g; ++vg)
1288  {
1289  unsigned int n_comp_g =
1290  node->n_comp_group(this->sys_number(), vg);
1291  dof_id_type my_first_dof = n_comp_g ?
1292  node->vg_dof_base(this->sys_number(), vg) : 0;
1293  libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
1294  }
1295  }
1296  }
1297 #endif // DEBUG
1298 }
unsigned int n_variable_groups() const
Definition: dof_map.h:533
MeshBase & mesh
unsigned int sys_number() const
Definition: dof_map.h:1744
processor_id_type n_processors() const
const dof_id_type n_nodes
Definition: tecplot_io.C:68
dof_id_type _n_SCALAR_dofs
Definition: dof_map.h:1655
static const dof_id_type invalid_id
Definition: dof_object.h:347
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:1752
processor_id_type processor_id() const
uint8_t dof_id_type
Definition: id_types.h:64

◆ distribute_local_dofs_var_major()

void libMesh::DofMap::distribute_local_dofs_var_major ( dof_id_type next_free_dof,
MeshBase mesh 
)
private

Distributes the global degrees of freedom, for dofs on this processor. In this format the local degrees of freedom are in a contiguous block for each variable in the system. Starts at index next_free_dof, and increments it to the post-final index.

Definition at line 1302 of file dof_map.C.

References _n_SCALAR_dofs, libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::OrderWrapper::get_order(), libMesh::DofObject::invalid_id, mesh, libMesh::DofObject::n_comp_group(), n_nodes, libMesh::ParallelObject::n_processors(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::FEType::order, libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), libMesh::SCALAR, libMesh::DofObject::set_vg_dof_base(), sys_number(), libMesh::Variable::type(), variable_group(), and libMesh::DofObject::vg_dof_base().

Referenced by distribute_dofs().

1304 {
1305  const unsigned int sys_num = this->sys_number();
1306  const unsigned int n_var_groups = this->n_variable_groups();
1307 
1308  // Our numbering here must be kept consistent with the numbering
1309  // scheme assumed by DofMap::local_variable_indices!
1310 
1311  //-------------------------------------------------------------------------
1312  // First count and assign temporary numbers to local dofs
1313  for (unsigned vg=0; vg<n_var_groups; vg++)
1314  {
1315  const VariableGroup & vg_description(this->variable_group(vg));
1316 
1317  const unsigned int n_vars_in_group = vg_description.n_variables();
1318 
1319  // Skip the SCALAR dofs
1320  if (vg_description.type().family == SCALAR)
1321  continue;
1322 
1323  for (auto & elem : mesh.active_local_element_ptr_range())
1324  {
1325  // Only number dofs connected to active elements on this
1326  // processor and only variables which are active on on this
1327  // element's subdomain.
1328  if (!vg_description.active_on_subdomain(elem->subdomain_id()))
1329  continue;
1330 
1331  const unsigned int n_nodes = elem->n_nodes();
1332 
1333  // First number the nodal DOFS
1334  for (unsigned int n=0; n<n_nodes; n++)
1335  {
1336  Node & node = elem->node_ref(n);
1337 
1338  // assign dof numbers (all at once) if this is
1339  // our node and if they aren't already there
1340  if ((node.n_comp_group(sys_num,vg) > 0) &&
1341  (node.processor_id() == this->processor_id()) &&
1342  (node.vg_dof_base(sys_num,vg) ==
1344  {
1345  node.set_vg_dof_base(sys_num, vg, next_free_dof);
1346 
1347  next_free_dof += (n_vars_in_group*
1348  node.n_comp_group(sys_num,vg));
1349  }
1350  }
1351 
1352  // Now number the element DOFS
1353  if (elem->n_comp_group(sys_num,vg) > 0)
1354  {
1355  libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg),
1357 
1358  elem->set_vg_dof_base(sys_num,
1359  vg,
1360  next_free_dof);
1361 
1362  next_free_dof += (n_vars_in_group*
1363  elem->n_comp_group(sys_num,vg));
1364  }
1365  } // end loop on elements
1366 
1367  // we may have missed assigning DOFs to nodes that we own
1368  // but to which we have no connected elements matching our
1369  // variable restriction criterion. this will happen, for example,
1370  // if variable V is restricted to subdomain S. We may not own
1371  // any elements which live in S, but we may own nodes which are
1372  // *connected* to elements which do. in this scenario these nodes
1373  // will presently have unnumbered DOFs. we need to take care of
1374  // them here since we own them and no other processor will touch them.
1375  for (auto & node : mesh.local_node_ptr_range())
1376  if (node->n_comp_group(sys_num,vg))
1377  if (node->vg_dof_base(sys_num,vg) == DofObject::invalid_id)
1378  {
1379  node->set_vg_dof_base (sys_num,
1380  vg,
1381  next_free_dof);
1382 
1383  next_free_dof += (n_vars_in_group*
1384  node->n_comp_group(sys_num,vg));
1385  }
1386  } // end loop on variable groups
1387 
1388  // Finally, count up the SCALAR dofs
1389  this->_n_SCALAR_dofs = 0;
1390  for (unsigned vg=0; vg<n_var_groups; vg++)
1391  {
1392  const VariableGroup & vg_description(this->variable_group(vg));
1393 
1394  if (vg_description.type().family == SCALAR)
1395  {
1396  this->_n_SCALAR_dofs += (vg_description.n_variables()*
1397  vg_description.type().order.get_order());
1398  continue;
1399  }
1400  }
1401 
1402  // Only increment next_free_dof if we're on the processor
1403  // that holds this SCALAR variable
1404  if (this->processor_id() == (this->n_processors()-1))
1405  next_free_dof += _n_SCALAR_dofs;
1406 
1407 #ifdef DEBUG
1408  {
1409  // Make sure we didn't miss any nodes
1410  MeshTools::libmesh_assert_valid_procids<Node>(mesh);
1411 
1412  for (auto & node : mesh.local_node_ptr_range())
1413  {
1414  unsigned int n_var_g = node->n_var_groups(this->sys_number());
1415  for (unsigned int vg=0; vg != n_var_g; ++vg)
1416  {
1417  unsigned int n_comp_g =
1418  node->n_comp_group(this->sys_number(), vg);
1419  dof_id_type my_first_dof = n_comp_g ?
1420  node->vg_dof_base(this->sys_number(), vg) : 0;
1421  libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
1422  }
1423  }
1424  }
1425 #endif // DEBUG
1426 }
unsigned int n_variable_groups() const
Definition: dof_map.h:533
MeshBase & mesh
unsigned int sys_number() const
Definition: dof_map.h:1744
processor_id_type n_processors() const
const dof_id_type n_nodes
Definition: tecplot_io.C:68
dof_id_type _n_SCALAR_dofs
Definition: dof_map.h:1655
static const dof_id_type invalid_id
Definition: dof_object.h:347
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:1752
processor_id_type processor_id() const
uint8_t dof_id_type
Definition: id_types.h:64

◆ dof_indices() [1/4]

void libMesh::DofMap::dof_indices ( const Elem *const  elem,
std::vector< dof_id_type > &  di 
) const

Fills the vector di with the global degree of freedom indices for the element.

Definition at line 1930 of file dof_map.C.

References _dof_indices(), libMesh::Elem::active(), libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::MeshTools::Subdivision::find_one_ring(), libMesh::Elem::get_nodes(), libMesh::Tri3Subdivision::is_ghost(), n_nodes, libMesh::Elem::n_nodes(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::VariableGroup::number(), libMesh::FEType::order, libMesh::Elem::p_level(), libMesh::SCALAR, SCALAR_dof_indices(), libMesh::Elem::subdomain_id(), libMesh::TRI3SUBDIVISION, libMesh::Variable::type(), libMesh::Elem::type(), and variable_group().

Referenced by libMesh::ExactSolution::_compute_error(), libMesh::UniformRefinementEstimator::_estimate_error(), add_neighbors_to_send_list(), libMesh::HPCoarsenTest::add_projection(), libMesh::EquationSystems::build_discontinuous_solution_vector(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::EquationSystems::build_parallel_solution_vector(), libMesh::System::calculate_norm(), libMesh::FEGenericBase< FEOutputType< T >::type >::coarsened_dof_values(), libMesh::FEGenericBase< FEOutputType< T >::type >::compute_periodic_constraints(), libMesh::FEGenericBase< FEOutputType< T >::type >::compute_proj_constraints(), libMesh::MeshFunction::discontinuous_gradient(), libMesh::MeshFunction::discontinuous_value(), DMCreateDomainDecomposition_libMesh(), DMCreateFieldDecomposition_libMesh(), dof_indices(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::MeshFunction::gradient(), libMesh::MeshFunction::hessian(), libMesh::SystemSubsetBySubdomain::init(), is_evaluable(), libMesh::System::local_dof_indices(), libMesh::DGFEMContext::neighbor_side_fe_reinit(), libMesh::WeightedPatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::PatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::MeshFunction::operator()(), libMesh::BoundaryProjectSolution::operator()(), libMesh::ErrorVector::plot_error(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::FEMContext::pre_fe_reinit(), libMesh::HPCoarsenTest::select_refinement(), libMesh::PetscDMWrapper::set_point_range_in_section(), libMesh::SparsityPattern::Build::sorted_connected_dofs(), libMesh::EnsightIO::write_scalar_ascii(), and libMesh::EnsightIO::write_vector_ascii().

1932 {
1933  // We now allow elem==nullptr to request just SCALAR dofs
1934  // libmesh_assert(elem);
1935 
1936  // If we are asking for current indices on an element, it ought to
1937  // be an active element (or a Side proxy, which also thinks it's
1938  // active)
1939  libmesh_assert(!elem || elem->active());
1940 
1941  LOG_SCOPE("dof_indices()", "DofMap");
1942 
1943  // Clear the DOF indices vector
1944  di.clear();
1945 
1946  const unsigned int n_var_groups = this->n_variable_groups();
1947 
1948 #ifdef DEBUG
1949  // Check that sizes match in DEBUG mode
1950  std::size_t tot_size = 0;
1951 #endif
1952 
1953  if (elem && elem->type() == TRI3SUBDIVISION)
1954  {
1955  // Subdivision surface FE require the 1-ring around elem
1956  const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
1957 
1958  // Ghost subdivision elements have no real dofs
1959  if (!sd_elem->is_ghost())
1960  {
1961  // Determine the nodes contributing to element elem
1962  std::vector<const Node *> elem_nodes;
1963  MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
1964 
1965  // Get the dof numbers
1966  for (unsigned int vg=0; vg<n_var_groups; vg++)
1967  {
1968  const VariableGroup & var = this->variable_group(vg);
1969  const unsigned int vars_in_group = var.n_variables();
1970 
1971  if (var.type().family == SCALAR &&
1972  var.active_on_subdomain(elem->subdomain_id()))
1973  {
1974  for (unsigned int vig=0; vig != vars_in_group; ++vig)
1975  {
1976 #ifdef DEBUG
1977  tot_size += var.type().order;
1978 #endif
1979  std::vector<dof_id_type> di_new;
1980  this->SCALAR_dof_indices(di_new,var.number(vig));
1981  di.insert( di.end(), di_new.begin(), di_new.end());
1982  }
1983  }
1984  else
1985  for (unsigned int vig=0; vig != vars_in_group; ++vig)
1986  {
1987  _dof_indices(*elem, elem->p_level(), di, vg, vig,
1988  elem_nodes.data(),
1989  cast_int<unsigned int>(elem_nodes.size())
1990 #ifdef DEBUG
1991  , var.number(vig), tot_size
1992 #endif
1993  );
1994  }
1995  }
1996  }
1997 
1998  return;
1999  }
2000 
2001  // Get the dof numbers for each variable
2002  const unsigned int n_nodes = elem ? elem->n_nodes() : 0;
2003  for (unsigned int vg=0; vg<n_var_groups; vg++)
2004  {
2005  const VariableGroup & var = this->variable_group(vg);
2006  const unsigned int vars_in_group = var.n_variables();
2007 
2008  if (var.type().family == SCALAR &&
2009  (!elem ||
2010  var.active_on_subdomain(elem->subdomain_id())))
2011  {
2012  for (unsigned int vig=0; vig != vars_in_group; ++vig)
2013  {
2014 #ifdef DEBUG
2015  tot_size += var.type().order;
2016 #endif
2017  std::vector<dof_id_type> di_new;
2018  this->SCALAR_dof_indices(di_new,var.number(vig));
2019  di.insert( di.end(), di_new.begin(), di_new.end());
2020  }
2021  }
2022  else if (elem)
2023  for (unsigned int vig=0; vig != vars_in_group; ++vig)
2024  {
2025  _dof_indices(*elem, elem->p_level(), di, vg, vig,
2026  elem->get_nodes(), n_nodes
2027 #ifdef DEBUG
2028  , var.number(vig), tot_size
2029 #endif
2030  );
2031  }
2032  }
2033 
2034 #ifdef DEBUG
2035  libmesh_assert_equal_to (tot_size, di.size());
2036 #endif
2037 }
void _dof_indices(const Elem &elem, int p_level, std::vector< dof_id_type > &di, const unsigned int vg, const unsigned int vig, const Node *const *nodes, unsigned int n_nodes #ifdef DEBUG, const unsigned int v, std::size_t &tot_size #endif) const
Definition: dof_map.C:2209
unsigned int n_variable_groups() const
Definition: dof_map.h:533
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Definition: dof_map.C:2348
void find_one_ring(const Tri3Subdivision *elem, std::vector< const Node *> &nodes)
const dof_id_type n_nodes
Definition: tecplot_io.C:68
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:1752

◆ dof_indices() [2/4]

void libMesh::DofMap::dof_indices ( const Elem *const  elem,
std::vector< dof_id_type > &  di,
const unsigned int  vn,
int  p_level = -12345 
) const

Fills the vector di with the global degree of freedom indices for the element. For one variable, and potentially for a non-default element p refinement level

Definition at line 2040 of file dof_map.C.

References _dof_indices(), _variable_group_numbers, libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::MeshTools::Subdivision::find_one_ring(), libMesh::Elem::get_nodes(), libMesh::Tri3Subdivision::is_ghost(), libMesh::Elem::n_nodes(), libMesh::VariableGroup::number(), libMesh::FEType::order, libMesh::Elem::p_level(), libMesh::SCALAR, SCALAR_dof_indices(), libMesh::Elem::subdomain_id(), libMesh::TRI3SUBDIVISION, libMesh::Variable::type(), libMesh::Elem::type(), and variable_group().

2044 {
2045  // We now allow elem==nullptr to request just SCALAR dofs
2046  // libmesh_assert(elem);
2047 
2048  LOG_SCOPE("dof_indices()", "DofMap");
2049 
2050  // Clear the DOF indices vector
2051  di.clear();
2052 
2053  // Use the default p refinement level?
2054  if (p_level == -12345)
2055  p_level = elem ? elem->p_level() : 0;
2056 
2057  const unsigned int vg = this->_variable_group_numbers[vn];
2058  const VariableGroup & var = this->variable_group(vg);
2059  const unsigned int vig = vn - var.number();
2060 
2061 #ifdef DEBUG
2062  // Check that sizes match in DEBUG mode
2063  std::size_t tot_size = 0;
2064 #endif
2065 
2066  if (elem && elem->type() == TRI3SUBDIVISION)
2067  {
2068  // Subdivision surface FE require the 1-ring around elem
2069  const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
2070 
2071  // Ghost subdivision elements have no real dofs
2072  if (!sd_elem->is_ghost())
2073  {
2074  // Determine the nodes contributing to element elem
2075  std::vector<const Node *> elem_nodes;
2076  MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
2077 
2078  _dof_indices(*elem, p_level, di, vg, vig, elem_nodes.data(),
2079  cast_int<unsigned int>(elem_nodes.size())
2080 #ifdef DEBUG
2081  , vn, tot_size
2082 #endif
2083  );
2084  }
2085 
2086  return;
2087  }
2088 
2089  // Get the dof numbers
2090  if (var.type().family == SCALAR &&
2091  (!elem ||
2092  var.active_on_subdomain(elem->subdomain_id())))
2093  {
2094 #ifdef DEBUG
2095  tot_size += var.type().order;
2096 #endif
2097  std::vector<dof_id_type> di_new;
2098  this->SCALAR_dof_indices(di_new,vn);
2099  di.insert( di.end(), di_new.begin(), di_new.end());
2100  }
2101  else if (elem)
2102  _dof_indices(*elem, p_level, di, vg, vig, elem->get_nodes(),
2103  elem->n_nodes()
2104 #ifdef DEBUG
2105  , vn, tot_size
2106 #endif
2107  );
2108 
2109 #ifdef DEBUG
2110  libmesh_assert_equal_to (tot_size, di.size());
2111 #endif
2112 }
void _dof_indices(const Elem &elem, int p_level, std::vector< dof_id_type > &di, const unsigned int vg, const unsigned int vig, const Node *const *nodes, unsigned int n_nodes #ifdef DEBUG, const unsigned int v, std::size_t &tot_size #endif) const
Definition: dof_map.C:2209
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Definition: dof_map.C:2348
void find_one_ring(const Tri3Subdivision *elem, std::vector< const Node *> &nodes)
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:1752
std::vector< unsigned int > _variable_group_numbers
Definition: dof_map.h:1508

◆ dof_indices() [3/4]

void libMesh::DofMap::dof_indices ( const Node *const  node,
std::vector< dof_id_type > &  di 
) const

Fills the vector di with the global degree of freedom indices for the node.

Definition at line 2115 of file dof_map.C.

References libMesh::DofObject::dof_number(), libMesh::FEType::family, libMesh::DofObject::invalid_id, libMesh::DofObject::n_comp_group(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::VariableGroup::number(), libMesh::SCALAR, SCALAR_dof_indices(), sys_number(), libMesh::Variable::type(), and variable_group().

2117 {
2118  // We allow node==nullptr to request just SCALAR dofs
2119  // libmesh_assert(elem);
2120 
2121  LOG_SCOPE("dof_indices(Node)", "DofMap");
2122 
2123  // Clear the DOF indices vector
2124  di.clear();
2125 
2126  const unsigned int n_var_groups = this->n_variable_groups();
2127  const unsigned int sys_num = this->sys_number();
2128 
2129  // Get the dof numbers
2130  for (unsigned int vg=0; vg<n_var_groups; vg++)
2131  {
2132  const VariableGroup & var = this->variable_group(vg);
2133  const unsigned int vars_in_group = var.n_variables();
2134 
2135  if (var.type().family == SCALAR)
2136  {
2137  for (unsigned int vig=0; vig != vars_in_group; ++vig)
2138  {
2139  std::vector<dof_id_type> di_new;
2140  this->SCALAR_dof_indices(di_new,var.number(vig));
2141  di.insert( di.end(), di_new.begin(), di_new.end());
2142  }
2143  }
2144  else
2145  {
2146  const int n_comp = node->n_comp_group(sys_num,vg);
2147  for (unsigned int vig=0; vig != vars_in_group; ++vig)
2148  {
2149  for (int i=0; i != n_comp; ++i)
2150  {
2151  const dof_id_type d =
2152  node->dof_number(sys_num, vg, vig, i, n_comp);
2153  libmesh_assert_not_equal_to
2154  (d, DofObject::invalid_id);
2155  di.push_back(d);
2156  }
2157  }
2158  }
2159  }
2160 }
unsigned int n_variable_groups() const
Definition: dof_map.h:533
unsigned int sys_number() const
Definition: dof_map.h:1744
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Definition: dof_map.C:2348
static const dof_id_type invalid_id
Definition: dof_object.h:347
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:1752
uint8_t dof_id_type
Definition: id_types.h:64

◆ dof_indices() [4/4]

void libMesh::DofMap::dof_indices ( const Node *const  node,
std::vector< dof_id_type > &  di,
const unsigned int  vn 
) const

Fills the vector di with the global degree of freedom indices for the node. For one variable vn.

Definition at line 2163 of file dof_map.C.

References _variable_group_numbers, dof_indices(), libMesh::DofObject::dof_number(), libMesh::FEType::family, libMesh::DofObject::invalid_id, libMesh::invalid_uint, libMesh::DofObject::n_comp_group(), libMesh::VariableGroup::number(), libMesh::SCALAR, SCALAR_dof_indices(), sys_number(), libMesh::Variable::type(), and variable_group().

2166 {
2167  if (vn == libMesh::invalid_uint)
2168  {
2169  this->dof_indices(node, di);
2170  return;
2171  }
2172 
2173  // We allow node==nullptr to request just SCALAR dofs
2174  // libmesh_assert(elem);
2175 
2176  LOG_SCOPE("dof_indices(Node)", "DofMap");
2177 
2178  // Clear the DOF indices vector
2179  di.clear();
2180 
2181  const unsigned int sys_num = this->sys_number();
2182 
2183  // Get the dof numbers
2184  const unsigned int vg = this->_variable_group_numbers[vn];
2185  const VariableGroup & var = this->variable_group(vg);
2186 
2187  if (var.type().family == SCALAR)
2188  {
2189  std::vector<dof_id_type> di_new;
2190  this->SCALAR_dof_indices(di_new,vn);
2191  di.insert( di.end(), di_new.begin(), di_new.end());
2192  }
2193  else
2194  {
2195  const unsigned int vig = vn - var.number();
2196  const int n_comp = node->n_comp_group(sys_num,vg);
2197  for (int i=0; i != n_comp; ++i)
2198  {
2199  const dof_id_type d =
2200  node->dof_number(sys_num, vg, vig, i, n_comp);
2201  libmesh_assert_not_equal_to
2202  (d, DofObject::invalid_id);
2203  di.push_back(d);
2204  }
2205  }
2206 }
const unsigned int invalid_uint
Definition: libmesh.h:245
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition: dof_map.C:1930
unsigned int sys_number() const
Definition: dof_map.h:1744
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Definition: dof_map.C:2348
static const dof_id_type invalid_id
Definition: dof_object.h:347
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:1752
std::vector< unsigned int > _variable_group_numbers
Definition: dof_map.h:1508
uint8_t dof_id_type
Definition: id_types.h:64

◆ dof_owner()

processor_id_type libMesh::DofMap::dof_owner ( const dof_id_type  dof) const
inline
Returns
The processor id that owns the dof index dof

Definition at line 650 of file dof_map.h.

References _end_df.

Referenced by libMesh::PetscDMWrapper::build_sf().

651  { std::vector<dof_id_type>::const_iterator ub =
652  std::upper_bound(_end_df.begin(), _end_df.end(), dof);
653  libmesh_assert (ub != _end_df.end());
654  return cast_int<processor_id_type>(ub - _end_df.begin());
655  }
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1535

◆ elem_ptr()

DofObject * libMesh::DofMap::elem_ptr ( MeshBase mesh,
dof_id_type  i 
) const
private
Returns
The Elem pointer with index i from the mesh.

Definition at line 313 of file dof_map.C.

References mesh.

Referenced by distribute_dofs().

314 {
315  return mesh.elem_ptr(i);
316 }
MeshBase & mesh

◆ enable_print_counter_info()

void libMesh::ReferenceCounter::enable_print_counter_info ( )
staticinherited

Methods to enable/disable the reference counter output from print_info()

Definition at line 100 of file reference_counter.C.

References libMesh::ReferenceCounter::_enable_print_counter.

101 {
102  _enable_print_counter = true;
103  return;
104 }

◆ end_dof() [1/2]

dof_id_type libMesh::DofMap::end_dof ( const processor_id_type  proc) const
inline
Returns
The first dof index that is after all indices local to processor proc.

Analogous to the end() member function of STL containers.

Definition at line 641 of file dof_map.h.

References _end_df.

Referenced by DMCreateDomainDecomposition_libMesh(), DMCreateFieldDecomposition_libMesh(), libMesh::SparsityPattern::Build::handle_vi_vj(), libMesh::SystemSubsetBySubdomain::init(), libMesh::CondensedEigenSystem::initialize_condensed_dofs(), libMesh::SparsityPattern::Build::join(), libMesh::System::local_dof_indices(), libMesh::SparsityPattern::Build::operator()(), and libMesh::SparsityPattern::Build::parallel_sync().

642  { libmesh_assert_less (proc, _end_df.size()); return _end_df[proc]; }
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1535

◆ end_dof() [2/2]

dof_id_type libMesh::DofMap::end_dof ( ) const
inline

Definition at line 644 of file dof_map.h.

References libMesh::ParallelObject::processor_id().

Referenced by distribute_dofs(), and local_index().

645  { return this->end_dof(this->processor_id()); }
dof_id_type end_dof() const
Definition: dof_map.h:644
processor_id_type processor_id() const

◆ end_old_dof() [1/2]

dof_id_type libMesh::DofMap::end_old_dof ( const processor_id_type  proc) const
inline
Returns
The first old dof index that is after all indices local to processor proc.

Analogous to the end() member function of STL containers.

Definition at line 664 of file dof_map.h.

References _end_old_df.

Referenced by libMesh::BuildProjectionList::operator()().

665  { libmesh_assert_less (proc, _end_old_df.size()); return _end_old_df[proc]; }
std::vector< dof_id_type > _end_old_df
Definition: dof_map.h:1672

◆ end_old_dof() [2/2]

dof_id_type libMesh::DofMap::end_old_dof ( ) const
inline

Definition at line 667 of file dof_map.h.

References libMesh::ParallelObject::processor_id().

668  { return this->end_old_dof(this->processor_id()); }
dof_id_type end_old_dof() const
Definition: dof_map.h:667
processor_id_type processor_id() const

◆ enforce_adjoint_constraints_exactly()

void libMesh::DofMap::enforce_adjoint_constraints_exactly ( NumericVector< Number > &  v,
unsigned int  q 
) const
inline

Heterogenously constrains the numeric vector v, which represents an adjoint solution defined on the mesh for quantity fo interest q. For homogeneous constraints, use enforce_constraints_exactly instead

Definition at line 2170 of file dof_map_constraints.C.

References libMesh::NumericVector< T >::close(), libMesh::NumericVector< T >::closed(), libMesh::NumericVector< T >::get(), libMesh::GHOSTED, libMesh::NumericVector< T >::localize(), libMesh::PARALLEL, libMesh::SERIAL, libMesh::NumericVector< T >::set(), libMesh::NumericVector< T >::size(), and libMesh::NumericVector< T >::type().

Referenced by libMesh::ImplicitSystem::adjoint_solve(), and libMesh::AdjointRefinementEstimator::estimate_error().

2172 {
2173  parallel_object_only();
2174 
2175  if (!this->n_constrained_dofs())
2176  return;
2177 
2178  LOG_SCOPE("enforce_adjoint_constraints_exactly()", "DofMap");
2179 
2180  NumericVector<Number> * v_local = nullptr; // will be initialized below
2181  NumericVector<Number> * v_global = nullptr; // will be initialized below
2182  std::unique_ptr<NumericVector<Number>> v_built;
2183  if (v.type() == SERIAL)
2184  {
2185  v_built = NumericVector<Number>::build(this->comm());
2186  v_built->init(this->n_dofs(), this->n_local_dofs(), true, PARALLEL);
2187  v_built->close();
2188 
2189  for (dof_id_type i=v_built->first_local_index();
2190  i<v_built->last_local_index(); i++)
2191  v_built->set(i, v(i));
2192  v_built->close();
2193  v_global = v_built.get();
2194 
2195  v_local = &v;
2196  libmesh_assert (v_local->closed());
2197  }
2198  else if (v.type() == PARALLEL)
2199  {
2200  v_built = NumericVector<Number>::build(this->comm());
2201  v_built->init (v.size(), v.size(), true, SERIAL);
2202  v.localize(*v_built);
2203  v_built->close();
2204  v_local = v_built.get();
2205 
2206  v_global = &v;
2207  }
2208  else if (v.type() == GHOSTED)
2209  {
2210  v_local = &v;
2211  v_global = &v;
2212  }
2213  else // unknown v.type()
2214  libmesh_error_msg("ERROR: Unknown v.type() == " << v.type());
2215 
2216  // We should never hit these asserts because we should error-out in
2217  // else clause above. Just to be sure we don't try to use v_local
2218  // and v_global uninitialized...
2219  libmesh_assert(v_local);
2220  libmesh_assert(v_global);
2221 
2222  // Do we have any non_homogeneous constraints?
2223  const AdjointDofConstraintValues::const_iterator
2224  adjoint_constraint_map_it = _adjoint_constraint_values.find(q);
2225  const DofConstraintValueMap * constraint_map =
2226  (adjoint_constraint_map_it == _adjoint_constraint_values.end()) ?
2227  nullptr : &adjoint_constraint_map_it->second;
2228 
2229  for (const auto & pr : _dof_constraints)
2230  {
2231  dof_id_type constrained_dof = pr.first;
2232  if (!this->local_index(constrained_dof))
2233  continue;
2234 
2235  const DofConstraintRow constraint_row = pr.second;
2236 
2237  Number exact_value = 0;
2238  if (constraint_map)
2239  {
2240  const DofConstraintValueMap::const_iterator
2241  adjoint_constraint_it =
2242  constraint_map->find(constrained_dof);
2243  if (adjoint_constraint_it != constraint_map->end())
2244  exact_value = adjoint_constraint_it->second;
2245  }
2246 
2247  for (const auto & j : constraint_row)
2248  exact_value += j.second * (*v_local)(j.first);
2249 
2250  v_global->set(constrained_dof, exact_value);
2251  }
2252 
2253  // If the old vector was serial, we probably need to send our values
2254  // to other processors
2255  if (v.type() == SERIAL)
2256  {
2257 #ifndef NDEBUG
2258  v_global->close();
2259 #endif
2260  v_global->localize (v);
2261  }
2262  v.close();
2263 }
dof_id_type n_local_dofs() const
Definition: dof_map.h:584
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
virtual numeric_index_type size() const =0
const Parallel::Communicator & comm() const
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1691
dof_id_type n_dofs() const
Definition: dof_map.h:574
DofConstraints _dof_constraints
Definition: dof_map.h:1687
virtual void close()=0
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package())
virtual bool closed() const
ParallelType type() const
dof_id_type n_constrained_dofs() const
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
Definition: dof_map.h:97
virtual void set(const numeric_index_type i, const T value)=0
uint8_t dof_id_type
Definition: id_types.h:64
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:738
virtual void localize(std::vector< T > &v_local) const =0

◆ enforce_constraints_exactly()

void libMesh::DofMap::enforce_constraints_exactly ( const System system,
NumericVector< Number > *  v = nullptr,
bool  homogeneous = false 
) const
inline

Constrains the numeric vector v, which represents a solution defined on the mesh. This may need to be used after a linear solve, if your linear solver's solutions do not satisfy your DoF constraints to a tight enough tolerance.

If v == nullptr, the system solution vector is constrained

If homogeneous == true, heterogeneous constraints are enforced as if they were homogeneous. This might be appropriate for e.g. a vector representing a difference between two heterogeneously-constrained solutions.

Definition at line 2077 of file dof_map_constraints.C.

References libMesh::NumericVector< T >::close(), libMesh::NumericVector< T >::closed(), libMesh::NumericVector< T >::get(), libMesh::System::get_dof_map(), libMesh::GHOSTED, libMesh::NumericVector< T >::localize(), libMesh::PARALLEL, libMesh::SERIAL, libMesh::NumericVector< T >::set(), libMesh::NumericVector< T >::size(), libMesh::System::solution, and libMesh::NumericVector< T >::type().

Referenced by libMesh::__libmesh_petsc_diff_solver_jacobian(), libMesh::__libmesh_petsc_diff_solver_residual(), libMesh::Problem_Interface::computeF(), libMesh::Problem_Interface::computeJacobian(), libMesh::Problem_Interface::computePreconditioner(), DMlibMeshFunction(), DMlibMeshJacobian(), libMesh::libmesh_petsc_snes_jacobian(), libMesh::libmesh_petsc_snes_postcheck(), libMesh::libmesh_petsc_snes_residual_helper(), libMesh::ImplicitSystem::sensitivity_solve(), libMesh::NewtonSolver::solve(), libMesh::PetscDiffSolver::solve(), libMesh::ImplicitSystem::weighted_sensitivity_adjoint_solve(), and libMesh::ImplicitSystem::weighted_sensitivity_solve().

2080 {
2081  parallel_object_only();
2082 
2083  if (!this->n_constrained_dofs())
2084  return;
2085 
2086  LOG_SCOPE("enforce_constraints_exactly()","DofMap");
2087 
2088  if (!v)
2089  v = system.solution.get();
2090 
2091  NumericVector<Number> * v_local = nullptr; // will be initialized below
2092  NumericVector<Number> * v_global = nullptr; // will be initialized below
2093  std::unique_ptr<NumericVector<Number>> v_built;
2094  if (v->type() == SERIAL)
2095  {
2096  v_built = NumericVector<Number>::build(this->comm());
2097  v_built->init(this->n_dofs(), this->n_local_dofs(), true, PARALLEL);
2098  v_built->close();
2099 
2100  for (dof_id_type i=v_built->first_local_index();
2101  i<v_built->last_local_index(); i++)
2102  v_built->set(i, (*v)(i));
2103  v_built->close();
2104  v_global = v_built.get();
2105 
2106  v_local = v;
2107  libmesh_assert (v_local->closed());
2108  }
2109  else if (v->type() == PARALLEL)
2110  {
2111  v_built = NumericVector<Number>::build(this->comm());
2112  v_built->init (v->size(), v->size(), true, SERIAL);
2113  v->localize(*v_built);
2114  v_built->close();
2115  v_local = v_built.get();
2116 
2117  v_global = v;
2118  }
2119  else if (v->type() == GHOSTED)
2120  {
2121  v_local = v;
2122  v_global = v;
2123  }
2124  else // unknown v->type()
2125  libmesh_error_msg("ERROR: Unknown v->type() == " << v->type());
2126 
2127  // We should never hit these asserts because we should error-out in
2128  // else clause above. Just to be sure we don't try to use v_local
2129  // and v_global uninitialized...
2130  libmesh_assert(v_local);
2131  libmesh_assert(v_global);
2132  libmesh_assert_equal_to (this, &(system.get_dof_map()));
2133 
2134  for (const auto & pr : _dof_constraints)
2135  {
2136  dof_id_type constrained_dof = pr.first;
2137  if (!this->local_index(constrained_dof))
2138  continue;
2139 
2140  const DofConstraintRow constraint_row = pr.second;
2141 
2142  Number exact_value = 0;
2143  if (!homogeneous)
2144  {
2145  DofConstraintValueMap::const_iterator rhsit =
2146  _primal_constraint_values.find(constrained_dof);
2147  if (rhsit != _primal_constraint_values.end())
2148  exact_value = rhsit->second;
2149  }
2150  for (const auto & j : constraint_row)
2151  exact_value += j.second * (*v_local)(j.first);
2152 
2153  v_global->set(constrained_dof, exact_value);
2154  }
2155 
2156  // If the old vector was serial, we probably need to send our values
2157  // to other processors
2158  if (v->type() == SERIAL)
2159  {
2160 #ifndef NDEBUG
2161  v_global->close();
2162 #endif
2163  v_global->localize (*v);
2164  }
2165  v->close();
2166 }
dof_id_type n_local_dofs() const
Definition: dof_map.h:584
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
virtual numeric_index_type size() const =0
const Parallel::Communicator & comm() const
dof_id_type n_dofs() const
Definition: dof_map.h:574
std::unique_ptr< NumericVector< Number > > solution
Definition: system.h:1523
DofConstraints _dof_constraints
Definition: dof_map.h:1687
virtual void close()=0
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package())
virtual bool closed() const
ParallelType type() const
dof_id_type n_constrained_dofs() const
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1689
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
Definition: dof_map.h:97
virtual void set(const numeric_index_type i, const T value)=0
const DofMap & get_dof_map() const
Definition: system.h:2049
uint8_t dof_id_type
Definition: id_types.h:64
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:738
virtual void localize(std::vector< T > &v_local) const =0

◆ extract_local_vector()

void libMesh::DofMap::extract_local_vector ( const NumericVector< Number > &  Ug,
const std::vector< dof_id_type > &  dof_indices,
DenseVectorBase< Number > &  Ue 
) const

Builds the local element vector Ue from the global vector Ug, accounting for any constrained degrees of freedom. For an element without constrained degrees of freedom this is the trivial mapping $ Ue[i] = Ug[dof_indices[i]] $

Note
The user must ensure that the element vector Ue is properly sized when calling this method. This is because there is no resize() method in the DenseVectorBase<> class.

Definition at line 1848 of file dof_map.C.

References build_constraint_matrix_and_vector(), libMesh::DenseVectorBase< T >::el(), libMesh::NumericVector< T >::first_local_index(), is_constrained_dof(), libMesh::NumericVector< T >::last_local_index(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVectorBase< T >::size(), libMesh::NumericVector< T >::size(), and libMesh::DenseVectorBase< T >::zero().

1851 {
1852  const unsigned int n_original_dofs = dof_indices_in.size();
1853 
1854 #ifdef LIBMESH_ENABLE_AMR
1855 
1856  // Trivial mapping
1857  libmesh_assert_equal_to (dof_indices_in.size(), Ue.size());
1858  bool has_constrained_dofs = false;
1859 
1860  for (unsigned int il=0; il != n_original_dofs; ++il)
1861  {
1862  const dof_id_type ig = dof_indices_in[il];
1863 
1864  if (this->is_constrained_dof (ig)) has_constrained_dofs = true;
1865 
1866  libmesh_assert_less (ig, Ug.size());
1867 
1868  Ue.el(il) = Ug(ig);
1869  }
1870 
1871  // If the element has any constrained DOFs then we need
1872  // to account for them in the mapping. This will handle
1873  // the case that the input vector is not constrained.
1874  if (has_constrained_dofs)
1875  {
1876  // Copy the input DOF indices.
1877  std::vector<dof_id_type> constrained_dof_indices(dof_indices_in);
1878 
1879  DenseMatrix<Number> C;
1880  DenseVector<Number> H;
1881 
1882  this->build_constraint_matrix_and_vector (C, H, constrained_dof_indices);
1883 
1884  libmesh_assert_equal_to (dof_indices_in.size(), C.m());
1885  libmesh_assert_equal_to (constrained_dof_indices.size(), C.n());
1886 
1887  // zero-out Ue
1888  Ue.zero();
1889 
1890  // compute Ue = C Ug, with proper mapping.
1891  for (unsigned int i=0; i != n_original_dofs; i++)
1892  {
1893  Ue.el(i) = H(i);
1894 
1895  const unsigned int n_constrained =
1896  cast_int<unsigned int>(constrained_dof_indices.size());
1897  for (unsigned int j=0; j<n_constrained; j++)
1898  {
1899  const dof_id_type jg = constrained_dof_indices[j];
1900 
1901  // If Ug is a serial or ghosted vector, then this assert is
1902  // overzealous. If Ug is a parallel vector, then this assert
1903  // is redundant.
1904  // libmesh_assert ((jg >= Ug.first_local_index()) &&
1905  // (jg < Ug.last_local_index()));
1906 
1907  Ue.el(i) += C(i,j)*Ug(jg);
1908  }
1909  }
1910  }
1911 
1912 #else
1913 
1914  // Trivial mapping
1915 
1916  libmesh_assert_equal_to (n_original_dofs, Ue.size());
1917 
1918  for (unsigned int il=0; il<n_original_dofs; il++)
1919  {
1920  const dof_id_type ig = dof_indices_in[il];
1921 
1922  libmesh_assert ((ig >= Ug.first_local_index()) && (ig < Ug.last_local_index()));
1923 
1924  Ue.el(il) = Ug(ig);
1925  }
1926 
1927 #endif
1928 }
void build_constraint_matrix_and_vector(DenseMatrix< Number > &C, DenseVector< Number > &H, std::vector< dof_id_type > &elem_dofs, int qoi_index=-1, const bool called_recursively=false) const
virtual numeric_index_type size() const =0
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1829
virtual numeric_index_type first_local_index() const =0
virtual numeric_index_type last_local_index() const =0
uint8_t dof_id_type
Definition: id_types.h:64

◆ find_connected_dof_objects()

void libMesh::DofMap::find_connected_dof_objects ( std::vector< const DofObject *> &  objs) const
private

Finds all the DofObjects associated with the set in objs. This will account for off-element couplings via hanging nodes.

◆ find_connected_dofs()

void libMesh::DofMap::find_connected_dofs ( std::vector< dof_id_type > &  elem_dofs) const
private

Finds all the DOFS associated with the element DOFs elem_dofs. This will account for off-element couplings via hanging nodes.

Definition at line 2633 of file dof_map.C.

References _dof_constraints, and is_constrained_dof().

Referenced by libMesh::SparsityPattern::Build::sorted_connected_dofs().

2634 {
2635  typedef std::set<dof_id_type> RCSet;
2636 
2637  // First insert the DOFS we already depend on into the set.
2638  RCSet dof_set (elem_dofs.begin(), elem_dofs.end());
2639 
2640  bool done = true;
2641 
2642  // Next insert any dofs those might be constrained in terms
2643  // of. Note that in this case we may not be done: Those may
2644  // in turn depend on others. So, we need to repeat this process
2645  // in that case until the system depends only on unconstrained
2646  // degrees of freedom.
2647  for (const auto & dof : elem_dofs)
2648  if (this->is_constrained_dof(dof))
2649  {
2650  // If the DOF is constrained
2651  DofConstraints::const_iterator
2652  pos =