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 = _dof_constraints.find(dof);
2653 
2654  libmesh_assert (pos != _dof_constraints.end());
2655 
2656  const DofConstraintRow & constraint_row = pos->second;
2657 
2658  // adaptive p refinement currently gives us lots of empty constraint
2659  // rows - we should optimize those DoFs away in the future. [RHS]
2660  //libmesh_assert (!constraint_row.empty());
2661 
2662  // Add the DOFs this dof is constrained in terms of.
2663  // note that these dofs might also be constrained, so
2664  // we will need to call this function recursively.
2665  for (const auto & pr : constraint_row)
2666  if (!dof_set.count (pr.first))
2667  {
2668  dof_set.insert (pr.first);
2669  done = false;
2670  }
2671  }
2672 
2673 
2674  // If not done then we need to do more work
2675  // (obviously :-) )!
2676  if (!done)
2677  {
2678  // Fill the vector with the contents of the set
2679  elem_dofs.clear();
2680  elem_dofs.insert (elem_dofs.end(),
2681  dof_set.begin(), dof_set.end());
2682 
2683 
2684  // May need to do this recursively. It is possible
2685  // that we just replaced a constrained DOF with another
2686  // constrained DOF.
2687  this->find_connected_dofs (elem_dofs);
2688 
2689  } // end if (!done)
2690 }
void find_connected_dofs(std::vector< dof_id_type > &elem_dofs) const
Definition: dof_map.C:2633
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1829
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

◆ first_dof() [1/2]

◆ first_dof() [2/2]

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

Definition at line 602 of file dof_map.h.

References libMesh::ParallelObject::processor_id().

Referenced by distribute_dofs(), and local_index().

603  { return this->first_dof(this->processor_id()); }
dof_id_type first_dof() const
Definition: dof_map.h:602
processor_id_type processor_id() const

◆ first_old_dof() [1/2]

dof_id_type libMesh::DofMap::first_old_dof ( const processor_id_type  proc) const
inline
Returns
The first old dof index that is local to partition proc.

Definition at line 609 of file dof_map.h.

References _first_old_df.

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

610  { libmesh_assert_less (proc, _first_old_df.size()); return _first_old_df[proc]; }
std::vector< dof_id_type > _first_old_df
Definition: dof_map.h:1667

◆ first_old_dof() [2/2]

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

Definition at line 612 of file dof_map.h.

References libMesh::ParallelObject::processor_id().

613  { return this->first_old_dof(this->processor_id()); }
dof_id_type first_old_dof() const
Definition: dof_map.h:612
processor_id_type processor_id() const

◆ gather_constraints()

void libMesh::DofMap::gather_constraints ( MeshBase mesh,
std::set< dof_id_type > &  unexpanded_dofs,
bool  look_for_constrainees 
)

Helper function for querying about constraint equations on other processors. If any id in requested_dof_ids is constrained on another processor, its constraint will be added on this processor as well. If look_for_constrainees is true, then constraints will also be returned if the id appears as a constraining value not just if it appears as a constrained value.

This function operates recursively: if the constraint for a constrained dof is newly added locally, then any other dofs which constrain it are queried to see if they are in turn constrained, and so on.

Definition at line 3871 of file dof_map_constraints.C.

References data, libMesh::Parallel::pull_parallel_vector_data(), and libMesh::Real.

3874 {
3875  typedef std::set<dof_id_type> DoF_RCSet;
3876 
3877  // If we have heterogenous adjoint constraints we need to
3878  // communicate those too.
3879  const unsigned int max_qoi_num =
3880  _adjoint_constraint_values.empty() ?
3881  0 : _adjoint_constraint_values.rbegin()->first;
3882 
3883  // We have to keep recursing while the unexpanded set is
3884  // nonempty on *any* processor
3885  bool unexpanded_set_nonempty = !unexpanded_dofs.empty();
3886  this->comm().max(unexpanded_set_nonempty);
3887 
3888  while (unexpanded_set_nonempty)
3889  {
3890  // Let's make sure we don't lose sync in this loop.
3891  parallel_object_only();
3892 
3893  // Request sets
3894  DoF_RCSet dof_request_set;
3895 
3896  // Request sets to send to each processor
3897  std::map<processor_id_type, std::vector<dof_id_type>>
3898  requested_dof_ids;
3899 
3900  // And the sizes of each
3901  std::map<processor_id_type, dof_id_type>
3902  dof_ids_on_proc;
3903 
3904  // Fill (and thereby sort and uniq!) the main request sets
3905  for (const auto & unexpanded_dof : unexpanded_dofs)
3906  {
3907  DofConstraints::const_iterator
3908  pos = _dof_constraints.find(unexpanded_dof);
3909 
3910  // If we were asked for a DoF and we don't already have a
3911  // constraint for it, then we need to check for one.
3912  if (pos == _dof_constraints.end())
3913  {
3914  if (!this->local_index(unexpanded_dof) &&
3915  !_dof_constraints.count(unexpanded_dof) )
3916  dof_request_set.insert(unexpanded_dof);
3917  }
3918  // If we were asked for a DoF and we already have a
3919  // constraint for it, then we need to check if the
3920  // constraint is recursive.
3921  else
3922  {
3923  const DofConstraintRow & row = pos->second;
3924  for (const auto & j : row)
3925  {
3926  const dof_id_type constraining_dof = j.first;
3927 
3928  // If it's non-local and we haven't already got a
3929  // constraint for it, we might need to ask for one
3930  if (!this->local_index(constraining_dof) &&
3931  !_dof_constraints.count(constraining_dof))
3932  dof_request_set.insert(constraining_dof);
3933  }
3934  }
3935  }
3936 
3937  // Clear the unexpanded constraint set; we're about to expand it
3938  unexpanded_dofs.clear();
3939 
3940  // Count requests by processor
3941  processor_id_type proc_id = 0;
3942  for (const auto & i : dof_request_set)
3943  {
3944  while (i >= _end_df[proc_id])
3945  proc_id++;
3946  dof_ids_on_proc[proc_id]++;
3947  }
3948 
3949  for (auto & pair : dof_ids_on_proc)
3950  {
3951  requested_dof_ids[pair.first].reserve(pair.second);
3952  }
3953 
3954  // Prepare each processor's request set
3955  proc_id = 0;
3956  for (const auto & i : dof_request_set)
3957  {
3958  while (i >= _end_df[proc_id])
3959  proc_id++;
3960  requested_dof_ids[proc_id].push_back(i);
3961  }
3962 
3963  typedef std::vector<std::pair<dof_id_type, Real>> row_datum;
3964 
3965  typedef std::vector<Number> rhss_datum;
3966 
3967  auto row_gather_functor =
3968  [this]
3970  const std::vector<dof_id_type> & ids,
3971  std::vector<row_datum> & data)
3972  {
3973  // Fill those requests
3974  const std::size_t query_size = ids.size();
3975 
3976  data.resize(query_size);
3977  for (std::size_t i=0; i != query_size; ++i)
3978  {
3979  dof_id_type constrained = ids[i];
3980  if (_dof_constraints.count(constrained))
3981  {
3982  DofConstraintRow & row = _dof_constraints[constrained];
3983  std::size_t row_size = row.size();
3984  data[i].reserve(row_size);
3985  for (const auto & j : row)
3986  {
3987  data[i].push_back(j);
3988 
3989  // We should never have an invalid constraining
3990  // dof id
3991  libmesh_assert(j.first != DofObject::invalid_id);
3992 
3993  // We should never have a 0 constraint
3994  // coefficient; that's implicit via sparse
3995  // constraint storage
3996  //
3997  // But we can't easily control how users add
3998  // constraints, so we can't safely assert that
3999  // we're being efficient here.
4000  //
4001  // libmesh_assert(j.second);
4002  }
4003  }
4004  else
4005  {
4006  // We have to distinguish "constraint with no
4007  // constraining dofs" (e.g. due to Dirichlet
4008  // constraint equations) from "no constraint".
4009  // We'll use invalid_id for the latter.
4010  data[i].push_back
4011  (std::make_pair(DofObject::invalid_id, Real(0)));
4012  }
4013  }
4014  };
4015 
4016  auto rhss_gather_functor =
4017  [this,
4018  max_qoi_num]
4020  const std::vector<dof_id_type> & ids,
4021  std::vector<rhss_datum> & data)
4022  {
4023  // Fill those requests
4024  const std::size_t query_size = ids.size();
4025 
4026  data.resize(query_size);
4027  for (std::size_t i=0; i != query_size; ++i)
4028  {
4029  dof_id_type constrained = ids[i];
4030  data[i].clear();
4031  if (_dof_constraints.count(constrained))
4032  {
4033  DofConstraintValueMap::const_iterator rhsit =
4034  _primal_constraint_values.find(constrained);
4035  data[i].push_back
4036  ((rhsit == _primal_constraint_values.end()) ?
4037  0 : rhsit->second);
4038 
4039  for (unsigned int q = 0; q != max_qoi_num; ++q)
4040  {
4041  AdjointDofConstraintValues::const_iterator adjoint_map_it =
4043 
4044  if (adjoint_map_it == _adjoint_constraint_values.end())
4045  {
4046  data[i].push_back(0);
4047  continue;
4048  }
4049 
4050  const DofConstraintValueMap & constraint_map =
4051  adjoint_map_it->second;
4052 
4053  DofConstraintValueMap::const_iterator adj_rhsit =
4054  constraint_map.find(constrained);
4055  data[i].push_back
4056  ((adj_rhsit == constraint_map.end()) ?
4057  0 : adj_rhsit->second);
4058  }
4059  }
4060  }
4061  };
4062 
4063  auto row_action_functor =
4064  [this,
4065  & unexpanded_dofs]
4067  const std::vector<dof_id_type> & ids,
4068  const std::vector<row_datum> & data)
4069  {
4070  // Add any new constraint rows we've found
4071  const std::size_t query_size = ids.size();
4072 
4073  for (std::size_t i=0; i != query_size; ++i)
4074  {
4075  const dof_id_type constrained = ids[i];
4076 
4077  // An empty row is an constraint with an empty row; for
4078  // no constraint we use a "no row" placeholder
4079  if (data[i].empty())
4080  {
4081  DofConstraintRow & row = _dof_constraints[constrained];
4082  row.clear();
4083  }
4084  else if (data[i][0].first != DofObject::invalid_id)
4085  {
4086  DofConstraintRow & row = _dof_constraints[constrained];
4087  row.clear();
4088  for (auto & pair : data[i])
4089  row[pair.first] = pair.second;
4090 
4091  // And prepare to check for more recursive constraints
4092  unexpanded_dofs.insert(constrained);
4093  }
4094  }
4095  };
4096 
4097  auto rhss_action_functor =
4098  [this,
4099  max_qoi_num]
4101  const std::vector<dof_id_type> & ids,
4102  const std::vector<rhss_datum> & data)
4103  {
4104  // Add rhs data for any new constraint rows we've found
4105  const std::size_t query_size = ids.size();
4106 
4107  for (std::size_t i=0; i != query_size; ++i)
4108  {
4109  if (!data[i].empty())
4110  {
4111  dof_id_type constrained = ids[i];
4112  if (data[i][0] != Number(0))
4113  _primal_constraint_values[constrained] = data[i][0];
4114  else
4115  _primal_constraint_values.erase(constrained);
4116 
4117  for (unsigned int q = 0; q != max_qoi_num; ++q)
4118  {
4119  AdjointDofConstraintValues::iterator adjoint_map_it =
4121 
4122  if ((adjoint_map_it == _adjoint_constraint_values.end()) &&
4123  data[i][q+1] == Number(0))
4124  continue;
4125 
4126  if (adjoint_map_it == _adjoint_constraint_values.end())
4127  adjoint_map_it = _adjoint_constraint_values.insert
4128  (std::make_pair(q,DofConstraintValueMap())).first;
4129 
4130  DofConstraintValueMap & constraint_map =
4131  adjoint_map_it->second;
4132 
4133  if (data[i][q+1] != Number(0))
4134  constraint_map[constrained] =
4135  data[i][q+1];
4136  else
4137  constraint_map.erase(constrained);
4138  }
4139  }
4140  }
4141 
4142  };
4143 
4144  // Now request constraint rows from other processors
4145  row_datum * row_ex = nullptr;
4147  (this->comm(), requested_dof_ids, row_gather_functor,
4148  row_action_functor, row_ex);
4149 
4150  // And request constraint right hand sides from other procesors
4151  rhss_datum * rhs_ex = nullptr;
4153  (this->comm(), requested_dof_ids, rhss_gather_functor,
4154  rhss_action_functor, rhs_ex);
4155 
4156  // We have to keep recursing while the unexpanded set is
4157  // nonempty on *any* processor
4158  unexpanded_set_nonempty = !unexpanded_dofs.empty();
4159  this->comm().max(unexpanded_set_nonempty);
4160  }
4161 }
uint8_t processor_id_type
Definition: id_types.h:99
const Parallel::Communicator & comm() const
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1691
void pull_parallel_vector_data(const Communicator &comm, const MapToVectors &queries, RequestContainer &reqs, GatherFunctor &gather_data, ActionFunctor &act_on_data, const datum *example)
static const dof_id_type invalid_id
Definition: dof_object.h:347
DofConstraints _dof_constraints
Definition: dof_map.h:1687
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1535
IterBase * data
uint8_t dof_id_type
Definition: id_types.h:64
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:738

◆ get_adjoint_dirichlet_boundaries() [1/2]

const DirichletBoundaries * libMesh::DofMap::get_adjoint_dirichlet_boundaries ( unsigned int  q) const

Definition at line 4302 of file dof_map_constraints.C.

4303 {
4304  libmesh_assert_greater(_adjoint_dirichlet_boundaries.size(),q);
4306 }
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1727

◆ get_adjoint_dirichlet_boundaries() [2/2]

DirichletBoundaries * libMesh::DofMap::get_adjoint_dirichlet_boundaries ( unsigned int  q)

Definition at line 4310 of file dof_map_constraints.C.

4311 {
4312  unsigned int old_size = cast_int<unsigned int>
4314  for (unsigned int i = old_size; i <= q; ++i)
4316 
4318 }
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1727

◆ get_dirichlet_boundaries() [1/2]

const DirichletBoundaries* libMesh::DofMap::get_dirichlet_boundaries ( ) const
inline

Definition at line 1223 of file dof_map.h.

References _dirichlet_boundaries.

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

1224  {
1225  return _dirichlet_boundaries.get();
1226  }
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Definition: dof_map.h:1721

◆ get_dirichlet_boundaries() [2/2]

DirichletBoundaries* libMesh::DofMap::get_dirichlet_boundaries ( )
inline

Definition at line 1228 of file dof_map.h.

References _dirichlet_boundaries.

1229  {
1230  return _dirichlet_boundaries.get();
1231  }
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Definition: dof_map.h:1721

◆ get_info() [1/2]

std::string libMesh::ReferenceCounter::get_info ( )
staticinherited

Gets a string containing the reference information.

Definition at line 47 of file reference_counter.C.

References libMesh::ReferenceCounter::_counts, and libMesh::Quality::name().

Referenced by libMesh::ReferenceCounter::print_info().

48 {
49 #if defined(LIBMESH_ENABLE_REFERENCE_COUNTING) && defined(DEBUG)
50 
51  std::ostringstream oss;
52 
53  oss << '\n'
54  << " ---------------------------------------------------------------------------- \n"
55  << "| Reference count information |\n"
56  << " ---------------------------------------------------------------------------- \n";
57 
58  for (const auto & pr : _counts)
59  {
60  const std::string name(pr.first);
61  const unsigned int creations = pr.second.first;
62  const unsigned int destructions = pr.second.second;
63 
64  oss << "| " << name << " reference count information:\n"
65  << "| Creations: " << creations << '\n'
66  << "| Destructions: " << destructions << '\n';
67  }
68 
69  oss << " ---------------------------------------------------------------------------- \n";
70 
71  return oss.str();
72 
73 #else
74 
75  return "";
76 
77 #endif
78 }
std::string name(const ElemQuality q)
Definition: elem_quality.C:42

◆ get_info() [2/2]

std::string libMesh::DofMap::get_info ( ) const

Gets summary info about the sparsity bandwidth and constraints.

Definition at line 2703 of file dof_map.C.

References _dof_constraints, _matrices, _n_nz, _n_oz, _node_constraints, _primal_constraint_values, libMesh::ParallelObject::comm(), local_index(), std::max(), libMesh::Parallel::Communicator::max(), libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), libMesh::TypeVector< T >::size(), and libMesh::Parallel::Communicator::sum().

Referenced by libMesh::System::get_info(), and print_info().

2704 {
2705  std::ostringstream os;
2706 
2707  // If we didn't calculate the exact sparsity pattern, the threaded
2708  // sparsity pattern assembly may have just given us an upper bound
2709  // on sparsity.
2710  const char * may_equal = " <= ";
2711 
2712  // If we calculated the exact sparsity pattern, then we can report
2713  // exact bandwidth figures:
2714  for (const auto & mat : _matrices)
2715  if (mat->need_full_sparsity_pattern())
2716  may_equal = " = ";
2717 
2718  dof_id_type max_n_nz = 0, max_n_oz = 0;
2719  long double avg_n_nz = 0, avg_n_oz = 0;
2720 
2721  if (_n_nz)
2722  {
2723  for (const auto & val : *_n_nz)
2724  {
2725  max_n_nz = std::max(max_n_nz, val);
2726  avg_n_nz += val;
2727  }
2728 
2729  std::size_t n_nz_size = _n_nz->size();
2730 
2731  this->comm().max(max_n_nz);
2732  this->comm().sum(avg_n_nz);
2733  this->comm().sum(n_nz_size);
2734 
2735  avg_n_nz /= std::max(n_nz_size,std::size_t(1));
2736 
2737  libmesh_assert(_n_oz);
2738 
2739  for (const auto & val : *_n_oz)
2740  {
2741  max_n_oz = std::max(max_n_oz, val);
2742  avg_n_oz += val;
2743  }
2744 
2745  std::size_t n_oz_size = _n_oz->size();
2746 
2747  this->comm().max(max_n_oz);
2748  this->comm().sum(avg_n_oz);
2749  this->comm().sum(n_oz_size);
2750 
2751  avg_n_oz /= std::max(n_oz_size,std::size_t(1));
2752  }
2753 
2754  os << " DofMap Sparsity\n Average On-Processor Bandwidth"
2755  << may_equal << avg_n_nz << '\n';
2756 
2757  os << " Average Off-Processor Bandwidth"
2758  << may_equal << avg_n_oz << '\n';
2759 
2760  os << " Maximum On-Processor Bandwidth"
2761  << may_equal << max_n_nz << '\n';
2762 
2763  os << " Maximum Off-Processor Bandwidth"
2764  << may_equal << max_n_oz << std::endl;
2765 
2766 #ifdef LIBMESH_ENABLE_CONSTRAINTS
2767 
2768  std::size_t n_constraints = 0, max_constraint_length = 0,
2769  n_rhss = 0;
2770  long double avg_constraint_length = 0.;
2771 
2772  for (const auto & pr : _dof_constraints)
2773  {
2774  // Only count local constraints, then sum later
2775  const dof_id_type constrained_dof = pr.first;
2776  if (!this->local_index(constrained_dof))
2777  continue;
2778 
2779  const DofConstraintRow & row = pr.second;
2780  std::size_t rowsize = row.size();
2781 
2782  max_constraint_length = std::max(max_constraint_length,
2783  rowsize);
2784  avg_constraint_length += rowsize;
2785  n_constraints++;
2786 
2787  if (_primal_constraint_values.count(constrained_dof))
2788  n_rhss++;
2789  }
2790 
2791  this->comm().sum(n_constraints);
2792  this->comm().sum(n_rhss);
2793  this->comm().sum(avg_constraint_length);
2794  this->comm().max(max_constraint_length);
2795 
2796  os << " DofMap Constraints\n Number of DoF Constraints = "
2797  << n_constraints;
2798  if (n_rhss)
2799  os << '\n'
2800  << " Number of Heterogenous Constraints= " << n_rhss;
2801  if (n_constraints)
2802  {
2803  avg_constraint_length /= n_constraints;
2804 
2805  os << '\n'
2806  << " Average DoF Constraint Length= " << avg_constraint_length;
2807  }
2808 
2809 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2810  std::size_t n_node_constraints = 0, max_node_constraint_length = 0,
2811  n_node_rhss = 0;
2812  long double avg_node_constraint_length = 0.;
2813 
2814  for (const auto & pr : _node_constraints)
2815  {
2816  // Only count local constraints, then sum later
2817  const Node * node = pr.first;
2818  if (node->processor_id() != this->processor_id())
2819  continue;
2820 
2821  const NodeConstraintRow & row = pr.second.first;
2822  std::size_t rowsize = row.size();
2823 
2824  max_node_constraint_length = std::max(max_node_constraint_length,
2825  rowsize);
2826  avg_node_constraint_length += rowsize;
2827  n_node_constraints++;
2828 
2829  if (pr.second.second != Point(0))
2830  n_node_rhss++;
2831  }
2832 
2833  this->comm().sum(n_node_constraints);
2834  this->comm().sum(n_node_rhss);
2835  this->comm().sum(avg_node_constraint_length);
2836  this->comm().max(max_node_constraint_length);
2837 
2838  os << "\n Number of Node Constraints = " << n_node_constraints;
2839  if (n_node_rhss)
2840  os << '\n'
2841  << " Number of Heterogenous Node Constraints= " << n_node_rhss;
2842  if (n_node_constraints)
2843  {
2844  avg_node_constraint_length /= n_node_constraints;
2845  os << "\n Maximum Node Constraint Length= " << max_node_constraint_length
2846  << '\n'
2847  << " Average Node Constraint Length= " << avg_node_constraint_length;
2848  }
2849 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
2850 
2851  os << std::endl;
2852 
2853 #endif // LIBMESH_ENABLE_CONSTRAINTS
2854 
2855  return os.str();
2856 }
const Parallel::Communicator & comm() const
long double max(long double a, double b)
std::vector< dof_id_type > * _n_nz
Definition: dof_map.h:1638
std::vector< dof_id_type > * _n_oz
Definition: dof_map.h:1644
DofConstraints _dof_constraints
Definition: dof_map.h:1687
std::vector< SparseMatrix< Number > *> _matrices
Definition: dof_map.h:1525
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
std::map< const Node *, Real, std::less< const Node * >, Threads::scalable_allocator< std::pair< const Node *const, Real > > > NodeConstraintRow
Definition: dof_map.h:145
processor_id_type processor_id() const
uint8_t dof_id_type
Definition: id_types.h:64
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:738
NodeConstraints _node_constraints
Definition: dof_map.h:1698

◆ get_local_constraints()

std::string libMesh::DofMap::get_local_constraints ( bool  print_nonlocal = false) const

Gets a string reporting all DoF and Node constraints local to this processor. If print_nonlocal is true, then nonlocal constraints which are locally known are included.

Definition at line 1444 of file dof_map_constraints.C.

References libMesh::DofObject::id(), and libMesh::DofObject::processor_id().

1445 {
1446  std::ostringstream os;
1447 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
1448  if (print_nonlocal)
1449  os << "All ";
1450  else
1451  os << "Local ";
1452 
1453  os << "Node Constraints:"
1454  << std::endl;
1455 
1456  for (const auto & pr : _node_constraints)
1457  {
1458  const Node * node = pr.first;
1459 
1460  // Skip non-local nodes if requested
1461  if (!print_nonlocal &&
1462  node->processor_id() != this->processor_id())
1463  continue;
1464 
1465  const NodeConstraintRow & row = pr.second.first;
1466  const Point & offset = pr.second.second;
1467 
1468  os << "Constraints for Node id " << node->id()
1469  << ": \t";
1470 
1471  for (const auto & item : row)
1472  os << " (" << item.first->id() << "," << item.second << ")\t";
1473 
1474  os << "rhs: " << offset;
1475 
1476  os << std::endl;
1477  }
1478 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
1479 
1480  if (print_nonlocal)
1481  os << "All ";
1482  else
1483  os << "Local ";
1484 
1485  os << "DoF Constraints:"
1486  << std::endl;
1487 
1488  for (const auto & pr : _dof_constraints)
1489  {
1490  const dof_id_type i = pr.first;
1491 
1492  // Skip non-local dofs if requested
1493  if (!print_nonlocal && !this->local_index(i))
1494  continue;
1495 
1496  const DofConstraintRow & row = pr.second;
1497  DofConstraintValueMap::const_iterator rhsit =
1498  _primal_constraint_values.find(i);
1499  const Number rhs = (rhsit == _primal_constraint_values.end()) ?
1500  0 : rhsit->second;
1501 
1502  os << "Constraints for DoF " << i
1503  << ": \t";
1504 
1505  for (const auto & item : row)
1506  os << " (" << item.first << "," << item.second << ")\t";
1507 
1508  os << "rhs: " << rhs;
1509  os << std::endl;
1510  }
1511 
1512  for (unsigned int qoi_index = 0,
1513  n_qois = cast_int<unsigned int>(_adjoint_dirichlet_boundaries.size());
1514  qoi_index != n_qois; ++qoi_index)
1515  {
1516  os << "Adjoint " << qoi_index << " DoF rhs values:"
1517  << std::endl;
1518 
1519  AdjointDofConstraintValues::const_iterator adjoint_map_it =
1520  _adjoint_constraint_values.find(qoi_index);
1521 
1522  if (adjoint_map_it != _adjoint_constraint_values.end())
1523  for (const auto & pr : adjoint_map_it->second)
1524  {
1525  const dof_id_type i = pr.first;
1526 
1527  // Skip non-local dofs if requested
1528  if (!print_nonlocal && !this->local_index(i))
1529  continue;
1530 
1531  const Number rhs = pr.second;
1532 
1533  os << "RHS for DoF " << i
1534  << ": " << rhs;
1535 
1536  os << std::endl;
1537  }
1538  }
1539 
1540  return os.str();
1541 }
A geometric point in (x,y,z) space associated with a DOF.
Definition: node.h:52
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1691
dof_id_type id() const
Definition: dof_object.h:655
DofConstraints _dof_constraints
Definition: dof_map.h:1687
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1727
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
std::map< const Node *, Real, std::less< const Node * >, Threads::scalable_allocator< std::pair< const Node *const, Real > > > NodeConstraintRow
Definition: dof_map.h:145
processor_id_type processor_id() const
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
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:738
NodeConstraints _node_constraints
Definition: dof_map.h:1698

◆ get_n_nz()

const std::vector<dof_id_type>& libMesh::DofMap::get_n_nz ( ) const
inline
Returns
A constant reference to the _n_nz list for this processor.

The vector contains the bandwidth of the on-processor coupling for each row of the global matrix that the current processor owns. This information can be used to preallocate space for a parallel sparse matrix.

Definition at line 459 of file dof_map.h.

References _n_nz.

460  {
461  libmesh_assert(_n_nz);
462  return *_n_nz;
463  }
std::vector< dof_id_type > * _n_nz
Definition: dof_map.h:1638

◆ get_n_oz()

const std::vector<dof_id_type>& libMesh::DofMap::get_n_oz ( ) const
inline
Returns
A constant reference to the _n_oz list for this processor.

The vector contains the bandwidth of the off-processor coupling for each row of the global matrix that the current processor owns. This information can be used to preallocate space for a parallel sparse matrix.

Definition at line 472 of file dof_map.h.

References _n_oz.

473  {
474  libmesh_assert(_n_oz);
475  return *_n_oz;
476  }
std::vector< dof_id_type > * _n_oz
Definition: dof_map.h:1644

◆ get_periodic_boundaries()

PeriodicBoundaries* libMesh::DofMap::get_periodic_boundaries ( )
inline

Definition at line 1185 of file dof_map.h.

References _periodic_boundaries.

1186  {
1187  return _periodic_boundaries.get();
1188  }
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Definition: dof_map.h:1707

◆ get_primal_constraint_values()

DofConstraintValueMap & libMesh::DofMap::get_primal_constraint_values ( )
inline
Returns
A reference to the set of right-hand-side values in primal constraint equations

Definition at line 1874 of file dof_map.h.

References _primal_constraint_values.

1875 {
1877 }
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1689

◆ get_send_list()

const std::vector<dof_id_type>& libMesh::DofMap::get_send_list ( ) const
inline
Returns
A constant reference to the _send_list for this processor.

The _send_list contains the global indices of all the variables in the global solution vector that influence the current processor. This information can be used for gathers at each solution step to retrieve solution values needed for computation.

Definition at line 450 of file dof_map.h.

References _send_list.

Referenced by libMesh::UniformRefinementEstimator::_estimate_error(), libMesh::UnsteadySolver::adjoint_advance_timestep(), libMesh::NewmarkSolver::advance_timestep(), libMesh::UnsteadySolver::advance_timestep(), libMesh::PetscDMWrapper::build_sf(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::SecondOrderUnsteadySolver::init_data(), libMesh::UnsteadySolver::init_data(), libMesh::System::re_update(), libMesh::SecondOrderUnsteadySolver::reinit(), libMesh::UnsteadySolver::reinit(), and libMesh::UnsteadySolver::retrieve_timestep().

450 { return _send_list; }
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1547

◆ has_adjoint_dirichlet_boundaries()

bool libMesh::DofMap::has_adjoint_dirichlet_boundaries ( unsigned int  q) const

Definition at line 4292 of file dof_map_constraints.C.

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

4293 {
4294  if (_adjoint_dirichlet_boundaries.size() > q)
4295  return true;
4296 
4297  return false;
4298 }
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1727

◆ has_blocked_representation()

bool libMesh::DofMap::has_blocked_representation ( ) const
inline
Returns
true if the variables are capable of being stored in a blocked form. Presently, this means that there can only be one variable group, and that the group has more than one variable.

Definition at line 549 of file dof_map.h.

References n_variable_groups(), and n_variables().

Referenced by block_size().

550  {
551 #ifdef LIBMESH_ENABLE_BLOCKED_STORAGE
552  return ((this->n_variable_groups() == 1) && (this->n_variables() > 1));
553 #else
554  return false;
555 #endif
556  }
unsigned int n_variable_groups() const
Definition: dof_map.h:533
unsigned int n_variables() const
Definition: dof_map.h:541

◆ has_heterogenous_adjoint_constraint()

Number libMesh::DofMap::has_heterogenous_adjoint_constraint ( const unsigned int  qoi_num,
const dof_id_type  dof 
) const
inline
Returns
The heterogeneous constraint value if the degree of freedom dof has a heterogenous constraint for adjoint solution qoi_num, zero otherwise.

Definition at line 1853 of file dof_map.h.

References _adjoint_constraint_values.

1855 {
1856  AdjointDofConstraintValues::const_iterator it =
1857  _adjoint_constraint_values.find(qoi_num);
1858  if (it != _adjoint_constraint_values.end())
1859  {
1860  DofConstraintValueMap::const_iterator rhsit =
1861  it->second.find(dof);
1862  if (rhsit == it->second.end())
1863  return 0;
1864  else
1865  return rhsit->second;
1866  }
1867 
1868  return 0;
1869 }
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1691

◆ has_heterogenous_adjoint_constraints()

bool libMesh::DofMap::has_heterogenous_adjoint_constraints ( const unsigned int  qoi_num) const
inline
Returns
true if the system has any heterogenous constraints for adjoint solution qoi_num, false otherwise.

Definition at line 1839 of file dof_map.h.

References _adjoint_constraint_values.

1840 {
1841  AdjointDofConstraintValues::const_iterator it =
1842  _adjoint_constraint_values.find(qoi_num);
1843  if (it == _adjoint_constraint_values.end())
1844  return false;
1845  if (it->second.empty())
1846  return false;
1847 
1848  return true;
1849 }
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1691

◆ heterogenously_constrain_element_matrix_and_vector()

void libMesh::DofMap::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

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.

The heterogenous version of this method creates linear systems in which heterogenously constrained degrees of freedom will solve to their correct offset values, as would be appropriate for finding a solution to a linear problem in a single algebraic solve. The non-heterogenous version of this method creates linear systems in which even heterogenously constrained degrees of freedom are solved without offset values taken into account, as would be appropriate for finding linearized updates to a solution in which heterogenous constraints are already satisfied.

By default, the constraints for the primal solution of this system are used. If a non-negative qoi_index is passed in, then the constraints for the corresponding adjoint solution are used instead.

Definition at line 1694 of file dof_map_constraints.C.

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

1699 {
1700  libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
1701  libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
1702  libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
1703 
1704  // check for easy return
1705  if (this->_dof_constraints.empty())
1706  return;
1707 
1708  // The constrained matrix is built up as C^T K C.
1709  // The constrained RHS is built up as C^T (F - K H)
1712 
1713  this->build_constraint_matrix_and_vector (C, H, elem_dofs, qoi_index);
1714 
1715  LOG_SCOPE("hetero_cnstrn_elem_mat_vec()", "DofMap");
1716 
1717  // It is possible that the matrix is not constrained at all.
1718  if ((C.m() == matrix.m()) &&
1719  (C.n() == elem_dofs.size())) // It the matrix is constrained
1720  {
1721  // We may have rhs values to use later
1722  const DofConstraintValueMap * rhs_values = nullptr;
1723  if (qoi_index < 0)
1724  rhs_values = &_primal_constraint_values;
1725  else
1726  {
1727  const AdjointDofConstraintValues::const_iterator
1728  it = _adjoint_constraint_values.find(qoi_index);
1729  if (it != _adjoint_constraint_values.end())
1730  rhs_values = &it->second;
1731  }
1732 
1733  // Compute matrix/vector product K H
1735  matrix.vector_mult(KH, H);
1736 
1737  // Compute the matrix-vector product C^T (F - KH)
1738  DenseVector<Number> F_minus_KH(rhs);
1739  F_minus_KH -= KH;
1740  C.vector_mult_transpose(rhs, F_minus_KH);
1741 
1742  // Compute the matrix-matrix-matrix product C^T K C
1743  matrix.left_multiply_transpose (C);
1744  matrix.right_multiply (C);
1745 
1746  libmesh_assert_equal_to (matrix.m(), matrix.n());
1747  libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
1748  libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
1749 
1750  for (unsigned int i=0,
1751  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
1752  i != n_elem_dofs; i++)
1753  {
1754  const dof_id_type dof_id = elem_dofs[i];
1755 
1756  if (this->is_constrained_dof(dof_id))
1757  {
1758  for (unsigned int j=0; j<matrix.n(); j++)
1759  matrix(i,j) = 0.;
1760 
1761  // If the DOF is constrained
1762  matrix(i,i) = 1.;
1763 
1764  // This will put a nonsymmetric entry in the constraint
1765  // row to ensure that the linear system produces the
1766  // correct value for the constrained DOF.
1767  if (asymmetric_constraint_rows)
1768  {
1769  DofConstraints::const_iterator
1770  pos = _dof_constraints.find(dof_id);
1771 
1772  libmesh_assert (pos != _dof_constraints.end());
1773 
1774  const DofConstraintRow & constraint_row = pos->second;
1775 
1776  for (const auto & item : constraint_row)
1777  for (unsigned int j=0; j != n_elem_dofs; j++)
1778  if (elem_dofs[j] == item.first)
1779  matrix(i,j) = -item.second;
1780 
1781  if (rhs_values)
1782  {
1783  const DofConstraintValueMap::const_iterator valpos =
1784  rhs_values->find(dof_id);
1785 
1786  rhs(i) = (valpos == rhs_values->end()) ?
1787  0 : valpos->second;
1788  }
1789  }
1790  else
1791  rhs(i) = 0.;
1792  }
1793  }
1794 
1795  } // end if is constrained...
1796 }
virtual unsigned int size() const override
Definition: dense_vector.h:92
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
unsigned int m() const
dof_id_type dof_id
Definition: xdr_io.C:49
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1691
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)
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
unsigned int n() const
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const
uint8_t dof_id_type
Definition: id_types.h:64

◆ heterogenously_constrain_element_vector()

void libMesh::DofMap::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

Constrains the element vector. This method requires the element matrix to be square and not-yet-constrained, in which case the elem_dofs correspond to the global DOF indices of both the rows and columns of the element matrix.

The heterogenous version of this method creates linear systems in which heterogenously constrained degrees of freedom will solve to their correct offset values, as would be appropriate for finding a solution to a linear problem in a single algebraic solve. The non-heterogenous version of this method creates linear systems in which even heterogenously constrained degrees of freedom are solved without offset values taken into account, as would be appropriate for finding linearized updates to a solution in which heterogenous constraints are already satisfied.

By default, the constraints for the primal solution of this system are used. If a non-negative qoi_index is passed in, then the constraints for the corresponding adjoint solution are used instead.

Definition at line 1800 of file dof_map_constraints.C.

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

1805 {
1806  libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
1807  libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
1808  libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
1809 
1810  // check for easy return
1811  if (this->_dof_constraints.empty())
1812  return;
1813 
1814  // The constrained matrix is built up as C^T K C.
1815  // The constrained RHS is built up as C^T (F - K H)
1818 
1819  this->build_constraint_matrix_and_vector (C, H, elem_dofs, qoi_index);
1820 
1821  LOG_SCOPE("hetero_cnstrn_elem_vec()", "DofMap");
1822 
1823  // It is possible that the matrix is not constrained at all.
1824  if ((C.m() == matrix.m()) &&
1825  (C.n() == elem_dofs.size())) // It the matrix is constrained
1826  {
1827  // We may have rhs values to use later
1828  const DofConstraintValueMap * rhs_values = nullptr;
1829  if (qoi_index < 0)
1830  rhs_values = &_primal_constraint_values;
1831  else
1832  {
1833  const AdjointDofConstraintValues::const_iterator
1834  it = _adjoint_constraint_values.find(qoi_index);
1835  if (it != _adjoint_constraint_values.end())
1836  rhs_values = &it->second;
1837  }
1838 
1839  // Compute matrix/vector product K H
1841  matrix.vector_mult(KH, H);
1842 
1843  // Compute the matrix-vector product C^T (F - KH)
1844  DenseVector<Number> F_minus_KH(rhs);
1845  F_minus_KH -= KH;
1846  C.vector_mult_transpose(rhs, F_minus_KH);
1847 
1848  for (unsigned int i=0,
1849  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
1850  i != n_elem_dofs; i++)
1851  {
1852  const dof_id_type dof_id = elem_dofs[i];
1853 
1854  if (this->is_constrained_dof(dof_id))
1855  {
1856  // This will put a nonsymmetric entry in the constraint
1857  // row to ensure that the linear system produces the
1858  // correct value for the constrained DOF.
1859  if (asymmetric_constraint_rows && rhs_values)
1860  {
1861  const DofConstraintValueMap::const_iterator valpos =
1862  rhs_values->find(dof_id);
1863 
1864  rhs(i) = (valpos == rhs_values->end()) ?
1865  0 : valpos->second;
1866  }
1867  else
1868  rhs(i) = 0.;
1869  }
1870  }
1871 
1872  } // end if is constrained...
1873 }
virtual unsigned int size() const override
Definition: dense_vector.h:92
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
unsigned int m() const
dof_id_type dof_id
Definition: xdr_io.C:49
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1691
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
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1689
unsigned int n() const
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const
uint8_t dof_id_type
Definition: id_types.h:64

◆ increment_constructor_count()

void libMesh::ReferenceCounter::increment_constructor_count ( const std::string &  name)
inlineprotectedinherited

Increments the construction counter. Should be called in the constructor of any derived class that will be reference counted.

Definition at line 181 of file reference_counter.h.

References libMesh::ReferenceCounter::_counts, libMesh::Quality::name(), and libMesh::Threads::spin_mtx.

Referenced by libMesh::ReferenceCountedObject< RBParametrized >::ReferenceCountedObject().

182 {
183  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
184  std::pair<unsigned int, unsigned int> & p = _counts[name];
185 
186  p.first++;
187 }
std::string name(const ElemQuality q)
Definition: elem_quality.C:42
spin_mutex spin_mtx
Definition: threads.C:29

◆ increment_destructor_count()

void libMesh::ReferenceCounter::increment_destructor_count ( const std::string &  name)
inlineprotectedinherited

Increments the destruction counter. Should be called in the destructor of any derived class that will be reference counted.

Definition at line 194 of file reference_counter.h.

References libMesh::ReferenceCounter::_counts, libMesh::Quality::name(), and libMesh::Threads::spin_mtx.

Referenced by libMesh::ReferenceCountedObject< RBParametrized >::~ReferenceCountedObject().

195 {
196  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
197  std::pair<unsigned int, unsigned int> & p = _counts[name];
198 
199  p.second++;
200 }
std::string name(const ElemQuality q)
Definition: elem_quality.C:42
spin_mutex spin_mtx
Definition: threads.C:29

◆ invalidate_dofs()

void libMesh::DofMap::invalidate_dofs ( MeshBase mesh) const
private

Invalidates all active DofObject dofs for this system

Definition at line 813 of file dof_map.C.

References mesh, and sys_number().

Referenced by distribute_dofs(), and reinit().

814 {
815  const unsigned int sys_num = this->sys_number();
816 
817  // All the nodes
818  for (auto & node : mesh.node_ptr_range())
819  node->invalidate_dofs(sys_num);
820 
821  // All the active elements.
822  for (auto & elem : mesh.active_element_ptr_range())
823  elem->invalidate_dofs(sys_num);
824 }
MeshBase & mesh
unsigned int sys_number() const
Definition: dof_map.h:1744

◆ is_attached()

bool libMesh::DofMap::is_attached ( SparseMatrix< Number > &  matrix)

Matrices should not be attached more than once. We can test for an already-attached matrix if necessary using is_attached

Definition at line 298 of file dof_map.C.

References _matrices.

Referenced by libMesh::ImplicitSystem::init_matrices().

299 {
300  return (std::find(_matrices.begin(), _matrices.end(),
301  &matrix) != _matrices.end());
302 }
std::vector< SparseMatrix< Number > *> _matrices
Definition: dof_map.h:1525

◆ is_constrained_dof()

bool libMesh::DofMap::is_constrained_dof ( const dof_id_type  dof) const
inline
Returns
true if the degree of freedom dof is constrained, false otherwise.

Definition at line 1829 of file dof_map.h.

References _dof_constraints.

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

1830 {
1831  if (_dof_constraints.count(dof))
1832  return true;
1833 
1834  return false;
1835 }
DofConstraints _dof_constraints
Definition: dof_map.h:1687

◆ is_constrained_node()

bool libMesh::DofMap::is_constrained_node ( const Node node) const
inline
Returns
true if the Node is constrained, false otherwise.

Definition at line 1812 of file dof_map.h.

References _node_constraints.

1817 {
1818 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
1819  if (_node_constraints.count(node))
1820  return true;
1821 #endif
1822 
1823  return false;
1824 }
NodeConstraints _node_constraints
Definition: dof_map.h:1698

◆ is_evaluable()

template<typename DofObjectSubclass >
template bool libMesh::DofMap::is_evaluable< Node > ( const DofObjectSubclass &  obj,
unsigned int  var_num = libMesh::invalid_uint 
) const
Returns
true iff our solutions can be locally evaluated on obj (which should be an Elem or a Node) for variable number var_num (for all variables, if var_num is invalid_uint)

Definition at line 2413 of file dof_map.C.

References all_semilocal_indices(), dof_indices(), libMesh::invalid_uint, and libMesh::ParallelObject::processor_id().

Referenced by libMesh::System::point_gradient(), and libMesh::System::point_hessian().

2415 {
2416  // Everything is evaluable on a local object
2417  if (obj.processor_id() == this->processor_id())
2418  return true;
2419 
2420  std::vector<dof_id_type> di;
2421 
2422  if (var_num == libMesh::invalid_uint)
2423  this->dof_indices(&obj, di);
2424  else
2425  this->dof_indices(&obj, di, var_num);
2426 
2427  return this->all_semilocal_indices(di);
2428 }
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
bool all_semilocal_indices(const std::vector< dof_id_type > &dof_indices) const
Definition: dof_map.C:2400
processor_id_type processor_id() const

◆ is_periodic_boundary()

bool libMesh::DofMap::is_periodic_boundary ( const boundary_id_type  boundaryid) const
Returns
true if the boundary given by boundaryid is periodic, false otherwise

Definition at line 219 of file dof_map.C.

References _periodic_boundaries.

220 {
221  if (_periodic_boundaries->count(boundaryid) != 0)
222  return true;
223 
224  return false;
225 }
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Definition: dof_map.h:1707

◆ last_dof() [1/2]

dof_id_type libMesh::DofMap::last_dof ( const processor_id_type  proc) const
inline
Returns
The last dof index that is local to processor proc.
Deprecated:
This function returns nonsense in the rare case where proc has no local dof indices. Use end_dof() instead.

Definition at line 624 of file dof_map.h.

References _end_df.

625  {
626  libmesh_deprecated();
627  libmesh_assert_less (proc, _end_df.size());
628  return cast_int<dof_id_type>(_end_df[proc] - 1);
629  }
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1535

◆ last_dof() [2/2]

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

Definition at line 631 of file dof_map.h.

References libMesh::ParallelObject::processor_id().

632  { return this->last_dof(this->processor_id()); }
dof_id_type last_dof() const
Definition: dof_map.h:631
processor_id_type processor_id() const

◆ local_index()

bool libMesh::DofMap::local_index ( dof_id_type  dof_index) const
inline
Returns
true if degree of freedom index dof_index is a local index.

Definition at line 738 of file dof_map.h.

References end_dof(), and first_dof().

Referenced by add_neighbors_to_send_list(), get_info(), local_variable_indices(), semilocal_index(), and libMesh::PetscDMWrapper::set_point_range_in_section().

739  { return (dof_index >= this->first_dof()) && (dof_index < this->end_dof()); }
dof_id_type end_dof() const
Definition: dof_map.h:644
dof_id_type first_dof() const
Definition: dof_map.h:602

◆ local_variable_indices()

void libMesh::DofMap::local_variable_indices ( std::vector< dof_id_type > &  idx,
const MeshBase mesh,
unsigned int  var_num 
) const

Fills an array of those dof indices which belong to the given variable number and live on the current processor.

Definition at line 1076 of file dof_map.C.

References libMesh::Variable::active_on_subdomain(), libMesh::DofObject::dof_number(), libMesh::MeshTools::Generation::Private::idx(), local_index(), mesh, libMesh::DofObject::n_comp(), n_nodes, libMesh::ParallelObject::n_processors(), libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), libMesh::SCALAR, SCALAR_dof_indices(), sys_number(), variable(), and variable_type().

Referenced by libMesh::petsc_auto_fieldsplit().

1079 {
1080  // Count dofs in the *exact* order that distribute_dofs numbered
1081  // them, so that we can assume ascending indices and use push_back
1082  // instead of find+insert.
1083 
1084  const unsigned int sys_num = this->sys_number();
1085 
1086  // If this isn't a SCALAR variable, we need to find all its field
1087  // dofs on the mesh
1088  if (this->variable_type(var_num).family != SCALAR)
1089  {
1090  const Variable & var(this->variable(var_num));
1091 
1092  for (auto & elem : mesh.active_local_element_ptr_range())
1093  {
1094  if (!var.active_on_subdomain(elem->subdomain_id()))
1095  continue;
1096 
1097  // Only count dofs connected to active
1098  // elements on this processor.
1099  const unsigned int n_nodes = elem->n_nodes();
1100 
1101  // First get any new nodal DOFS
1102  for (unsigned int n=0; n<n_nodes; n++)
1103  {
1104  Node & node = elem->node_ref(n);
1105 
1106  if (node.processor_id() < this->processor_id())
1107  continue;
1108 
1109  const unsigned int n_comp = node.n_comp(sys_num, var_num);
1110  for(unsigned int i=0; i<n_comp; i++)
1111  {
1112  const dof_id_type index = node.dof_number(sys_num,var_num,i);
1113  libmesh_assert (this->local_index(index));
1114 
1115  if (idx.empty() || index > idx.back())
1116  idx.push_back(index);
1117  }
1118  }
1119 
1120  // Next get any new element DOFS
1121  const unsigned int n_comp = elem->n_comp(sys_num, var_num);
1122  for (unsigned int i=0; i<n_comp; i++)
1123  {
1124  const dof_id_type index = elem->dof_number(sys_num,var_num,i);
1125  if (idx.empty() || index > idx.back())
1126  idx.push_back(index);
1127  }
1128  } // done looping over elements
1129 
1130 
1131  // we may have missed assigning DOFs to nodes that we own
1132  // but to which we have no connected elements matching our
1133  // variable restriction criterion. this will happen, for example,
1134  // if variable V is restricted to subdomain S. We may not own
1135  // any elements which live in S, but we may own nodes which are
1136  // *connected* to elements which do. in this scenario these nodes
1137  // will presently have unnumbered DOFs. we need to take care of
1138  // them here since we own them and no other processor will touch them.
1139  for (const auto & node : mesh.local_node_ptr_range())
1140  {
1141  libmesh_assert(node);
1142 
1143  const unsigned int n_comp = node->n_comp(sys_num, var_num);
1144  for (unsigned int i=0; i<n_comp; i++)
1145  {
1146  const dof_id_type index = node->dof_number(sys_num,var_num,i);
1147  if (idx.empty() || index > idx.back())
1148  idx.push_back(index);
1149  }
1150  }
1151  }
1152  // Otherwise, count up the SCALAR dofs, if we're on the processor
1153  // that holds this SCALAR variable
1154  else if (this->processor_id() == (this->n_processors()-1))
1155  {
1156  std::vector<dof_id_type> di_scalar;
1157  this->SCALAR_dof_indices(di_scalar,var_num);
1158  idx.insert( idx.end(), di_scalar.begin(), di_scalar.end());
1159  }
1160 }
const FEType & variable_type(const unsigned int c) const
Definition: dof_map.h:1792
MeshBase & mesh
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
processor_id_type n_processors() const
const dof_id_type n_nodes
Definition: tecplot_io.C:68
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:1762
processor_id_type processor_id() const
unsigned int idx(const ElemType type, const unsigned int nx, const unsigned int i, const unsigned int j)
uint8_t dof_id_type
Definition: id_types.h:64
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:738

◆ max_constraint_error()

std::pair< Real, Real > libMesh::DofMap::max_constraint_error ( const System system,
NumericVector< Number > *  v = nullptr 
) const

Tests the constrained degrees of freedom on the numeric vector v, which represents a solution defined on the mesh, returning a pair whose first entry is the maximum absolute error on a constrained DoF and whose second entry is the maximum relative error. Useful for debugging purposes.

If v == nullptr, the system solution vector is tested.

Definition at line 2268 of file dof_map_constraints.C.

References std::abs(), libMesh::MeshBase::active_local_element_ptr_range(), libMesh::NumericVector< T >::closed(), libMesh::NumericVector< T >::first_local_index(), libMesh::System::get_dof_map(), libMesh::System::get_mesh(), libMesh::NumericVector< T >::last_local_index(), libMesh::DenseMatrixBase< T >::m(), std::max(), mesh, libMesh::DenseMatrixBase< T >::n(), libMesh::Real, and libMesh::System::solution.

2270 {
2271  if (!v)
2272  v = system.solution.get();
2273  NumericVector<Number> & vec = *v;
2274 
2275  // We'll assume the vector is closed
2276  libmesh_assert (vec.closed());
2277 
2278  Real max_absolute_error = 0., max_relative_error = 0.;
2279 
2280  const MeshBase & mesh = system.get_mesh();
2281 
2282  libmesh_assert_equal_to (this, &(system.get_dof_map()));
2283 
2284  // indices on each element
2285  std::vector<dof_id_type> local_dof_indices;
2286 
2287  for (const auto & elem : mesh.active_local_element_ptr_range())
2288  {
2289  this->dof_indices(elem, local_dof_indices);
2290  std::vector<dof_id_type> raw_dof_indices = local_dof_indices;
2291 
2292  // Constraint matrix for each element
2294 
2295  this->build_constraint_matrix (C, local_dof_indices);
2296 
2297  // Continue if the element is unconstrained
2298  if (!C.m())
2299  continue;
2300 
2301  libmesh_assert_equal_to (C.m(), raw_dof_indices.size());
2302  libmesh_assert_equal_to (C.n(), local_dof_indices.size());
2303 
2304  for (unsigned int i=0; i!=C.m(); ++i)
2305  {
2306  // Recalculate any constrained dof owned by this processor
2307  dof_id_type global_dof = raw_dof_indices[i];
2308  if (this->is_constrained_dof(global_dof) &&
2309  global_dof >= vec.first_local_index() &&
2310  global_dof < vec.last_local_index())
2311  {
2312 #ifndef NDEBUG
2313  DofConstraints::const_iterator
2314  pos = _dof_constraints.find(global_dof);
2315 
2316  libmesh_assert (pos != _dof_constraints.end());
2317 #endif
2318 
2319  Number exact_value = 0;
2320  DofConstraintValueMap::const_iterator rhsit =
2321  _primal_constraint_values.find(global_dof);
2322  if (rhsit != _primal_constraint_values.end())
2323  exact_value = rhsit->second;
2324 
2325  for (unsigned int j=0; j!=C.n(); ++j)
2326  {
2327  if (local_dof_indices[j] != global_dof)
2328  exact_value += C(i,j) *
2329  vec(local_dof_indices[j]);
2330  }
2331 
2332  max_absolute_error = std::max(max_absolute_error,
2333  std::abs(vec(global_dof) - exact_value));
2334  max_relative_error = std::max(max_relative_error,
2335  std::abs(vec(global_dof) - exact_value)
2336  / std::abs(exact_value));
2337  }
2338  }
2339  }
2340 
2341  return std::pair<Real, Real>(max_absolute_error, max_relative_error);
2342 }
double abs(double a)
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition: dof_map.C:1930
MeshBase & mesh
unsigned int m() const
long double max(long double a, double b)
const MeshBase & get_mesh() const
Definition: system.h:2033
Base class for Mesh.
Definition: mesh_base.h:77
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
std::unique_ptr< NumericVector< Number > > solution
Definition: system.h:1523
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1829
DofConstraints _dof_constraints
Definition: dof_map.h:1687
virtual bool closed() const
virtual numeric_index_type first_local_index() const =0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1689
void build_constraint_matrix(DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
unsigned int n() const
const DofMap & get_dof_map() const
Definition: system.h:2049
virtual numeric_index_type last_local_index() const =0
uint8_t dof_id_type
Definition: id_types.h:64

◆ merge_ghost_functor_outputs()

void libMesh::DofMap::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 
)
staticprivate

Definition at line 1432 of file dof_map.C.

References libMesh::as_range().

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

1439 {
1440  for (const auto & gf : as_range(gf_begin, gf_end))
1441  {
1442  GhostingFunctor::map_type more_elements_to_ghost;
1443 
1444  libmesh_assert(gf);
1445  (*gf)(elems_begin, elems_end, p, more_elements_to_ghost);
1446 
1447  for (const auto & pr : more_elements_to_ghost)
1448  {
1449  GhostingFunctor::map_type::iterator existing_it =
1450  elements_to_ghost.find (pr.first);
1451  if (existing_it == elements_to_ghost.end())
1452  elements_to_ghost.insert(pr);
1453  else
1454  {
1455  if (existing_it->second)
1456  {
1457  if (pr.second)
1458  {
1459  // If this isn't already a temporary
1460  // then we need to make one so we'll
1461  // have a non-const matrix to merge
1462  if (temporary_coupling_matrices.empty() ||
1463  temporary_coupling_matrices.find(const_cast<CouplingMatrix *>(existing_it->second)) == temporary_coupling_matrices.end())
1464  {
1465  CouplingMatrix * cm = new CouplingMatrix(*existing_it->second);
1466  temporary_coupling_matrices.insert(cm);
1467  existing_it->second = cm;
1468  }
1469  const_cast<CouplingMatrix &>(*existing_it->second) &= *pr.second;
1470  }
1471  else
1472  {
1473  // Any existing_it matrix merged with a full
1474  // matrix (symbolized as nullptr) gives another
1475  // full matrix (symbolizable as nullptr).
1476 
1477  // So if existing_it->second is a temporary then
1478  // we don't need it anymore; we might as well
1479  // remove it to keep the set of temporaries
1480  // small.
1481  std::set<CouplingMatrix *>::iterator temp_it =
1482  temporary_coupling_matrices.find(const_cast<CouplingMatrix *>(existing_it->second));
1483  if (temp_it != temporary_coupling_matrices.end())
1484  temporary_coupling_matrices.erase(temp_it);
1485 
1486  existing_it->second = nullptr;
1487  }
1488  }
1489  // else we have a nullptr already, then we have a full
1490  // coupling matrix, already, and merging with anything
1491  // else won't change that, so we're done.
1492  }
1493  }
1494  }
1495 }
SimpleRange< I > as_range(const std::pair< I, I > &p)
Definition: simple_range.h:57
std::unordered_map< const Elem *, const CouplingMatrix * > map_type

◆ n_constrained_dofs()

dof_id_type libMesh::DofMap::n_constrained_dofs ( ) const
Returns
The total number of constrained degrees of freedom in the problem.

Definition at line 1172 of file dof_map_constraints.C.

Referenced by libMesh::libmesh_petsc_snes_postcheck().

1173 {
1174  parallel_object_only();
1175 
1176  dof_id_type nc_dofs = this->n_local_constrained_dofs();
1177  this->comm().sum(nc_dofs);
1178  return nc_dofs;
1179 }
dof_id_type n_local_constrained_dofs() const
const Parallel::Communicator & comm() const
uint8_t dof_id_type
Definition: id_types.h:64

◆ n_constrained_nodes()

dof_id_type libMesh::DofMap::n_constrained_nodes ( ) const
inline
Returns
The total number of constrained Nodes in the mesh.

Definition at line 810 of file dof_map.h.

References _node_constraints.

811  { return cast_int<dof_id_type>(_node_constraints.size()); }
NodeConstraints _node_constraints
Definition: dof_map.h:1698

◆ n_dofs()

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

◆ n_dofs_on_processor()

dof_id_type libMesh::DofMap::n_dofs_on_processor ( const processor_id_type  proc) const
inline
Returns
The number of degrees of freedom on partition proc.

Definition at line 590 of file dof_map.h.

References _end_df, and _first_df.

Referenced by build_sparsity(), libMesh::SparsityPattern::Build::join(), n_local_dofs(), libMesh::SparsityPattern::Build::operator()(), and libMesh::SparsityPattern::Build::parallel_sync().

591  {
592  libmesh_assert_less (proc, _first_df.size());
593  return cast_int<dof_id_type>(_end_df[proc] - _first_df[proc]);
594  }
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1535
std::vector< dof_id_type > _first_df
Definition: dof_map.h:1530

◆ n_local_constrained_dofs()

dof_id_type libMesh::DofMap::n_local_constrained_dofs ( ) const
Returns
The number of constrained degrees of freedom on this processor.

Definition at line 1182 of file dof_map_constraints.C.

1183 {
1184  const DofConstraints::const_iterator lower =
1185  _dof_constraints.lower_bound(this->first_dof()),
1186  upper =
1187  _dof_constraints.upper_bound(this->end_dof()-1);
1188 
1189  return cast_int<dof_id_type>(std::distance(lower, upper));
1190 }
DofConstraints _dof_constraints
Definition: dof_map.h:1687
dof_id_type end_dof() const
Definition: dof_map.h:644
dof_id_type first_dof() const
Definition: dof_map.h:602

◆ n_local_dofs()

dof_id_type libMesh::DofMap::n_local_dofs ( ) const
inline
Returns
The number of degrees of freedom on this processor.

Definition at line 584 of file dof_map.h.

References n_dofs_on_processor(), and libMesh::ParallelObject::processor_id().

Referenced by libMesh::PetscDMWrapper::build_sf(), and libMesh::PetscDMWrapper::set_point_range_in_section().

585  { return this->n_dofs_on_processor (this->processor_id()); }
dof_id_type n_dofs_on_processor(const processor_id_type proc) const
Definition: dof_map.h:590
processor_id_type processor_id() const

◆ n_objects()

static unsigned int libMesh::ReferenceCounter::n_objects ( )
inlinestaticinherited

Prints the number of outstanding (created, but not yet destroyed) objects.

Definition at line 83 of file reference_counter.h.

References libMesh::ReferenceCounter::_n_objects.

84  { return _n_objects; }
static Threads::atomic< unsigned int > _n_objects

◆ n_old_dofs()

dof_id_type libMesh::DofMap::n_old_dofs ( ) const
inline
Returns
The total number of degrees of freedom on old_dof_objects

Definition at line 1271 of file dof_map.h.

References _n_old_dfs.

Referenced by SCALAR_dof_indices().

1271 { return _n_old_dfs; }
dof_id_type _n_old_dfs
Definition: dof_map.h:1662

◆ n_processors()

processor_id_type libMesh::ParallelObject::n_processors ( ) const
inlineinherited
Returns
The number of processors in the group.

Definition at line 95 of file parallel_object.h.

References libMesh::ParallelObject::_communicator, and libMesh::Parallel::Communicator::size().

Referenced by libMesh::BoundaryInfo::_find_id_maps(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::DistributedMesh::add_elem(), libMesh::DistributedMesh::add_node(), libMesh::LaplaceMeshSmoother::allgather_graph(), libMesh::FEMSystem::assembly(), libMesh::AztecLinearSolver< T >::AztecLinearSolver(), libMesh::BoundaryInfo::build_node_list_from_side_list(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::DistributedMesh::clear(), libMesh::Nemesis_IO_Helper::compute_border_node_ids(), libMesh::Nemesis_IO_Helper::construct_nemesis_filename(), libMesh::UnstructuredMesh::create_pid_mesh(), libMesh::MeshTools::create_processor_bounding_box(), distribute_dofs(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), libMesh::EnsightIO::EnsightIO(), libMesh::MeshBase::get_info(), libMesh::SystemSubsetBySubdomain::init(), libMesh::PetscDMWrapper::init_and_attach_petscdm(), libMesh::Nemesis_IO_Helper::initialize(), libMesh::DistributedMesh::insert_elem(), 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::MeshTools::libmesh_assert_valid_refinement_flags(), local_variable_indices(), libMesh::MeshRefinement::make_coarsening_compatible(), libMesh::MeshBase::n_active_elem_on_proc(), libMesh::MeshBase::n_elem_on_proc(), libMesh::MeshBase::n_nodes_on_proc(), libMesh::MeshBase::partition(), libMesh::PetscLinearSolver< T >::PetscLinearSolver(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), libMesh::NameBasedIO::read(), libMesh::Nemesis_IO::read(), libMesh::CheckpointIO::read(), libMesh::CheckpointIO::read_connectivity(), libMesh::XdrIO::read_header(), libMesh::CheckpointIO::read_nodes(), libMesh::System::read_parallel_data(), libMesh::System::read_SCALAR_dofs(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::System::read_serialized_vector(), libMesh::DistributedMesh::renumber_dof_objects(), set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), libMesh::MeshRefinement::uniformly_coarsen(), libMesh::DistributedMesh::update_parallel_id_counts(), libMesh::GMVIO::write_binary(), libMesh::GMVIO::write_discontinuous_gmv(), libMesh::System::write_parallel_data(), 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().

96  { return cast_int<processor_id_type>(_communicator.size()); }
processor_id_type size() const
Definition: communicator.h:175
const Parallel::Communicator & _communicator

◆ n_SCALAR_dofs()

dof_id_type libMesh::DofMap::n_SCALAR_dofs ( ) const
inline
Returns
The number of SCALAR dofs.

Definition at line 579 of file dof_map.h.

References _n_SCALAR_dofs.

Referenced by distribute_dofs(), SCALAR_dof_indices(), and libMesh::PetscDMWrapper::set_point_range_in_section().

579 { return _n_SCALAR_dofs; }
dof_id_type _n_SCALAR_dofs
Definition: dof_map.h:1655

◆ n_variable_groups()

unsigned int libMesh::DofMap::n_variable_groups ( ) const
inline
Returns
The number of variables in the global solution vector. Defaults to 1, should be 1 for a scalar equation, 3 for 2D incompressible Navier Stokes (u,v,p), etc...

Definition at line 533 of file dof_map.h.

References _variable_groups.

Referenced by distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), dof_indices(), has_blocked_representation(), old_dof_indices(), reinit(), and set_nonlocal_dof_objects().

534  { return cast_int<unsigned int>(_variable_groups.size()); }
std::vector< VariableGroup > _variable_groups
Definition: dof_map.h:1503

◆ n_variables()

unsigned int libMesh::DofMap::n_variables ( ) const
inline
Returns
The number of variables in the global solution vector. Defaults to 1, should be 1 for a scalar equation, 3 for 2D incompressible Navier Stokes (u,v,p), etc...

Definition at line 541 of file dof_map.h.

References _variables.

Referenced by add_neighbors_to_send_list(), block_size(), libMesh::FEGenericBase< FEOutputType< T >::type >::coarsened_dof_values(), distribute_dofs(), DMlibMeshSetSystem_libMesh(), has_blocked_representation(), libMesh::SparsityPattern::Build::operator()(), reinit(), and use_coupled_neighbor_dofs().

542  { return cast_int<unsigned int>(_variables.size()); }
std::vector< Variable > _variables
Definition: dof_map.h:1498

◆ node_constraint_rows_begin()

NodeConstraints::const_iterator libMesh::DofMap::node_constraint_rows_begin ( ) const
inline
Returns
An iterator pointing to the first Node constraint row.

Definition at line 927 of file dof_map.h.

References _node_constraints.

928  { return _node_constraints.begin(); }
NodeConstraints _node_constraints
Definition: dof_map.h:1698

◆ node_constraint_rows_end()

NodeConstraints::const_iterator libMesh::DofMap::node_constraint_rows_end ( ) const
inline
Returns
An iterator pointing just past the last Node constraint row.

Definition at line 933 of file dof_map.h.

References _node_constraints.

934  { return _node_constraints.end(); }
NodeConstraints _node_constraints
Definition: dof_map.h:1698

◆ node_ptr()

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

Definition at line 306 of file dof_map.C.

References mesh.

Referenced by distribute_dofs().

307 {
308  return mesh.node_ptr(i);
309 }
MeshBase & mesh

◆ old_dof_indices()

void libMesh::DofMap::old_dof_indices ( const Elem *const  elem,
std::vector< dof_id_type > &  di,
const unsigned int  vn = libMesh::invalid_uint 
) const

After a mesh is refined and repartitioned it is possible that the _send_list will need to be augmented. This is the case when an element is refined and its children end up on different processors than the parent. These children will need values from the parent when projecting the solution onto the refined mesh, hence the parent's DOF indices need to be included in the _send_list. Fills the vector di with the global degree of freedom indices for the element using the DofMap::old_dof_object. If no variable number is specified then all variables are returned.

Definition at line 2434 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::MeshTools::Subdivision::find_one_ring(), libMesh::Elem::get_nodes(), libMesh::DofObject::has_dofs(), libMesh::Elem::infinite(), libMesh::DofObject::invalid_id, libMesh::invalid_uint, libMesh::Elem::is_vertex(), libMesh::Elem::JUST_COARSENED, libMesh::Elem::JUST_REFINED, libMesh::LAGRANGE, libMesh::DofObject::n_comp_group(), libMesh::FEInterface::n_dofs_at_node(), libMesh::FEInterface::n_dofs_at_node_function(), libMesh::FEInterface::n_dofs_per_elem(), n_nodes, libMesh::Elem::n_nodes(), libMesh::DofObject::n_systems(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::VariableGroup::number(), libMesh::DofObject::old_dof_object, libMesh::FEType::order, libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::Elem::refinement_flag(), libMesh::SCALAR, SCALAR_dof_indices(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::TRI3SUBDIVISION, libMesh::Variable::type(), libMesh::Elem::type(), and variable_group().

Referenced by libMesh::FEGenericBase< FEOutputType< T >::type >::coarsened_dof_values(), libMesh::BuildProjectionList::operator()(), and libMesh::FEMContext::pre_fe_reinit().

2437 {
2438  LOG_SCOPE("old_dof_indices()", "DofMap");
2439 
2440  libmesh_assert(elem);
2441 
2442  const ElemType type = elem->type();
2443  const unsigned int sys_num = this->sys_number();
2444  const unsigned int n_var_groups = this->n_variable_groups();
2445  const unsigned int dim = elem->dim();
2446 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2447  const bool is_inf = elem->infinite();
2448 #endif
2449 
2450  // If we have dof indices stored on the elem, and there's no chance
2451  // that we only have those indices because we were just p refined,
2452  // then we should have old dof indices too.
2453  libmesh_assert(!elem->has_dofs(sys_num) ||
2454  elem->p_refinement_flag() == Elem::JUST_REFINED ||
2455  elem->old_dof_object);
2456 
2457  // Clear the DOF indices vector.
2458  di.clear();
2459 
2460  // Determine the nodes contributing to element elem
2461  std::vector<const Node *> elem_nodes;
2462  const Node * const * nodes_ptr;
2463  unsigned int n_nodes;
2464  if (elem->type() == TRI3SUBDIVISION)
2465  {
2466  // Subdivision surface FE require the 1-ring around elem
2467  const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
2468  MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
2469  nodes_ptr = elem_nodes.data();
2470  n_nodes = cast_int<unsigned int>(elem_nodes.size());
2471  }
2472  else
2473  {
2474  // All other FE use only the nodes of elem itself
2475  nodes_ptr = elem->get_nodes();
2476  n_nodes = elem->n_nodes();
2477  }
2478 
2479  // Get the dof numbers
2480  for (unsigned int vg=0; vg<n_var_groups; vg++)
2481  {
2482  const VariableGroup & var = this->variable_group(vg);
2483  const unsigned int vars_in_group = var.n_variables();
2484 
2485  for (unsigned int vig=0; vig<vars_in_group; vig++)
2486  {
2487  const unsigned int v = var.number(vig);
2488  if ((vn == v) || (vn == libMesh::invalid_uint))
2489  {
2490  if (var.type().family == SCALAR &&
2491  (!elem ||
2492  var.active_on_subdomain(elem->subdomain_id())))
2493  {
2494  // We asked for this variable, so add it to the vector.
2495  std::vector<dof_id_type> di_new;
2496  this->SCALAR_dof_indices(di_new,v,true);
2497  di.insert( di.end(), di_new.begin(), di_new.end());
2498  }
2499  else
2500  if (var.active_on_subdomain(elem->subdomain_id()))
2501  { // Do this for all the variables if one was not specified
2502  // or just for the specified variable
2503 
2504  // Increase the polynomial order on p refined elements,
2505  // but make sure you get the right polynomial order for
2506  // the OLD degrees of freedom
2507  int p_adjustment = 0;
2508  if (elem->p_refinement_flag() == Elem::JUST_REFINED)
2509  {
2510  libmesh_assert_greater (elem->p_level(), 0);
2511  p_adjustment = -1;
2512  }
2513  else if (elem->p_refinement_flag() == Elem::JUST_COARSENED)
2514  {
2515  p_adjustment = 1;
2516  }
2517  FEType fe_type = var.type();
2518  fe_type.order = static_cast<Order>(fe_type.order +
2519  elem->p_level() +
2520  p_adjustment);
2521 
2522  const bool extra_hanging_dofs =
2524 
2525  const FEInterface::n_dofs_at_node_ptr ndan =
2527 
2528  // Get the node-based DOF numbers
2529  for (unsigned int n=0; n<n_nodes; n++)
2530  {
2531  const Node * node = nodes_ptr[n];
2532  const DofObject * old_dof_obj = node->old_dof_object;
2533  libmesh_assert(old_dof_obj);
2534 
2535  // There is a potential problem with h refinement. Imagine a
2536  // quad9 that has a linear FE on it. Then, on the hanging side,
2537  // it can falsely identify a DOF at the mid-edge node. This is why
2538  // we call FEInterface instead of node->n_comp() directly.
2539  const unsigned int nc =
2540 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2541  is_inf ?
2542  FEInterface::n_dofs_at_node(dim, fe_type, type, n) :
2543 #endif
2544  ndan (type, fe_type.order, n);
2545 
2546  const int n_comp = old_dof_obj->n_comp_group(sys_num,vg);
2547 
2548  // If this is a non-vertex on a hanging node with extra
2549  // degrees of freedom, we use the non-vertex dofs (which
2550  // come in reverse order starting from the end, to
2551  // simplify p refinement)
2552  if (extra_hanging_dofs && !elem->is_vertex(n))
2553  {
2554  const int dof_offset = n_comp - nc;
2555 
2556  // We should never have fewer dofs than necessary on a
2557  // node unless we're getting indices on a parent element
2558  // or a just-coarsened element
2559  if (dof_offset < 0)
2560  {
2561  libmesh_assert(!elem->active() || elem->refinement_flag() ==
2563  di.resize(di.size() + nc, DofObject::invalid_id);
2564  }
2565  else
2566  for (int i=n_comp-1; i>=dof_offset; i--)
2567  {
2568  const dof_id_type d =
2569  old_dof_obj->dof_number(sys_num, vg, vig, i, n_comp);
2570  libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2571  di.push_back(d);
2572  }
2573  }
2574  // If this is a vertex or an element without extra hanging
2575  // dofs, our dofs come in forward order coming from the
2576  // beginning
2577  else
2578  for (unsigned int i=0; i<nc; i++)
2579  {
2580  const dof_id_type d =
2581  old_dof_obj->dof_number(sys_num, vg, vig, i, n_comp);
2582  libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2583  di.push_back(d);
2584  }
2585  }
2586 
2587  // If there are any element-based DOF numbers, get them
2588  const unsigned int nc = FEInterface::n_dofs_per_elem(dim,
2589  fe_type,
2590  type);
2591 
2592  // We should never have fewer dofs than necessary on an
2593  // element unless we're getting indices on a parent element
2594  // or a just-coarsened element
2595  if (nc != 0)
2596  {
2597  const DofObject * old_dof_obj = elem->old_dof_object;
2598  libmesh_assert(old_dof_obj);
2599 
2600  const unsigned int n_comp =
2601  old_dof_obj->n_comp_group(sys_num,vg);
2602 
2603  if (old_dof_obj->n_systems() > sys_num &&
2604  nc <= n_comp)
2605  {
2606 
2607  for (unsigned int i=0; i<nc; i++)
2608  {
2609  const dof_id_type d =
2610  old_dof_obj->dof_number(sys_num, vg, vig, i, n_comp);
2611 
2612  di.push_back(d);
2613  }
2614  }
2615  else
2616  {
2617  libmesh_assert(!elem->active() || fe_type.family == LAGRANGE ||
2618  elem->refinement_flag() == Elem::JUST_COARSENED);
2619  di.resize(di.size() + nc, DofObject::invalid_id);
2620  }
2621  }
2622  }
2623  }
2624  } // end loop over variables within group
2625  } // end loop over variable groups
2626 }
static unsigned int n_dofs_per_elem(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:504
unsigned int n_variable_groups() const
Definition: dof_map.h:533
const unsigned int invalid_uint
Definition: libmesh.h:245
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
void find_one_ring(const Tri3Subdivision *elem, std::vector< const Node *> &nodes)
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

◆ prepare_send_list()

void libMesh::DofMap::prepare_send_list ( )

Takes the _send_list vector (which may have duplicate entries) and sorts it. The duplicate entries are then removed, resulting in a sorted _send_list with unique entries. Also calls any user-provided methods for adding to the send list.

Definition at line 1639 of file dof_map.C.

References _augment_send_list, _extra_send_list_context, _extra_send_list_function, _send_list, libMesh::DofMap::AugmentSendList::augment_send_list(), libMesh::out, and swap().

Referenced by libMesh::EquationSystems::allgather(), and libMesh::System::reinit_constraints().

1640 {
1641  LOG_SCOPE("prepare_send_list()", "DofMap");
1642 
1643  // Check to see if we have any extra stuff to add to the send_list
1645  {
1646  if (_augment_send_list)
1647  {
1648  libmesh_here();
1649  libMesh::out << "WARNING: You have specified both an extra send list function and object.\n"
1650  << " Are you sure this is what you meant to do??"
1651  << std::endl;
1652  }
1653 
1655  }
1656 
1657  if (_augment_send_list)
1659 
1660  // First sort the send list. After this
1661  // duplicated elements will be adjacent in the
1662  // vector
1663  std::sort(_send_list.begin(), _send_list.end());
1664 
1665  // Now use std::unique to remove duplicate entries
1666  std::vector<dof_id_type>::iterator new_end =
1667  std::unique (_send_list.begin(), _send_list.end());
1668 
1669  // Remove the end of the send_list. Use the "swap trick"
1670  // from Effective STL
1671  std::vector<dof_id_type> (_send_list.begin(), new_end).swap (_send_list);
1672 }
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1547
virtual void augment_send_list(std::vector< dof_id_type > &send_list)=0
AugmentSendList * _augment_send_list
Definition: dof_map.h:1569
void * _extra_send_list_context
Definition: dof_map.h:1579
void swap(Iterator &lhs, Iterator &rhs)
void(* _extra_send_list_function)(std::vector< dof_id_type > &, void *)
Definition: dof_map.h:1574
OStreamProxy out(std::cout)

◆ print_dof_constraints()

void libMesh::DofMap::print_dof_constraints ( std::ostream &  os = libMesh::out,
bool  print_nonlocal = false 
) const

Prints (from processor 0) all DoF and Node constraints. If print_nonlocal is true, then each constraint is printed once for each processor that knows about it, which may be useful for DistributedMesh debugging.

Definition at line 1418 of file dof_map_constraints.C.

1420 {
1421  parallel_object_only();
1422 
1423  std::string local_constraints =
1424  this->get_local_constraints(print_nonlocal);
1425 
1426  if (this->processor_id())
1427  {
1428  this->comm().send(0, local_constraints);
1429  }
1430  else
1431  {
1432  os << "Processor 0:\n";
1433  os << local_constraints;
1434 
1435  for (processor_id_type p=1, np=this->n_processors(); p != np; ++p)
1436  {
1437  this->comm().receive(p, local_constraints);
1438  os << "Processor " << p << ":\n";
1439  os << local_constraints;
1440  }
1441  }
1442 }
std::string get_local_constraints(bool print_nonlocal=false) const
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
uint8_t processor_id_type
Definition: id_types.h:99
const Parallel::Communicator & comm() const
processor_id_type n_processors() const
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
processor_id_type processor_id() const

◆ print_info() [1/2]

void libMesh::ReferenceCounter::print_info ( std::ostream &  out = libMesh::out)
staticinherited

Prints the reference information, by default to libMesh::out.

Definition at line 87 of file reference_counter.C.

References libMesh::ReferenceCounter::_enable_print_counter, and libMesh::ReferenceCounter::get_info().

88 {
90  out_stream << ReferenceCounter::get_info();
91 }
static std::string get_info()

◆ print_info() [2/2]

void libMesh::DofMap::print_info ( std::ostream &  os = libMesh::out) const

Prints summary info about the sparsity bandwidth and constraints.

Definition at line 2696 of file dof_map.C.

References get_info().

2697 {
2698  os << this->get_info();
2699 }
std::string get_info() const
Definition: dof_map.C:2703

◆ process_constraints()

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

Postprocesses any constrained degrees of freedom to be constrained only in terms of unconstrained dofs, then adds unconstrained dofs to the send_list and prepares that for use. This should be run after both system (create_dof_constraints) and user constraints have all been added.

Definition at line 3227 of file dof_map_constraints.C.

References mesh, and libMesh::Real.

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

3228 {
3229  // We've computed our local constraints, but they may depend on
3230  // non-local constraints that we'll need to take into account.
3231  this->allgather_recursive_constraints(mesh);
3232 
3234  {
3235  // Optionally check for cyclic constraints and throw an error
3236  // if they're detected. We always do this check below in dbg/devel
3237  // mode but here we optionally do it in opt mode as well.
3239  }
3240 
3241  // Create a set containing the DOFs we already depend on
3242  typedef std::set<dof_id_type> RCSet;
3243  RCSet unexpanded_set;
3244 
3245  for (const auto & i : _dof_constraints)
3246  unexpanded_set.insert(i.first);
3247 
3248  while (!unexpanded_set.empty())
3249  for (RCSet::iterator i = unexpanded_set.begin();
3250  i != unexpanded_set.end(); /* nothing */)
3251  {
3252  // If the DOF is constrained
3253  DofConstraints::iterator
3254  pos = _dof_constraints.find(*i);
3255 
3256  libmesh_assert (pos != _dof_constraints.end());
3257 
3258  DofConstraintRow & constraint_row = pos->second;
3259 
3260  DofConstraintValueMap::iterator rhsit =
3261  _primal_constraint_values.find(*i);
3262  Number constraint_rhs = (rhsit == _primal_constraint_values.end()) ?
3263  0 : rhsit->second;
3264 
3265  std::vector<dof_id_type> constraints_to_expand;
3266 
3267  for (const auto & item : constraint_row)
3268  if (item.first != *i && this->is_constrained_dof(item.first))
3269  {
3270  unexpanded_set.insert(item.first);
3271  constraints_to_expand.push_back(item.first);
3272  }
3273 
3274  for (const auto & expandable : constraints_to_expand)
3275  {
3276  const Real this_coef = constraint_row[expandable];
3277 
3278  DofConstraints::const_iterator
3279  subpos = _dof_constraints.find(expandable);
3280 
3281  libmesh_assert (subpos != _dof_constraints.end());
3282 
3283  const DofConstraintRow & subconstraint_row = subpos->second;
3284 
3285  for (const auto & item : subconstraint_row)
3286  {
3287  // Assert that the constraint is not cyclic.
3288  libmesh_assert(item.first != expandable);
3289  constraint_row[item.first] += item.second * this_coef;
3290  }
3291 
3292  DofConstraintValueMap::const_iterator subrhsit =
3293  _primal_constraint_values.find(expandable);
3294  if (subrhsit != _primal_constraint_values.end())
3295  constraint_rhs += subrhsit->second * this_coef;
3296 
3297  constraint_row.erase(expandable);
3298  }
3299 
3300  if (rhsit == _primal_constraint_values.end())
3301  {
3302  if (constraint_rhs != Number(0))
3303  _primal_constraint_values[*i] = constraint_rhs;
3304  else
3305  _primal_constraint_values.erase(*i);
3306  }
3307  else
3308  {
3309  if (constraint_rhs != Number(0))
3310  rhsit->second = constraint_rhs;
3311  else
3312  _primal_constraint_values.erase(rhsit);
3313  }
3314 
3315  if (constraints_to_expand.empty())
3316  i = unexpanded_set.erase(i);
3317  else
3318  ++i;
3319  }
3320 
3321  // In parallel we can't guarantee that nodes/dofs which constrain
3322  // others are on processors which are aware of that constraint, yet
3323  // we need such awareness for sparsity pattern generation. So send
3324  // other processors any constraints they might need to know about.
3325  this->scatter_constraints(mesh);
3326 
3327  // Now that we have our root constraint dependencies sorted out, add
3328  // them to the send_list
3330 }
bool _error_on_cyclic_constraint
Definition: dof_map.h:1493
void scatter_constraints(MeshBase &)
void allgather_recursive_constraints(MeshBase &)
DofConstraints _dof_constraints
Definition: dof_map.h:1687
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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

◆ processor_id()

processor_id_type libMesh::ParallelObject::processor_id ( ) const
inlineinherited
Returns
The rank of this processor in the group.

Definition at line 101 of file parallel_object.h.

References libMesh::ParallelObject::_communicator, and libMesh::Parallel::Communicator::rank().

Referenced by libMesh::BoundaryInfo::_find_id_maps(), libMesh::EquationSystems::_read_impl(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::DistributedMesh::add_elem(), libMesh::BoundaryInfo::add_elements(), add_neighbors_to_send_list(), libMesh::DistributedMesh::add_node(), libMesh::UnstructuredMesh::all_second_order(), libMesh::MeshTools::Modification::all_tri(), libMesh::FEMSystem::assembly(), libMesh::EquationSystems::build_discontinuous_solution_vector(), libMesh::Nemesis_IO_Helper::build_element_and_node_maps(), libMesh::InfElemBuilder::build_inf_elem(), libMesh::BoundaryInfo::build_node_list_from_side_list(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::DistributedMesh::clear(), libMesh::ExodusII_IO_Helper::close(), libMesh::Nemesis_IO_Helper::compute_border_node_ids(), libMesh::Nemesis_IO_Helper::compute_communication_map_parameters(), libMesh::Nemesis_IO_Helper::compute_internal_and_border_elems_and_internal_nodes(), libMesh::Nemesis_IO_Helper::compute_node_communication_maps(), 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::Nemesis_IO_Helper::construct_nemesis_filename(), libMesh::MeshTools::correct_node_proc_ids(), libMesh::ExodusII_IO_Helper::create(), libMesh::DistributedMesh::delete_elem(), libMesh::DistributedMesh::delete_node(), libMesh::MeshCommunication::delete_remote_elements(), distribute_dofs(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), libMesh::DistributedMesh::DistributedMesh(), end_dof(), end_old_dof(), libMesh::EnsightIO::EnsightIO(), libMesh::MeshFunction::find_element(), libMesh::MeshFunction::find_elements(), libMesh::UnstructuredMesh::find_neighbors(), first_dof(), first_old_dof(), libMesh::Nemesis_IO_Helper::get_cmap_params(), libMesh::Nemesis_IO_Helper::get_eb_info_global(), libMesh::Nemesis_IO_Helper::get_elem_cmap(), libMesh::Nemesis_IO_Helper::get_elem_map(), libMesh::MeshBase::get_info(), get_info(), libMesh::Nemesis_IO_Helper::get_init_global(), libMesh::Nemesis_IO_Helper::get_init_info(), libMesh::Nemesis_IO_Helper::get_loadbal_param(), libMesh::Nemesis_IO_Helper::get_node_cmap(), libMesh::Nemesis_IO_Helper::get_node_map(), libMesh::Nemesis_IO_Helper::get_ns_param_global(), libMesh::Nemesis_IO_Helper::get_ss_param_global(), libMesh::SparsityPattern::Build::handle_vi_vj(), libMesh::SystemSubsetBySubdomain::init(), libMesh::ExodusII_IO_Helper::initialize(), libMesh::ExodusII_IO_Helper::initialize_element_variables(), libMesh::ExodusII_IO_Helper::initialize_global_variables(), libMesh::ExodusII_IO_Helper::initialize_nodal_variables(), libMesh::DistributedMesh::insert_elem(), is_evaluable(), libMesh::SparsityPattern::Build::join(), last_dof(), 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_procids< Elem >(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_object_ids(), local_variable_indices(), libMesh::MeshRefinement::make_coarsening_compatible(), libMesh::MeshBase::n_active_local_elem(), libMesh::BoundaryInfo::n_boundary_conds(), libMesh::BoundaryInfo::n_edge_conds(), n_local_dofs(), libMesh::System::n_local_dofs(), libMesh::MeshBase::n_local_elem(), libMesh::MeshBase::n_local_nodes(), libMesh::BoundaryInfo::n_nodeset_conds(), libMesh::BoundaryInfo::n_shellface_conds(), libMesh::SparsityPattern::Build::operator()(), libMesh::DistributedMesh::own_node(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), libMesh::Nemesis_IO_Helper::put_cmap_params(), libMesh::Nemesis_IO_Helper::put_elem_cmap(), libMesh::Nemesis_IO_Helper::put_elem_map(), libMesh::Nemesis_IO_Helper::put_loadbal_param(), libMesh::Nemesis_IO_Helper::put_node_cmap(), libMesh::Nemesis_IO_Helper::put_node_map(), libMesh::NameBasedIO::read(), libMesh::Nemesis_IO::read(), libMesh::XdrIO::read(), libMesh::CheckpointIO::read(), libMesh::ExodusII_IO_Helper::read_elem_num_map(), libMesh::ExodusII_IO_Helper::read_global_values(), libMesh::CheckpointIO::read_header(), libMesh::XdrIO::read_header(), libMesh::System::read_header(), libMesh::System::read_legacy_data(), libMesh::ExodusII_IO_Helper::read_node_num_map(), libMesh::System::read_parallel_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::System::read_serialized_data(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::System::read_serialized_vector(), libMesh::System::read_serialized_vectors(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::CheckpointIO::select_split_config(), set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), libMesh::LaplaceMeshSmoother::smooth(), libMesh::MeshTools::total_weight(), libMesh::MeshRefinement::uniformly_coarsen(), libMesh::Parallel::Packing< T >::unpack(), libMesh::DistributedMesh::update_parallel_id_counts(), libMesh::NameBasedIO::write(), libMesh::XdrIO::write(), libMesh::CheckpointIO::write(), libMesh::EquationSystems::write(), libMesh::GMVIO::write_discontinuous_gmv(), libMesh::ExodusII_IO::write_element_data(), libMesh::ExodusII_IO_Helper::write_element_values(), libMesh::ExodusII_IO_Helper::write_elements(), libMesh::ExodusII_IO::write_global_data(), libMesh::ExodusII_IO_Helper::write_global_values(), libMesh::System::write_header(), libMesh::ExodusII_IO::write_information_records(), libMesh::ExodusII_IO_Helper::write_information_records(), libMesh::ExodusII_IO_Helper::write_nodal_coordinates(), libMesh::UCDIO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data_discontinuous(), libMesh::ExodusII_IO_Helper::write_nodal_values(), libMesh::Nemesis_IO_Helper::write_nodesets(), libMesh::ExodusII_IO_Helper::write_nodesets(), libMesh::System::write_parallel_data(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bc_names(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::System::write_serialized_data(), libMesh::XdrIO::write_serialized_nodes(), libMesh::XdrIO::write_serialized_nodesets(), libMesh::XdrIO::write_serialized_subdomain_names(), libMesh::System::write_serialized_vector(), libMesh::System::write_serialized_vectors(), libMesh::Nemesis_IO_Helper::write_sidesets(), libMesh::ExodusII_IO_Helper::write_sidesets(), libMesh::ExodusII_IO::write_timestep(), libMesh::ExodusII_IO_Helper::write_timestep(), and libMesh::ExodusII_IO::write_timestep_discontinuous().

102  { return cast_int<processor_id_type>(_communicator.rank()); }
const Parallel::Communicator & _communicator
processor_id_type rank() const
Definition: communicator.h:173

◆ reinit()

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

Reinitialize the underlying data structures conformal to the current mesh.

Definition at line 474 of file dof_map.C.

References _default_coupling, _dof_coupling, _n_SCALAR_dofs, libMesh::Variable::active_on_subdomain(), libMesh::CouplingMatrix::empty(), libMesh::Utility::enum_to_string(), libMesh::err, libMesh::FEInterface::extra_hanging_dofs(), libMesh::FEType::family, libMesh::OrderWrapper::get_order(), libMesh::DofObject::has_dofs(), invalidate_dofs(), libMesh::Elem::JUST_REFINED, std::max(), libMesh::FEInterface::max_order(), mesh, libMesh::DofObject::n_comp_group(), libMesh::FEInterface::n_dofs_at_node(), libMesh::FEInterface::n_dofs_per_elem(), n_variable_groups(), libMesh::VariableGroup::n_variables(), n_variables(), libMesh::DofObject::old_dof_object, libMesh::FEType::order, libMesh::SCALAR, libMesh::DofObject::set_n_comp_group(), libMesh::DofObject::set_old_dof_object(), libMesh::DofObject::set_vg_dof_base(), sys_number(), libMesh::Variable::type(), use_coupled_neighbor_dofs(), variable_group(), and libMesh::DofObject::vg_dof_base().

Referenced by distribute_dofs().

475 {
476  libmesh_assert (mesh.is_prepared());
477 
478  LOG_SCOPE("reinit()", "DofMap");
479 
480  // We ought to reconfigure our default coupling functor.
481  //
482  // The user might have removed it from our coupling functors set,
483  // but if so, who cares, this reconfiguration is cheap.
484 
485  // Avoid calling set_dof_coupling() with an empty/non-nullptr
486  // _dof_coupling matrix which may happen when there are actually no
487  // variables on the system.
488  if (this->_dof_coupling && this->_dof_coupling->empty() && !this->n_variables())
489  this->_dof_coupling = nullptr;
490  _default_coupling->set_dof_coupling(this->_dof_coupling);
491 
492  // By default we may want 0 or 1 levels of coupling
493  unsigned int standard_n_levels =
495  _default_coupling->set_n_levels
496  (std::max(_default_coupling->n_levels(), standard_n_levels));
497 
498  // But we *don't* want to restrict to a CouplingMatrix unless the
499  // user does so manually; the original libMesh behavior was to put
500  // ghost indices on the send_list regardless of variable.
501  //_default_evaluating->set_dof_coupling(this->_dof_coupling);
502 
503  const unsigned int
504  sys_num = this->sys_number(),
505  n_var_groups = this->n_variable_groups();
506 
507  // The DofObjects need to know how many variable groups we have, and
508  // how many variables there are in each group.
509  std::vector<unsigned int> n_vars_per_group; n_vars_per_group.reserve (n_var_groups);
510 
511  for (unsigned int vg=0; vg<n_var_groups; vg++)
512  n_vars_per_group.push_back (this->variable_group(vg).n_variables());
513 
514 #ifdef LIBMESH_ENABLE_AMR
515 
516  //------------------------------------------------------------
517  // Clear the old_dof_objects for all the nodes
518  // and elements so that we can overwrite them
519  for (auto & node : mesh.node_ptr_range())
520  {
521  node->clear_old_dof_object();
522  libmesh_assert (!node->old_dof_object);
523  }
524 
525  for (auto & elem : mesh.element_ptr_range())
526  {
527  elem->clear_old_dof_object();
528  libmesh_assert (!elem->old_dof_object);
529  }
530 
531 
532  //------------------------------------------------------------
533  // Set the old_dof_objects for the elements that
534  // weren't just created, if these old dof objects
535  // had variables
536  for (auto & elem : mesh.element_ptr_range())
537  {
538  // Skip the elements that were just refined
539  if (elem->refinement_flag() == Elem::JUST_REFINED)
540  continue;
541 
542  for (unsigned int n=0; n<elem->n_nodes(); n++)
543  {
544  Node & node = elem->node_ref(n);
545 
546  if (node.old_dof_object == nullptr)
547  if (node.has_dofs(sys_num))
548  node.set_old_dof_object();
549  }
550 
551  libmesh_assert (!elem->old_dof_object);
552 
553  if (elem->has_dofs(sys_num))
554  elem->set_old_dof_object();
555  }
556 
557 #endif // #ifdef LIBMESH_ENABLE_AMR
558 
559 
560  //------------------------------------------------------------
561  // Then set the number of variables for each \p DofObject
562  // equal to n_variables() for this system. This will
563  // handle new \p DofObjects that may have just been created
564 
565  // All the nodes
566  for (auto & node : mesh.node_ptr_range())
567  node->set_n_vars_per_group(sys_num, n_vars_per_group);
568 
569  // All the elements
570  for (auto & elem : mesh.element_ptr_range())
571  elem->set_n_vars_per_group(sys_num, n_vars_per_group);
572 
573  // Zero _n_SCALAR_dofs, it will be updated below.
574  this->_n_SCALAR_dofs = 0;
575 
576  //------------------------------------------------------------
577  // Next allocate space for the DOF indices
578  for (unsigned int vg=0; vg<n_var_groups; vg++)
579  {
580  const VariableGroup & vg_description = this->variable_group(vg);
581 
582  const unsigned int n_var_in_group = vg_description.n_variables();
583  const FEType & base_fe_type = vg_description.type();
584 
585  // Don't need to loop over elements for a SCALAR variable
586  // Just increment _n_SCALAR_dofs
587  if (base_fe_type.family == SCALAR)
588  {
589  this->_n_SCALAR_dofs += base_fe_type.order.get_order()*n_var_in_group;
590  continue;
591  }
592 
593  // This should be constant even on p-refined elements
594  const bool extra_hanging_dofs =
595  FEInterface::extra_hanging_dofs(base_fe_type);
596 
597  // For all the active elements, count vertex degrees of freedom.
598  for (auto & elem : mesh.active_element_ptr_range())
599  {
600  libmesh_assert(elem);
601 
602  // Skip the numbering if this variable is
603  // not active on this element's subdomain
604  if (!vg_description.active_on_subdomain(elem->subdomain_id()))
605  continue;
606 
607  const ElemType type = elem->type();
608  const unsigned int dim = elem->dim();
609 
610  FEType fe_type = base_fe_type;
611 
612 #ifdef LIBMESH_ENABLE_AMR
613  // Make sure we haven't done more p refinement than we can
614  // handle
615  if (elem->p_level() + base_fe_type.order >
616  FEInterface::max_order(base_fe_type, type))
617  {
618  libmesh_assert_less_msg(static_cast<unsigned int>(base_fe_type.order.get_order()),
619  FEInterface::max_order(base_fe_type,type),
620  "ERROR: Finite element "
621  << Utility::enum_to_string(base_fe_type.family)
622  << " on geometric element "
623  << Utility::enum_to_string(type)
624  << "\nonly supports FEInterface::max_order = "
625  << FEInterface::max_order(base_fe_type,type)
626  << ", not fe_type.order = "
627  << base_fe_type.order);
628 
629 # ifdef DEBUG
630  libMesh::err << "WARNING: Finite element "
631  << Utility::enum_to_string(base_fe_type.family)
632  << " on geometric element "
633  << Utility::enum_to_string(type) << std::endl
634  << "could not be p refined past FEInterface::max_order = "
635  << FEInterface::max_order(base_fe_type,type)
636  << std::endl;
637 # endif
638  elem->set_p_level(FEInterface::max_order(base_fe_type,type)
639  - base_fe_type.order);
640  }
641 #endif
642 
643  fe_type.order = static_cast<Order>(fe_type.order +
644  elem->p_level());
645 
646  // Allocate the vertex DOFs
647  for (unsigned int n=0; n<elem->n_nodes(); n++)
648  {
649  Node & node = elem->node_ref(n);
650 
651  if (elem->is_vertex(n))
652  {
653  const unsigned int old_node_dofs =
654  node.n_comp_group(sys_num, vg);
655 
656  const unsigned int vertex_dofs =
658  type, n),
659  old_node_dofs);
660 
661  // Some discontinuous FEs have no vertex dofs
662  if (vertex_dofs > old_node_dofs)
663  {
664  node.set_n_comp_group(sys_num, vg,
665  vertex_dofs);
666 
667  // Abusing dof_number to set a "this is a
668  // vertex" flag
669  node.set_vg_dof_base(sys_num, vg,
670  vertex_dofs);
671 
672  // libMesh::out << "sys_num,vg,old_node_dofs,vertex_dofs="
673  // << sys_num << ","
674  // << vg << ","
675  // << old_node_dofs << ","
676  // << vertex_dofs << '\n',
677  // node.debug_buffer();
678 
679  // libmesh_assert_equal_to (vertex_dofs, node.n_comp(sys_num, vg));
680  // libmesh_assert_equal_to (vertex_dofs, node.vg_dof_base(sys_num, vg));
681  }
682  }
683  }
684  } // done counting vertex dofs
685 
686  // count edge & face dofs next
687  for (auto & elem : mesh.active_element_ptr_range())
688  {
689  libmesh_assert(elem);
690 
691  // Skip the numbering if this variable is
692  // not active on this element's subdomain
693  if (!vg_description.active_on_subdomain(elem->subdomain_id()))
694  continue;
695 
696  const ElemType type = elem->type();
697  const unsigned int dim = elem->dim();
698 
699  FEType fe_type = base_fe_type;
700  fe_type.order = static_cast<Order>(fe_type.order +
701  elem->p_level());
702 
703  // Allocate the edge and face DOFs
704  for (unsigned int n=0; n<elem->n_nodes(); n++)
705  {
706  Node & node = elem->node_ref(n);
707 
708  const unsigned int old_node_dofs =
709  node.n_comp_group(sys_num, vg);
710 
711  const unsigned int vertex_dofs = old_node_dofs?
712  cast_int<unsigned int>(node.vg_dof_base (sys_num,vg)):0;
713 
714  const unsigned int new_node_dofs =
715  FEInterface::n_dofs_at_node(dim, fe_type, type, n);
716 
717  // We've already allocated vertex DOFs
718  if (elem->is_vertex(n))
719  {
720  libmesh_assert_greater_equal (old_node_dofs, vertex_dofs);
721  // //if (vertex_dofs < new_node_dofs)
722  // libMesh::out << "sys_num,vg,old_node_dofs,vertex_dofs,new_node_dofs="
723  // << sys_num << ","
724  // << vg << ","
725  // << old_node_dofs << ","
726  // << vertex_dofs << ","
727  // << new_node_dofs << '\n',
728  // node.debug_buffer();
729 
730  libmesh_assert_greater_equal (vertex_dofs, new_node_dofs);
731  }
732  // We need to allocate the rest
733  else
734  {
735  // If this has no dofs yet, it needs no vertex
736  // dofs, so we just give it edge or face dofs
737  if (!old_node_dofs)
738  {
739  node.set_n_comp_group(sys_num, vg,
740  new_node_dofs);
741  // Abusing dof_number to set a "this has no
742  // vertex dofs" flag
743  if (new_node_dofs)
744  node.set_vg_dof_base(sys_num, vg, 0);
745  }
746 
747  // If this has dofs, but has no vertex dofs,
748  // it may still need more edge or face dofs if
749  // we're p-refined.
750  else if (vertex_dofs == 0)
751  {
752  if (new_node_dofs > old_node_dofs)
753  {
754  node.set_n_comp_group(sys_num, vg,
755  new_node_dofs);
756 
757  node.set_vg_dof_base(sys_num, vg,
758  vertex_dofs);
759  }
760  }
761  // If this is another element's vertex,
762  // add more (non-overlapping) edge/face dofs if
763  // necessary
764  else if (extra_hanging_dofs)
765  {
766  if (new_node_dofs > old_node_dofs - vertex_dofs)
767  {
768  node.set_n_comp_group(sys_num, vg,
769  vertex_dofs + new_node_dofs);
770 
771  node.set_vg_dof_base(sys_num, vg,
772  vertex_dofs);
773  }
774  }
775  // If this is another element's vertex, add any
776  // (overlapping) edge/face dofs if necessary
777  else
778  {
779  libmesh_assert_greater_equal (old_node_dofs, vertex_dofs);
780  if (new_node_dofs > old_node_dofs)
781  {
782  node.set_n_comp_group(sys_num, vg,
783  new_node_dofs);
784 
785  node.set_vg_dof_base (sys_num, vg,
786  vertex_dofs);
787  }
788  }
789  }
790  }
791  // Allocate the element DOFs
792  const unsigned int dofs_per_elem =
793  FEInterface::n_dofs_per_elem(dim, fe_type,
794  type);
795 
796  elem->set_n_comp_group(sys_num, vg, dofs_per_elem);
797 
798  }
799  } // end loop over variable groups
800 
801  // Calling DofMap::reinit() by itself makes little sense,
802  // so we won't bother with nonlocal DofObjects.
803  // Those will be fixed by distribute_dofs
804 
805  //------------------------------------------------------------
806  // Finally, clear all the current DOF indices
807  // (distribute_dofs expects them cleared!)
808  this->invalidate_dofs(mesh);
809 }
static unsigned int n_dofs_per_elem(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:504
unsigned int n_variable_groups() const
Definition: dof_map.h:533
MeshBase & mesh
unsigned int n_variables() const
Definition: dof_map.h:541
bool use_coupled_neighbor_dofs(const MeshBase &mesh) const
Definition: dof_map.C:1682
long double max(long double a, double b)
static unsigned int max_order(const FEType &fe_t, const ElemType &el_t)
unsigned int sys_number() const
Definition: dof_map.h:1744
dof_id_type _n_SCALAR_dofs
Definition: dof_map.h:1655
static bool extra_hanging_dofs(const FEType &fe_t)
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:1752
CouplingMatrix * _dof_coupling
Definition: dof_map.h:1319
OStreamProxy err(std::cerr)
std::string enum_to_string(const T e)
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
void invalidate_dofs(MeshBase &mesh) const
Definition: dof_map.C:813
std::unique_ptr< DefaultCoupling > _default_coupling
Definition: dof_map.h:1587

◆ remove_adjoint_dirichlet_boundary()

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

Removes from the system the specified Dirichlet boundary for the adjoint equation defined by Quantity of interest index q

Definition at line 4336 of file dof_map_constraints.C.

References libMesh::DirichletBoundary::b, end, and libMesh::DirichletBoundary::variables.

4338 {
4339  libmesh_assert_greater(_adjoint_dirichlet_boundaries.size(),
4340  qoi_index);
4341 
4342  auto lam = [&boundary_to_remove](const DirichletBoundary * bdy)
4343  {return bdy->b == boundary_to_remove.b && bdy->variables == boundary_to_remove.variables;};
4344 
4345  auto it = std::find_if(_adjoint_dirichlet_boundaries[qoi_index]->begin(),
4346  _adjoint_dirichlet_boundaries[qoi_index]->end(),
4347  lam);
4348 
4349  // Delete it and remove it
4350  libmesh_assert (it != _adjoint_dirichlet_boundaries[qoi_index]->end());
4351  delete *it;
4352  _adjoint_dirichlet_boundaries[qoi_index]->erase(it);
4353 }
Class for specifying Dirichlet boundary conditions as constraints.
IterBase * end
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1727

◆ remove_algebraic_ghosting_functor()

void libMesh::DofMap::remove_algebraic_ghosting_functor ( GhostingFunctor evaluable_functor)

Removes a functor which was previously added to the set of algebraic ghosting functors, from both this DofMap and from the underlying mesh.

Definition at line 1840 of file dof_map.C.

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

Referenced by remove_default_ghosting().

1841 {
1842  _algebraic_ghosting_functors.erase(&evaluable_functor);
1843  _mesh.remove_ghosting_functor(evaluable_functor);
1844 }
void remove_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: mesh_base.C:281
std::set< GhostingFunctor * > _algebraic_ghosting_functors
Definition: dof_map.h:1605
MeshBase & _mesh
Definition: dof_map.h:1518

◆ remove_coupling_functor()

void libMesh::DofMap::remove_coupling_functor ( GhostingFunctor coupling_functor)

Removes a functor which was previously added to the set of coupling functors, from both this DofMap and from the underlying mesh.

Definition at line 1820 of file dof_map.C.

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

Referenced by remove_default_ghosting().

1821 {
1822  _coupling_functors.erase(&coupling_functor);
1823  _mesh.remove_ghosting_functor(coupling_functor);
1824 }
void remove_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: mesh_base.C:281
std::set< GhostingFunctor * > _coupling_functors
Definition: dof_map.h:1618
MeshBase & _mesh
Definition: dof_map.h:1518

◆ remove_default_ghosting()

void libMesh::DofMap::remove_default_ghosting ( )

Remove any default ghosting functor(s). User-added ghosting functors will be unaffected.

Unless user-added equivalent ghosting functors exist, removing the default coupling functor is only safe for explicit solves, and removing the default algebraic ghosting functor is only safe for codes where no evaluations on neighbor cells (e.g. no jump error estimators) are done.

Defaults can be restored manually via add_default_ghosting(), or automatically if clear() returns the DofMap to a default state.

Definition at line 1792 of file dof_map.C.

References default_algebraic_ghosting(), default_coupling(), remove_algebraic_ghosting_functor(), and remove_coupling_functor().

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

1793 {
1796 }
DefaultCoupling & default_coupling()
Definition: dof_map.h:329
DefaultCoupling & default_algebraic_ghosting()
Definition: dof_map.h:379
void remove_coupling_functor(GhostingFunctor &coupling_functor)
Definition: dof_map.C:1820
void remove_algebraic_ghosting_functor(GhostingFunctor &evaluable_functor)
Definition: dof_map.C:1840

◆ remove_dirichlet_boundary()

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

Removes the specified Dirichlet boundary from the system.

Definition at line 4321 of file dof_map_constraints.C.

References libMesh::DirichletBoundary::b, and libMesh::DirichletBoundary::variables.

4322 {
4323  // Find a boundary condition matching the one to be removed
4324  auto lam = [&boundary_to_remove](const DirichletBoundary * bdy)
4325  {return bdy->b == boundary_to_remove.b && bdy->variables == boundary_to_remove.variables;};
4326 
4327  auto it = std::find_if(_dirichlet_boundaries->begin(), _dirichlet_boundaries->end(), lam);
4328 
4329  // Delete it and remove it
4330  libmesh_assert (it != _dirichlet_boundaries->end());
4331  delete *it;
4332  _dirichlet_boundaries->erase(it);
4333 }
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Definition: dof_map.h:1721
Class for specifying Dirichlet boundary conditions as constraints.

◆ SCALAR_dof_indices()

void libMesh::DofMap::SCALAR_dof_indices ( std::vector< dof_id_type > &  di,
const unsigned int  vn,
const bool  old_dofs = false 
) const

Fills the vector di with the global degree of freedom indices corresponding to the SCALAR variable vn. If old_dofs=true, the old SCALAR dof indices are returned.

Note
We do not need to pass in an element since SCALARs are global variables.

Definition at line 2348 of file dof_map.C.

References _first_old_scalar_df, _first_scalar_df, libMesh::OrderWrapper::get_order(), libMesh::DofObject::invalid_id, n_old_dofs(), n_SCALAR_dofs(), libMesh::FEType::order, libMesh::SCALAR, libMesh::Variable::type(), and variable().

Referenced by dof_indices(), local_variable_indices(), old_dof_indices(), libMesh::System::project_vector(), libMesh::System::projection_matrix(), libMesh::System::read_parallel_data(), libMesh::System::read_SCALAR_dofs(), libMesh::System::write_parallel_data(), and libMesh::System::write_SCALAR_dofs().

2356 {
2357  LOG_SCOPE("SCALAR_dof_indices()", "DofMap");
2358 
2359  libmesh_assert(this->variable(vn).type().family == SCALAR);
2360 
2361 #ifdef LIBMESH_ENABLE_AMR
2362  // If we're asking for old dofs then we'd better have some
2363  if (old_dofs)
2364  libmesh_assert_greater_equal(n_old_dofs(), n_SCALAR_dofs());
2365 
2366  dof_id_type my_idx = old_dofs ?
2367  this->_first_old_scalar_df[vn] : this->_first_scalar_df[vn];
2368 #else
2369  dof_id_type my_idx = this->_first_scalar_df[vn];
2370 #endif
2371 
2372  libmesh_assert_not_equal_to(my_idx, DofObject::invalid_id);
2373 
2374  // The number of SCALAR dofs comes from the variable order
2375  const int n_dofs_vn = this->variable(vn).type().order.get_order();
2376 
2377  di.resize(n_dofs_vn);
2378  for (int i = 0; i != n_dofs_vn; ++i)
2379  di[i] = my_idx++;
2380 }
dof_id_type n_SCALAR_dofs() const
Definition: dof_map.h:579
OrderWrapper order
Definition: fe_type.h:198
dof_id_type n_old_dofs() const
Definition: dof_map.h:1271
std::vector< dof_id_type > _first_scalar_df
Definition: dof_map.h:1541
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
static const dof_id_type invalid_id
Definition: dof_object.h:347
int get_order() const
Definition: fe_type.h:78
uint8_t dof_id_type
Definition: id_types.h:64
const FEType & type() const
Definition: variable.h:119

◆ scatter_constraints()

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

Sends constraint equations to constraining processors

Definition at line 3432 of file dof_map_constraints.C.

References libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::MeshBase::active_not_local_elements_begin(), libMesh::MeshBase::active_not_local_elements_end(), libMesh::as_range(), data, end, libMesh::DofObject::id(), libMesh::index_range(), libMesh::MeshBase::is_serial(), mesh, libMesh::MeshBase::node_ptr(), libMesh::DofObject::processor_id(), libMesh::Parallel::push_parallel_vector_data(), libMesh::TypeVector< T >::size(), and libMesh::Parallel::wait().

3433 {
3434  // At this point each processor with a constrained node knows
3435  // the corresponding constraint row, but we also need each processor
3436  // with a constrainer node to know the corresponding row(s).
3437 
3438  // This function must be run on all processors at once
3439  parallel_object_only();
3440 
3441  // Return immediately if there's nothing to gather
3442  if (this->n_processors() == 1)
3443  return;
3444 
3445  // We might get to return immediately if none of the processors
3446  // found any constraints
3447  unsigned int has_constraints = !_dof_constraints.empty()
3448 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3449  || !_node_constraints.empty()
3450 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
3451  ;
3452  this->comm().max(has_constraints);
3453  if (!has_constraints)
3454  return;
3455 
3456  // We may be receiving packed_range sends out of order with
3457  // parallel_sync tags, so make sure they're received correctly.
3458  Parallel::MessageTag range_tag = this->comm().get_unique_tag(1414);
3459 
3460 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3461  std::map<processor_id_type, std::set<dof_id_type>> pushed_node_ids;
3462 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
3463 
3464  std::map<processor_id_type, std::set<dof_id_type>> pushed_ids;
3465 
3466  // Collect the dof constraints I need to push to each processor
3467  dof_id_type constrained_proc_id = 0;
3468  for (auto & i : _dof_constraints)
3469  {
3470  const dof_id_type constrained = i.first;
3471  while (constrained >= _end_df[constrained_proc_id])
3472  constrained_proc_id++;
3473 
3474  if (constrained_proc_id != this->processor_id())
3475  continue;
3476 
3477  DofConstraintRow & row = i.second;
3478  for (auto & j : row)
3479  {
3480  const dof_id_type constraining = j.first;
3481 
3482  processor_id_type constraining_proc_id = 0;
3483  while (constraining >= _end_df[constraining_proc_id])
3484  constraining_proc_id++;
3485 
3486  if (constraining_proc_id != this->processor_id() &&
3487  constraining_proc_id != constrained_proc_id)
3488  pushed_ids[constraining_proc_id].insert(constrained);
3489  }
3490  }
3491 
3492  // Pack the dof constraint rows and rhs's to push
3493 
3494  std::map<processor_id_type,
3495  std::vector<std::vector<std::pair<dof_id_type, Real>>>>
3496  pushed_keys_vals, pushed_keys_vals_to_me;
3497 
3498  std::map<processor_id_type, std::vector<std::pair<dof_id_type, Number>>>
3499  pushed_ids_rhss, pushed_ids_rhss_to_me;
3500 
3501  auto gather_ids =
3502  [this,
3503  & pushed_ids,
3504  & pushed_keys_vals,
3505  & pushed_ids_rhss]
3506  ()
3507  {
3508  for (auto & pid_id_pair : pushed_ids)
3509  {
3510  const processor_id_type pid = pid_id_pair.first;
3511  const std::set<dof_id_type>
3512  & pid_ids = pid_id_pair.second;
3513 
3514  const std::size_t ids_size = pid_ids.size();
3515  std::vector<std::vector<std::pair<dof_id_type, Real>>> &
3516  keys_vals = pushed_keys_vals[pid];
3517  std::vector<std::pair<dof_id_type,Number>> &
3518  ids_rhss = pushed_ids_rhss[pid];
3519  keys_vals.resize(ids_size);
3520  ids_rhss.resize(ids_size);
3521 
3522  std::size_t push_i;
3523  std::set<dof_id_type>::const_iterator it;
3524  for (push_i = 0, it = pid_ids.begin();
3525  it != pid_ids.end(); ++push_i, ++it)
3526  {
3527  const dof_id_type constrained = *it;
3528  DofConstraintRow & row = _dof_constraints[constrained];
3529  keys_vals[push_i].assign(row.begin(), row.end());
3530 
3531  DofConstraintValueMap::const_iterator rhsit =
3532  _primal_constraint_values.find(constrained);
3533  ids_rhss[push_i].first = constrained;
3534  ids_rhss[push_i].second =
3535  (rhsit == _primal_constraint_values.end()) ?
3536  0 : rhsit->second;
3537  }
3538  }
3539  };
3540 
3541  gather_ids();
3542 
3543  auto ids_rhss_action_functor =
3544  [& pushed_ids_rhss_to_me]
3545  (processor_id_type pid,
3546  const std::vector<std::pair<dof_id_type, Number>> & data)
3547  {
3548  pushed_ids_rhss_to_me[pid] = data;
3549  };
3550 
3551  auto keys_vals_action_functor =
3552  [& pushed_keys_vals_to_me]
3553  (processor_id_type pid,
3554  const std::vector<std::vector<std::pair<dof_id_type, Real>>> & data)
3555  {
3556  pushed_keys_vals_to_me[pid] = data;
3557  };
3558 
3559  // Trade pushed dof constraint rows
3561  (this->comm(), pushed_ids_rhss, ids_rhss_action_functor);
3563  (this->comm(), pushed_keys_vals, keys_vals_action_functor);
3564 
3565  // Now work on traded dof constraint rows
3566  auto receive_dof_constraints =
3567  [this,
3568  & pushed_ids_rhss_to_me,
3569  & pushed_keys_vals_to_me]
3570  ()
3571  {
3572  for (auto & pid_id_pair : pushed_ids_rhss_to_me)
3573  {
3574  const processor_id_type pid = pid_id_pair.first;
3575  const auto & ids_rhss = pid_id_pair.second;
3576  const auto & keys_vals = pushed_keys_vals_to_me[pid];
3577 
3578  libmesh_assert_equal_to
3579  (ids_rhss.size(), keys_vals.size());
3580 
3581  // Add the dof constraints that I've been sent
3582  for (auto i : index_range(ids_rhss))
3583  {
3584  dof_id_type constrained = ids_rhss[i].first;
3585 
3586  // If we don't already have a constraint for this dof,
3587  // add the one we were sent
3588  if (!this->is_constrained_dof(constrained))
3589  {
3590  DofConstraintRow & row = _dof_constraints[constrained];
3591  for (auto & key_val : keys_vals[i])
3592  {
3593  row[key_val.first] = key_val.second;
3594  }
3595  if (ids_rhss[i].second != Number(0))
3596  _primal_constraint_values[constrained] =
3597  ids_rhss[i].second;
3598  else
3599  _primal_constraint_values.erase(constrained);
3600  }
3601  }
3602  }
3603  };
3604 
3605  receive_dof_constraints();
3606 
3607 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3608  // Collect the node constraints to push to each processor
3609  for (auto & i : _node_constraints)
3610  {
3611  const Node * constrained = i.first;
3612 
3613  if (constrained->processor_id() != this->processor_id())
3614  continue;
3615 
3616  NodeConstraintRow & row = i.second.first;
3617  for (auto & j : row)
3618  {
3619  const Node * constraining = j.first;
3620 
3621  if (constraining->processor_id() != this->processor_id() &&
3622  constraining->processor_id() != constrained->processor_id())
3623  pushed_node_ids[constraining->processor_id()].insert(constrained->id());
3624  }
3625  }
3626 
3627  // Pack the node constraint rows and rhss to push
3628  std::map<processor_id_type,
3629  std::vector<std::vector<std::pair<dof_id_type,Real>>>>
3630  pushed_node_keys_vals, pushed_node_keys_vals_to_me;
3631  std::map<processor_id_type, std::vector<std::pair<dof_id_type, Point>>>
3632  pushed_node_ids_offsets, pushed_node_ids_offsets_to_me;
3633  std::map<processor_id_type, std::set<const Node *>> pushed_nodes;
3634 
3635  for (auto & pid_id_pair : pushed_node_ids)
3636  {
3637  const processor_id_type pid = pid_id_pair.first;
3638  const std::set<dof_id_type>
3639  & pid_ids = pid_id_pair.second;
3640 
3641  const std::size_t ids_size = pid_ids.size();
3642  std::vector<std::vector<std::pair<dof_id_type,Real>>> &
3643  keys_vals = pushed_node_keys_vals[pid];
3644  std::vector<std::pair<dof_id_type, Point>> &
3645  ids_offsets = pushed_node_ids_offsets[pid];
3646  keys_vals.resize(ids_size);
3647  ids_offsets.resize(ids_size);
3648  std::set<const Node *> & nodes = pushed_nodes[pid];
3649 
3650  std::size_t push_i;
3651  std::set<dof_id_type>::const_iterator it;
3652  for (push_i = 0, it = pid_ids.begin();
3653  it != pid_ids.end(); ++push_i, ++it)
3654  {
3655  const Node * constrained = mesh.node_ptr(*it);
3656 
3657  if (constrained->processor_id() != pid)
3658  nodes.insert(constrained);
3659 
3660  NodeConstraintRow & row = _node_constraints[constrained].first;
3661  std::size_t row_size = row.size();
3662  keys_vals[push_i].reserve(row_size);
3663  for (const auto & j : row)
3664  {
3665  const Node * constraining = j.first;
3666 
3667  keys_vals[push_i].push_back
3668  (std::make_pair(constraining->id(), j.second));
3669 
3670  if (constraining->processor_id() != pid)
3671  nodes.insert(constraining);
3672  }
3673 
3674  ids_offsets[push_i].first = *it;
3675  ids_offsets[push_i].second = _node_constraints[constrained].second;
3676  }
3677  }
3678 
3679  auto node_ids_offsets_action_functor =
3680  [& pushed_node_ids_offsets_to_me]
3681  (processor_id_type pid,
3682  const std::vector<std::pair<dof_id_type, Point>> & data)
3683  {
3684  pushed_node_ids_offsets_to_me[pid] = data;
3685  };
3686 
3687  auto node_keys_vals_action_functor =
3688  [& pushed_node_keys_vals_to_me]
3689  (processor_id_type pid,
3690  const std::vector<std::vector<std::pair<dof_id_type, Real>>> & data)
3691  {
3692  pushed_node_keys_vals_to_me[pid] = data;
3693  };
3694 
3695  // Trade pushed node constraint rows
3697  (this->comm(), pushed_node_ids_offsets, node_ids_offsets_action_functor);
3699  (this->comm(), pushed_node_keys_vals, node_keys_vals_action_functor);
3700 
3701  // Constraining nodes might not even exist on our subset of a
3702  // distributed mesh, so let's make them exist.
3703  std::vector<Parallel::Request> send_requests;
3704  if (!mesh.is_serial())
3705  {
3706  for (auto & pid_id_pair : pushed_node_ids_offsets)
3707  {
3708  const processor_id_type pid = pid_id_pair.first;
3709  send_requests.push_back(Parallel::Request());
3710  this->comm().send_packed_range
3711  (pid, &mesh,
3712  pushed_nodes[pid].begin(), pushed_nodes[pid].end(),
3713  send_requests.back(), range_tag);
3714  }
3715  }
3716 
3717  for (auto & pid_id_pair : pushed_node_ids_offsets_to_me)
3718  {
3719  const processor_id_type pid = pid_id_pair.first;
3720  const auto & ids_offsets = pid_id_pair.second;
3721  const auto & keys_vals = pushed_node_keys_vals_to_me[pid];
3722 
3723  libmesh_assert_equal_to
3724  (ids_offsets.size(), keys_vals.size());
3725 
3726  if (!mesh.is_serial())
3727  this->comm().receive_packed_range
3729  (Node**)nullptr, range_tag);
3730 
3731  // Add the node constraints that I've been sent
3732  for (auto i : index_range(ids_offsets))
3733  {
3734  dof_id_type constrained_id = ids_offsets[i].first;
3735 
3736  // If we don't already have a constraint for this node,
3737  // add the one we were sent
3738  const Node * constrained = mesh.node_ptr(constrained_id);
3739  if (!this->is_constrained_node(constrained))
3740  {
3741  NodeConstraintRow & row = _node_constraints[constrained].first;
3742  for (auto & key_val : keys_vals[i])
3743  {
3744  const Node * key_node = mesh.node_ptr(key_val.first);
3745  row[key_node] = key_val.second;
3746  }
3747  _node_constraints[constrained].second =
3748  ids_offsets[i].second;
3749  }
3750  }
3751  }
3752 
3753  Parallel::wait(send_requests);
3754 
3755 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
3756 
3757  // Next we need to push constraints to processors which don't own
3758  // the constrained dof, don't own the constraining dof, but own an
3759  // element supporting the constraining dof.
3760  //
3761  // We need to be able to quickly look up constrained dof ids by what
3762  // constrains them, so that we can handle the case where we see a
3763  // foreign element containing one of our constraining DoF ids and we
3764  // need to push that constraint.
3765  //
3766  // Getting distributed adaptive sparsity patterns right is hard.
3767 
3768  typedef std::map<dof_id_type, std::set<dof_id_type>> DofConstrainsMap;
3769  DofConstrainsMap dof_id_constrains;
3770 
3771  for (auto & i : _dof_constraints)
3772  {
3773  const dof_id_type constrained = i.first;
3774  DofConstraintRow & row = i.second;
3775  for (const auto & j : row)
3776  {
3777  const dof_id_type constraining = j.first;
3778 
3779  dof_id_type constraining_proc_id = 0;
3780  while (constraining >= _end_df[constraining_proc_id])
3781  constraining_proc_id++;
3782 
3783  if (constraining_proc_id == this->processor_id())
3784  dof_id_constrains[constraining].insert(constrained);
3785  }
3786  }
3787 
3788  // Loop over all foreign elements, find any supporting our
3789  // constrained dof indices.
3790  pushed_ids.clear();
3791 
3792  for (const auto & elem : as_range(mesh.active_not_local_elements_begin(),
3794  {
3795  std::vector<dof_id_type> my_dof_indices;
3796  this->dof_indices (elem, my_dof_indices);
3797 
3798  for (const auto & dof : my_dof_indices)
3799  {
3800  DofConstrainsMap::const_iterator dcmi = dof_id_constrains.find(dof);
3801  if (dcmi != dof_id_constrains.end())
3802  {
3803  for (const auto & constrained : dcmi->second)
3804  {
3805  dof_id_type the_constrained_proc_id = 0;
3806  while (constrained >= _end_df[the_constrained_proc_id])
3807  the_constrained_proc_id++;
3808 
3809  const processor_id_type elemproc = elem->processor_id();
3810  if (elemproc != the_constrained_proc_id)
3811  pushed_ids[elemproc].insert(constrained);
3812  }
3813  }
3814  }
3815  }
3816 
3817  pushed_ids_rhss.clear();
3818  pushed_ids_rhss_to_me.clear();
3819  pushed_keys_vals.clear();
3820  pushed_keys_vals_to_me.clear();
3821 
3822  gather_ids();
3823 
3824  // Trade pushed dof constraint rows
3826  (this->comm(), pushed_ids_rhss, ids_rhss_action_functor);
3828  (this->comm(), pushed_keys_vals, keys_vals_action_functor);
3829 
3830  receive_dof_constraints();
3831 
3832  // Finally, we need to handle the case of remote dof coupling. If a
3833  // processor's element is coupled to a ghost element, then the
3834  // processor needs to know about all constraints which affect the
3835  // dofs on that ghost element, so we'll have to query the ghost
3836  // element's owner.
3837 
3838  GhostingFunctor::map_type elements_to_couple;
3839 
3840  // Man, I wish we had guaranteed unique_ptr availability...
3841  std::set<CouplingMatrix*> temporary_coupling_matrices;
3842 
3844  (elements_to_couple,
3845  temporary_coupling_matrices,
3846  this->coupling_functors_begin(),
3847  this->coupling_functors_end(),
3850  this->processor_id());
3851 
3852  // Each ghost-coupled element's owner should get a request for its dofs
3853  std::set<dof_id_type> requested_dofs;
3854 
3855  for (const auto & pr : elements_to_couple)
3856  {
3857  const Elem * elem = pr.first;
3858 
3859  // FIXME - optimize for the non-fully-coupled case?
3860  std::vector<dof_id_type> element_dofs;
3861  this->dof_indices(elem, element_dofs);
3862 
3863  for (auto dof : element_dofs)
3864  requested_dofs.insert(dof);
3865  }
3866 
3867  this->gather_constraints(mesh, requested_dofs, false);
3868 }
void wait(std::vector< Request > &r)
Definition: request.C:213
bool is_constrained_node(const Node *node) const
Definition: dof_map.h:1812
A geometric point in (x,y,z) space associated with a DOF.
Definition: node.h:52
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
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
The base class for all geometric element types.
Definition: elem.h:100
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
IterBase * end
MessageTag get_unique_tag(int tagvalue) const
Definition: communicator.C:201
processor_id_type n_processors() const
virtual bool is_serial() const
Definition: mesh_base.h:154
dof_id_type id() const
Definition: dof_object.h:655
virtual element_iterator active_local_elements_begin()=0
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
std::unordered_map< const Elem *, const CouplingMatrix * > map_type
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
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
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1535
virtual element_iterator active_not_local_elements_begin()=0
std::set< GhostingFunctor * >::const_iterator coupling_functors_end() const
Definition: dof_map.h:323
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
processor_id_type processor_id() const
Definition: dof_object.h:717
virtual element_iterator active_local_elements_end()=0
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
uint8_t dof_id_type
Definition: id_types.h:64
NodeConstraints _node_constraints
Definition: dof_map.h:1698

◆ semilocal_index()

bool libMesh::DofMap::semilocal_index ( dof_id_type  dof_index) const
Returns
true if degree of freedom index dof_index is either a local index 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 2384 of file dof_map.C.

References _send_list, and local_index().

Referenced by all_semilocal_indices().

2385 {
2386  // If it's not in the local indices
2387  if (!this->local_index(dof_index))
2388  {
2389  // and if it's not in the ghost indices, then we're not
2390  // semilocal
2391  if (!std::binary_search(_send_list.begin(), _send_list.end(), dof_index))
2392  return false;
2393  }
2394 
2395  return true;
2396 }
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1547
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:738

◆ set_error_on_cyclic_constraint()

void libMesh::DofMap::set_error_on_cyclic_constraint ( bool  error_on_cyclic_constraint)

Specify whether or not we perform an extra (opt-mode enabled) check for cyclic constraints. If a cyclic constraint is present then the system constraints are not valid, so if error_on_cyclic_constraint is true we will throw an error in this case.

Definition at line 238 of file dof_map.C.

References _error_on_cyclic_constraint.

239 {
240  _error_on_cyclic_constraint = error_on_cyclic_constraint;
241 }
bool _error_on_cyclic_constraint
Definition: dof_map.h:1493

◆ set_implicit_neighbor_dofs()

void libMesh::DofMap::set_implicit_neighbor_dofs ( bool  implicit_neighbor_dofs)

Allow the implicit_neighbor_dofs flag to be set programmatically. This overrides the –implicit_neighbor_dofs commandline option. We can use this to set the implicit neighbor dofs option differently for different systems, whereas the commandline option is the same for all systems.

Definition at line 1675 of file dof_map.C.

References _implicit_neighbor_dofs, and _implicit_neighbor_dofs_initialized.

1676 {
1678  _implicit_neighbor_dofs = implicit_neighbor_dofs;
1679 }
bool _implicit_neighbor_dofs_initialized
Definition: dof_map.h:1736
bool _implicit_neighbor_dofs
Definition: dof_map.h:1737

◆ set_nonlocal_dof_objects()

template<typename iterator_type >
void libMesh::DofMap::set_nonlocal_dof_objects ( iterator_type  objects_begin,
iterator_type  objects_end,
MeshBase mesh,
dofobject_accessor  objects 
)
private

Helper function for distributing dofs in parallel

Definition at line 321 of file dof_map.C.

References libMesh::ParallelObject::comm(), data, libMesh::DofObject::dof_number(), libMesh::DofObject::id(), libMesh::index_range(), libMesh::DofObject::invalid_id, libMesh::DofObject::invalid_processor_id, mesh, libMesh::DofObject::n_comp(), libMesh::DofObject::n_comp_group(), libMesh::ParallelObject::n_processors(), libMesh::DofObject::n_var_groups(), n_variable_groups(), libMesh::DofObject::n_vars(), libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), libMesh::Parallel::pull_parallel_vector_data(), libMesh::DofObject::set_n_comp_group(), libMesh::DofObject::set_vg_dof_base(), sys_number(), and libMesh::DofObject::vg_dof_base().

Referenced by distribute_dofs().

325 {
326  // This function must be run on all processors at once
327  parallel_object_only();
328 
329  // First, iterate over local objects to find out how many
330  // are on each processor
331  std::unordered_map<processor_id_type, dof_id_type> ghost_objects_from_proc;
332 
333  iterator_type it = objects_begin;
334 
335  for (; it != objects_end; ++it)
336  {
337  DofObject * obj = *it;
338 
339  if (obj)
340  {
341  processor_id_type obj_procid = obj->processor_id();
342  // We'd better be completely partitioned by now
343  libmesh_assert_not_equal_to (obj_procid, DofObject::invalid_processor_id);
344  ghost_objects_from_proc[obj_procid]++;
345  }
346  }
347 
348  // Request sets to send to each processor
349  std::map<processor_id_type, std::vector<dof_id_type>>
350  requested_ids;
351 
352  // We know how many of our objects live on each processor, so
353  // reserve() space for requests from each.
354  auto ghost_end = ghost_objects_from_proc.end();
355  for (processor_id_type p=0, np = this->n_processors(); p != np; ++p)
356  if (p != this->processor_id())
357  {
358  auto ghost_it = ghost_objects_from_proc.find(p);
359  if (ghost_it != ghost_end)
360  requested_ids[p].reserve(ghost_it->second);
361  }
362 
363  for (it = objects_begin; it != objects_end; ++it)
364  {
365  DofObject * obj = *it;
366  if (obj->processor_id() != DofObject::invalid_processor_id)
367  requested_ids[obj->processor_id()].push_back(obj->id());
368  }
369 #ifdef DEBUG
370  for (processor_id_type p=0, np = this->n_processors(); p != np; ++p)
371  {
372  if (ghost_objects_from_proc.count(p))
373  libmesh_assert_equal_to (requested_ids[p].size(), ghost_objects_from_proc[p]);
374  else
375  libmesh_assert(!requested_ids.count(p));
376  }
377 #endif
378 
379  typedef std::vector<dof_id_type> datum;
380 
381  auto gather_functor =
382  [this, &mesh, &objects]
384  const std::vector<dof_id_type> & ids,
385  std::vector<datum> & data)
386  {
387  // Fill those requests
388  const unsigned int
389  sys_num = this->sys_number(),
390  n_var_groups = this->n_variable_groups();
391 
392  const std::size_t query_size = ids.size();
393 
394  data.resize(query_size);
395  for (auto & d : data)
396  d.resize(2 * n_var_groups);
397 
398  for (std::size_t i=0; i != query_size; ++i)
399  {
400  DofObject * requested = (this->*objects)(mesh, ids[i]);
401  libmesh_assert(requested);
402  libmesh_assert_equal_to (requested->processor_id(), this->processor_id());
403  libmesh_assert_equal_to (requested->n_var_groups(sys_num), n_var_groups);
404  for (unsigned int vg=0; vg != n_var_groups; ++vg)
405  {
406  unsigned int n_comp_g =
407  requested->n_comp_group(sys_num, vg);
408  data[i][vg] = n_comp_g;
409  dof_id_type my_first_dof = n_comp_g ?
410  requested->vg_dof_base(sys_num, vg) : 0;
411  libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
412  data[i][n_var_groups+vg] = my_first_dof;
413  }
414  }
415  };
416 
417  auto action_functor =
418  [this, &mesh, &objects]
419  (processor_id_type libmesh_dbg_var(pid),
420  const std::vector<dof_id_type> & ids,
421  const std::vector<datum> & data)
422  {
423  const unsigned int
424  sys_num = this->sys_number(),
425  n_var_groups = this->n_variable_groups();
426 
427  // Copy the id changes we've now been informed of
428  for (auto i : index_range(ids))
429  {
430  DofObject * requested = (this->*objects)(mesh, ids[i]);
431  libmesh_assert(requested);
432  libmesh_assert_equal_to (requested->processor_id(), pid);
433  for (unsigned int vg=0; vg != n_var_groups; ++vg)
434  {
435  unsigned int n_comp_g =
436  cast_int<unsigned int>(data[i][vg]);
437  requested->set_n_comp_group(sys_num, vg, n_comp_g);
438  if (n_comp_g)
439  {
440  dof_id_type my_first_dof = data[i][n_var_groups+vg];
441  libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
442  requested->set_vg_dof_base
443  (sys_num, vg, my_first_dof);
444  }
445  }
446  }
447  };
448 
449  datum * ex = nullptr;
451  (this->comm(), requested_ids, gather_functor, action_functor, ex);
452 
453 #ifdef DEBUG
454  // Double check for invalid dofs
455  for (it = objects_begin; it != objects_end; ++it)
456  {
457  DofObject * obj = *it;
458  libmesh_assert (obj);
459  unsigned int num_variables = obj->n_vars(this->sys_number());
460  for (unsigned int v=0; v != num_variables; ++v)
461  {
462  unsigned int n_comp =
463  obj->n_comp(this->sys_number(), v);
464  dof_id_type my_first_dof = n_comp ?
465  obj->dof_number(this->sys_number(), v, 0) : 0;
466  libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
467  }
468  }
469 #endif
470 }
unsigned int n_variable_groups() const
Definition: dof_map.h:533
MeshBase & mesh
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
const Parallel::Communicator & comm() const
unsigned int sys_number() const
Definition: dof_map.h:1744
processor_id_type n_processors() const
void pull_parallel_vector_data(const Communicator &comm, const MapToVectors &queries, RequestContainer &reqs, GatherFunctor &gather_data, ActionFunctor &act_on_data, const datum *example)
static const processor_id_type invalid_processor_id
Definition: dof_object.h:358
static const dof_id_type invalid_id
Definition: dof_object.h:347
IterBase * data
processor_id_type processor_id() const
uint8_t dof_id_type
Definition: id_types.h:64

◆ stash_dof_constraints()

void libMesh::DofMap::stash_dof_constraints ( )
inline

Definition at line 911 of file dof_map.h.

References _dof_constraints, and _stashed_dof_constraints.

912  {
913  libmesh_assert(_stashed_dof_constraints.empty());
915  }
DofConstraints _dof_constraints
Definition: dof_map.h:1687
DofConstraints _stashed_dof_constraints
Definition: dof_map.h:1687

◆ sys_number()

unsigned int libMesh::DofMap::sys_number ( ) const
inline

◆ unstash_dof_constraints()

void libMesh::DofMap::unstash_dof_constraints ( )
inline

Definition at line 917 of file dof_map.h.

References _dof_constraints, and _stashed_dof_constraints.

918  {
919  libmesh_assert(_dof_constraints.empty());
921  }
DofConstraints _dof_constraints
Definition: dof_map.h:1687
DofConstraints _stashed_dof_constraints
Definition: dof_map.h:1687

◆ use_coupled_neighbor_dofs()

bool libMesh::DofMap::use_coupled_neighbor_dofs ( const MeshBase mesh) const

Tells other library functions whether or not this problem includes coupling between dofs in neighboring cells, as can currently be specified on the command line or inferred from the use of all discontinuous variables.

Definition at line 1682 of file dof_map.C.

References _implicit_neighbor_dofs, _implicit_neighbor_dofs_initialized, libMesh::FEAbstract::build(), libMesh::command_line_next(), libMesh::DISCONTINUOUS, mesh, n_variables(), libMesh::on_command_line(), and variable_type().

Referenced by build_sparsity(), clear(), and reinit().

1683 {
1684  // If we were asked on the command line, then we need to
1685  // include sensitivities between neighbor degrees of freedom
1686  bool implicit_neighbor_dofs =
1687  libMesh::on_command_line ("--implicit-neighbor-dofs");
1688 
1689  // If the user specifies --implicit-neighbor-dofs 0, then
1690  // presumably he knows what he is doing and we won't try to
1691  // automatically turn it on even when all the variables are
1692  // discontinuous.
1693  if (implicit_neighbor_dofs)
1694  {
1695  // No flag provided defaults to 'true'
1696  int flag = 1;
1697  flag = libMesh::command_line_next ("--implicit-neighbor-dofs", flag);
1698 
1699  if (!flag)
1700  {
1701  // The user said --implicit-neighbor-dofs 0, so he knows
1702  // what he is doing and really doesn't want it.
1703  return false;
1704  }
1705  }
1706 
1707  // Possibly override the commandline option, if set_implicit_neighbor_dofs
1708  // has been called.
1710  {
1711  implicit_neighbor_dofs = _implicit_neighbor_dofs;
1712 
1713  // Again, if the user explicitly says implicit_neighbor_dofs = false,
1714  // then we return here.
1715  if (!implicit_neighbor_dofs)
1716  return false;
1717  }
1718 
1719  // Look at all the variables in this system. If every one is
1720  // discontinuous then the user must be doing DG/FVM, so be nice
1721  // and force implicit_neighbor_dofs=true.
1722  {
1723  bool all_discontinuous_dofs = true;
1724 
1725  for (unsigned int var=0; var<this->n_variables(); var++)
1726  if (FEAbstract::build (mesh.mesh_dimension(),
1727  this->variable_type(var))->get_continuity() != DISCONTINUOUS)
1728  all_discontinuous_dofs = false;
1729 
1730  if (all_discontinuous_dofs)
1731  implicit_neighbor_dofs = true;
1732  }
1733 
1734  return implicit_neighbor_dofs;
1735 }
bool _implicit_neighbor_dofs_initialized
Definition: dof_map.h:1736
bool _implicit_neighbor_dofs
Definition: dof_map.h:1737
const FEType & variable_type(const unsigned int c) const
Definition: dof_map.h:1792
MeshBase & mesh
unsigned int n_variables() const
Definition: dof_map.h:541
T command_line_next(std::string name, T value)
Definition: libmesh.C:941
static std::unique_ptr< FEAbstract > build(const unsigned int dim, const FEType &type)
Definition: fe_abstract.C:71
bool on_command_line(std::string arg)
Definition: libmesh.C:876

◆ variable()

const Variable & libMesh::DofMap::variable ( const unsigned int  c) const
inline
Returns
The variable description object for variable c.

Definition at line 1762 of file dof_map.h.

References _variables.

Referenced by distribute_dofs(), DMlibMeshSetSystem_libMesh(), local_variable_indices(), libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::operator()(), libMesh::BoundaryProjectSolution::operator()(), and SCALAR_dof_indices().

1763 {
1764  libmesh_assert_less (c, _variables.size());
1765 
1766  return _variables[c];
1767 }
std::vector< Variable > _variables
Definition: dof_map.h:1498

◆ variable_group()

const VariableGroup & libMesh::DofMap::variable_group ( const unsigned int  c) const
inline
Returns
The VariableGroup description object for group g.

Definition at line 1752 of file dof_map.h.

References _variable_groups.

Referenced by _dof_indices(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), dof_indices(), libMesh::System::get_info(), old_dof_indices(), and reinit().

1753 {
1754  libmesh_assert_less (g, _variable_groups.size());
1755 
1756  return _variable_groups[g];
1757 }
std::vector< VariableGroup > _variable_groups
Definition: dof_map.h:1503

◆ variable_group_order()

Order libMesh::DofMap::variable_group_order ( const unsigned int  vg) const
inline
Returns
The approximation order for VariableGroup vg.

Definition at line 1782 of file dof_map.h.

References _variable_groups.

1783 {
1784  libmesh_assert_less (vg, _variable_groups.size());
1785 
1786  return _variable_groups[vg].type().order;
1787 }
std::vector< VariableGroup > _variable_groups
Definition: dof_map.h:1503

◆ variable_group_type()

const FEType & libMesh::DofMap::variable_group_type ( const unsigned int  vg) const
inline
Returns
The finite element type for VariableGroup vg.

Definition at line 1802 of file dof_map.h.

References _variable_groups.

1803 {
1804  libmesh_assert_less (vg, _variable_groups.size());
1805 
1806  return _variable_groups[vg].type();
1807 }
std::vector< VariableGroup > _variable_groups
Definition: dof_map.h:1503

◆ variable_order()

Order libMesh::DofMap::variable_order ( const unsigned int  c) const
inline
Returns
The approximation order for variable c.

Definition at line 1772 of file dof_map.h.

References _variables.

1773 {
1774  libmesh_assert_less (c, _variables.size());
1775 
1776  return _variables[c].type().order;
1777 }
std::vector< Variable > _variables
Definition: dof_map.h:1498

◆ variable_type()

Friends And Related Function Documentation

◆ SparsityPattern::Build

friend class SparsityPattern::Build
friend

Definition at line 1730 of file dof_map.h.

Member Data Documentation

◆ _adjoint_constraint_values

AdjointDofConstraintValues libMesh::DofMap::_adjoint_constraint_values
private

◆ _adjoint_dirichlet_boundaries

std::vector<DirichletBoundaries *> libMesh::DofMap::_adjoint_dirichlet_boundaries
private

Data structure containing Dirichlet functions. The ith entry is the constraint matrix row for boundaryid i.

Definition at line 1727 of file dof_map.h.

Referenced by ~DofMap().

◆ _algebraic_ghosting_functors

std::set<GhostingFunctor *> libMesh::DofMap::_algebraic_ghosting_functors
private

The list of all GhostingFunctor objects to be used when distributing ghosted vectors.

The library should automatically copy these functors to the MeshBase, too, so any algebraically ghosted dofs will live on geometrically ghosted elements.

Definition at line 1605 of file dof_map.h.

Referenced by add_algebraic_ghosting_functor(), algebraic_ghosting_functors_begin(), algebraic_ghosting_functors_end(), clear(), distribute_dofs(), and remove_algebraic_ghosting_functor().

◆ _augment_send_list

AugmentSendList* libMesh::DofMap::_augment_send_list
private

Function object to call to add extra entries to the send list

Definition at line 1569 of file dof_map.h.

Referenced by attach_extra_send_list_object(), and prepare_send_list().

◆ _augment_sparsity_pattern

AugmentSparsityPattern* libMesh::DofMap::_augment_sparsity_pattern
private

Function object to call to add extra entries to the sparsity pattern

Definition at line 1552 of file dof_map.h.

Referenced by attach_extra_sparsity_object(), and build_sparsity().

◆ _communicator

◆ _counts

ReferenceCounter::Counts libMesh::ReferenceCounter::_counts
staticprotectedinherited

◆ _coupling_functors

std::set<GhostingFunctor *> libMesh::DofMap::_coupling_functors
private

The list of all GhostingFunctor objects to be used when coupling degrees of freedom in matrix sparsity patterns.

These objects will also be used as algebraic ghosting functors, but not vice-versa.

The library should automatically copy these functors to the MeshBase, too, so any dofs coupled to local dofs will live on geometrically ghosted elements.

Definition at line 1618 of file dof_map.h.

Referenced by add_coupling_functor(), build_sparsity(), clear(), coupling_functors_begin(), coupling_functors_end(), distribute_dofs(), and remove_coupling_functor().

◆ _default_coupling

std::unique_ptr<DefaultCoupling> libMesh::DofMap::_default_coupling
private

The default coupling GhostingFunctor, used to implement standard libMesh sparsity pattern construction.

We use a std::unique_ptr here to reduce header dependencies.

Definition at line 1587 of file dof_map.h.

Referenced by clear(), default_coupling(), DofMap(), reinit(), and ~DofMap().

◆ _default_evaluating

std::unique_ptr<DefaultCoupling> libMesh::DofMap::_default_evaluating
private

The default algebraic GhostingFunctor, used to implement standard libMesh send_list construction.

We use a std::unique_ptr here to reduce header dependencies.

Definition at line 1595 of file dof_map.h.

Referenced by clear(), default_algebraic_ghosting(), DofMap(), and ~DofMap().

◆ _dirichlet_boundaries

std::unique_ptr<DirichletBoundaries> libMesh::DofMap::_dirichlet_boundaries
private

Data structure containing Dirichlet functions. The ith entry is the constraint matrix row for boundaryid i.

Definition at line 1721 of file dof_map.h.

Referenced by get_dirichlet_boundaries().

◆ _dof_constraints

DofConstraints libMesh::DofMap::_dof_constraints
private

Data structure containing DOF constraints. The ith entry is the constraint matrix row for DOF i.

Definition at line 1687 of file dof_map.h.

Referenced by clear(), constraint_rows_begin(), constraint_rows_end(), find_connected_dofs(), get_info(), is_constrained_dof(), stash_dof_constraints(), and unstash_dof_constraints().

◆ _dof_coupling

CouplingMatrix* libMesh::DofMap::_dof_coupling

Degree of freedom coupling. If left empty each DOF couples to all others. Can be used to reduce memory requirements for sparse matrices. DOF 0 might only couple to itself, in which case dof_coupling(0,0) should be 1 and dof_coupling(0,j) = 0 for j not equal to 0.

This variable is named as though it were class private, but it is in the public interface. Also there are no public methods for accessing it... This typically means you should only use it if you know what you are doing.

Definition at line 1319 of file dof_map.h.

Referenced by build_sparsity(), clear(), and reinit().

◆ _enable_print_counter

bool libMesh::ReferenceCounter::_enable_print_counter = true
staticprotectedinherited

Flag to control whether reference count information is printed when print_info is called.

Definition at line 141 of file reference_counter.h.

Referenced by libMesh::ReferenceCounter::disable_print_counter_info(), libMesh::ReferenceCounter::enable_print_counter_info(), and libMesh::ReferenceCounter::print_info().

◆ _end_df

std::vector<dof_id_type> libMesh::DofMap::_end_df
private

Last DOF index (plus 1) on processor p.

Definition at line 1535 of file dof_map.h.

Referenced by clear(), distribute_dofs(), dof_owner(), end_dof(), last_dof(), and n_dofs_on_processor().

◆ _end_old_df

std::vector<dof_id_type> libMesh::DofMap::_end_old_df
private

Last old DOF index (plus 1) on processor p.

Definition at line 1672 of file dof_map.h.

Referenced by clear(), distribute_dofs(), and end_old_dof().

◆ _error_on_cyclic_constraint

bool libMesh::DofMap::_error_on_cyclic_constraint
private

This flag indicates whether or not we do an opt-mode check for the presence of cyclic constraints.

Definition at line 1493 of file dof_map.h.

Referenced by set_error_on_cyclic_constraint().

◆ _extra_send_list_context

void* libMesh::DofMap::_extra_send_list_context
private

A pointer associated with the extra send list that can optionally be passed in

Definition at line 1579 of file dof_map.h.

Referenced by attach_extra_send_list_function(), and prepare_send_list().

◆ _extra_send_list_function

void(* libMesh::DofMap::_extra_send_list_function) (std::vector< dof_id_type > &, void *)
private

A function pointer to a function to call to add extra entries to the send list

Definition at line 1574 of file dof_map.h.

Referenced by attach_extra_send_list_function(), and prepare_send_list().

◆ _extra_sparsity_context

void* libMesh::DofMap::_extra_sparsity_context
private

A pointer associated with the extra sparsity that can optionally be passed in

Definition at line 1564 of file dof_map.h.

Referenced by attach_extra_sparsity_function(), and build_sparsity().

◆ _extra_sparsity_function

void(* libMesh::DofMap::_extra_sparsity_function) (SparsityPattern::Graph &, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *)
private

A function pointer to a function to call to add extra entries to the sparsity pattern

Definition at line 1557 of file dof_map.h.

Referenced by attach_extra_sparsity_function(), and build_sparsity().

◆ _first_df

std::vector<dof_id_type> libMesh::DofMap::_first_df
private

First DOF index on processor p.

Definition at line 1530 of file dof_map.h.

Referenced by clear(), distribute_dofs(), first_dof(), and n_dofs_on_processor().

◆ _first_old_df

std::vector<dof_id_type> libMesh::DofMap::_first_old_df
private

First old DOF index on processor p.

Definition at line 1667 of file dof_map.h.

Referenced by clear(), distribute_dofs(), and first_old_dof().

◆ _first_old_scalar_df

std::vector<dof_id_type> libMesh::DofMap::_first_old_scalar_df
private

First old DOF index for SCALAR variable v, or garbage for non-SCALAR variable v

Definition at line 1678 of file dof_map.h.

Referenced by clear(), distribute_dofs(), and SCALAR_dof_indices().

◆ _first_scalar_df

std::vector<dof_id_type> libMesh::DofMap::_first_scalar_df
private

First DOF index for SCALAR variable v, or garbage for non-SCALAR variable v

Definition at line 1541 of file dof_map.h.

Referenced by clear(), distribute_dofs(), and SCALAR_dof_indices().

◆ _implicit_neighbor_dofs

bool libMesh::DofMap::_implicit_neighbor_dofs
private

Definition at line 1737 of file dof_map.h.

Referenced by set_implicit_neighbor_dofs(), and use_coupled_neighbor_dofs().

◆ _implicit_neighbor_dofs_initialized

bool libMesh::DofMap::_implicit_neighbor_dofs_initialized
private

Bools to indicate if we override the –implicit_neighbor_dofs commandline options.

Definition at line 1736 of file dof_map.h.

Referenced by set_implicit_neighbor_dofs(), and use_coupled_neighbor_dofs().

◆ _matrices

std::vector<SparseMatrix<Number> * > libMesh::DofMap::_matrices
private

Additional matrices handled by this object. These pointers do not handle the memory, instead, System, who told DofMap about them, owns them.

Definition at line 1525 of file dof_map.h.

Referenced by attach_matrix(), clear(), compute_sparsity(), DofMap(), get_info(), and is_attached().

◆ _mesh

MeshBase& libMesh::DofMap::_mesh
private

◆ _mutex

Threads::spin_mutex libMesh::ReferenceCounter::_mutex
staticprotectedinherited

Mutual exclusion object to enable thread-safe reference counting.

Definition at line 135 of file reference_counter.h.

◆ _n_dfs

dof_id_type libMesh::DofMap::_n_dfs
private

Total number of degrees of freedom.

Definition at line 1649 of file dof_map.h.

Referenced by clear(), distribute_dofs(), and n_dofs().

◆ _n_nz

std::vector<dof_id_type>* libMesh::DofMap::_n_nz
private

The number of on-processor nonzeros in my portion of the global matrix. If need_full_sparsity_pattern is true, this will just be a pointer into the corresponding sparsity pattern vector. Otherwise we have to new/delete it ourselves.

Definition at line 1638 of file dof_map.h.

Referenced by attach_matrix(), clear_sparsity(), compute_sparsity(), get_info(), and get_n_nz().

◆ _n_objects

Threads::atomic< unsigned int > libMesh::ReferenceCounter::_n_objects
staticprotectedinherited

The number of objects. Print the reference count information when the number returns to 0.

Definition at line 130 of file reference_counter.h.

Referenced by libMesh::ReferenceCounter::n_objects(), libMesh::ReferenceCounter::ReferenceCounter(), and libMesh::ReferenceCounter::~ReferenceCounter().

◆ _n_old_dfs

dof_id_type libMesh::DofMap::_n_old_dfs
private

Total number of degrees of freedom on old dof objects

Definition at line 1662 of file dof_map.h.

Referenced by clear(), distribute_dofs(), and n_old_dofs().

◆ _n_oz

std::vector<dof_id_type>* libMesh::DofMap::_n_oz
private

The number of off-processor nonzeros in my portion of the global matrix; allocated similar to _n_nz.

Definition at line 1644 of file dof_map.h.

Referenced by attach_matrix(), clear_sparsity(), compute_sparsity(), get_info(), and get_n_oz().

◆ _n_SCALAR_dofs

dof_id_type libMesh::DofMap::_n_SCALAR_dofs
private

The total number of SCALAR dofs associated to all SCALAR variables.

Definition at line 1655 of file dof_map.h.

Referenced by distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), n_SCALAR_dofs(), and reinit().

◆ _node_constraints

NodeConstraints libMesh::DofMap::_node_constraints
private

Data structure containing DofObject constraints.

Definition at line 1698 of file dof_map.h.

Referenced by get_info(), is_constrained_node(), n_constrained_nodes(), node_constraint_rows_begin(), and node_constraint_rows_end().

◆ _periodic_boundaries

std::unique_ptr<PeriodicBoundaries> libMesh::DofMap::_periodic_boundaries
private

Data structure containing periodic boundaries. The ith entry is the constraint matrix row for boundaryid i.

Definition at line 1707 of file dof_map.h.

Referenced by DofMap(), get_periodic_boundaries(), and is_periodic_boundary().

◆ _primal_constraint_values

DofConstraintValueMap libMesh::DofMap::_primal_constraint_values
private

Definition at line 1689 of file dof_map.h.

Referenced by clear(), get_info(), and get_primal_constraint_values().

◆ _send_list

std::vector<dof_id_type> libMesh::DofMap::_send_list
private

A list containing all the global DOF indices that affect the solution on my processor.

Definition at line 1547 of file dof_map.h.

Referenced by add_neighbors_to_send_list(), clear(), distribute_dofs(), get_send_list(), prepare_send_list(), and semilocal_index().

◆ _sp

std::unique_ptr<SparsityPattern::Build> libMesh::DofMap::_sp
private

The sparsity pattern of the global matrix, kept around if it might be needed by future additions of the same type of matrix.

Definition at line 1630 of file dof_map.h.

Referenced by attach_matrix(), clear_sparsity(), and compute_sparsity().

◆ _stashed_dof_constraints

DofConstraints libMesh::DofMap::_stashed_dof_constraints
private

Definition at line 1687 of file dof_map.h.

Referenced by clear(), stash_dof_constraints(), and unstash_dof_constraints().

◆ _sys_number

const unsigned int libMesh::DofMap::_sys_number
private

The number of the system we manage DOFs for.

Definition at line 1513 of file dof_map.h.

Referenced by sys_number().

◆ _variable_group_numbers

std::vector<unsigned int> libMesh::DofMap::_variable_group_numbers
private

The variable group number for each variable.

Definition at line 1508 of file dof_map.h.

Referenced by add_variable_group(), clear(), and dof_indices().

◆ _variable_groups

std::vector<VariableGroup> libMesh::DofMap::_variable_groups
private

The finite element type for each variable group.

Definition at line 1503 of file dof_map.h.

Referenced by add_variable_group(), clear(), n_variable_groups(), variable_group(), variable_group_order(), and variable_group_type().

◆ _variables

std::vector<Variable> libMesh::DofMap::_variables
private

The finite element type for each variable.

Definition at line 1498 of file dof_map.h.

Referenced by add_variable_group(), clear(), n_variables(), variable(), variable_order(), and variable_type().

◆ need_full_sparsity_pattern

bool libMesh::DofMap::need_full_sparsity_pattern
private

Default false; set to true if any attached matrix requires a full sparsity pattern.

Definition at line 1624 of file dof_map.h.

Referenced by attach_matrix(), build_sparsity(), clear(), clear_sparsity(), and compute_sparsity().


The documentation for this class was generated from the following files: