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 add_coupling_functor (GhostingFunctor &coupling_functor)
 
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 &ghosting_functor)
 
void remove_algebraic_ghosting_functor (GhostingFunctor &ghosting_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=libmesh_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=libmesh_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
 
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=libmesh_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=libmesh_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 v, const Node *const *nodes, unsigned int n_nodes#ifdef DEBUG, 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
 
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 168 of file dof_map.h.

Member Typedef Documentation

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 119 of file reference_counter.h.

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 1308 of file dof_map.h.

Constructor & Destructor Documentation

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 127 of file dof_map.C.

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

128  :
129  ParallelObject (mesh.comm()),
132  _variables(),
134  _sys_number(number),
135  _mesh(mesh),
136  _matrices(),
137  _first_df(),
138  _end_df(),
140  _send_list(),
147  _default_coupling(new DefaultCoupling()),
148  _default_evaluating(new DefaultCoupling()),
152  _n_dfs(0),
153  _n_SCALAR_dofs(0)
154 #ifdef LIBMESH_ENABLE_AMR
155  , _n_old_dfs(0),
156  _first_old_df(),
157  _end_old_df(),
159 #endif
160 #ifdef LIBMESH_ENABLE_CONSTRAINTS
161  , _dof_constraints()
165 #endif
166 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
168 #endif
169 #ifdef LIBMESH_ENABLE_PERIODIC
170  , _periodic_boundaries(new PeriodicBoundaries)
171 #endif
172 #ifdef LIBMESH_ENABLE_DIRICHLET
173  , _dirichlet_boundaries(new DirichletBoundaries)
175 #endif
178 {
179  _matrices.clear();
180 
181  _default_coupling->set_mesh(&_mesh);
182  _default_evaluating->set_mesh(&_mesh);
183  _default_evaluating->set_n_levels(1);
184 
185 #ifdef LIBMESH_ENABLE_PERIODIC
186  _default_coupling->set_periodic_boundaries(_periodic_boundaries.get());
187  _default_evaluating->set_periodic_boundaries(_periodic_boundaries.get());
188 #endif
189 
192 }
std::vector< VariableGroup > _variable_groups
Definition: dof_map.h:1435
ParallelObject(const Parallel::Communicator &comm_in)
bool _error_on_cyclic_constraint
Definition: dof_map.h:1425
bool _implicit_neighbor_dofs_initialized
Definition: dof_map.h:1663
const unsigned int _sys_number
Definition: dof_map.h:1440
bool _implicit_neighbor_dofs
Definition: dof_map.h:1664
void * _extra_sparsity_context
Definition: dof_map.h:1491
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1474
MeshBase & mesh
AugmentSparsityPattern * _augment_sparsity_pattern
Definition: dof_map.h:1479
const class libmesh_nullptr_t libmesh_nullptr
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Definition: dof_map.h:1648
std::vector< dof_id_type > _end_old_df
Definition: dof_map.h:1599
void add_coupling_functor(GhostingFunctor &coupling_functor)
Definition: dof_map.C:1801
std::vector< dof_id_type > _first_old_df
Definition: dof_map.h:1594
std::vector< dof_id_type > _first_scalar_df
Definition: dof_map.h:1468
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1618
std::vector< dof_id_type > * _n_nz
Definition: dof_map.h:1565
AugmentSendList * _augment_send_list
Definition: dof_map.h:1496
std::vector< dof_id_type > * _n_oz
Definition: dof_map.h:1571
bool need_full_sparsity_pattern
Definition: dof_map.h:1551
void add_algebraic_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: dof_map.C:1820
std::vector< dof_id_type > _first_old_scalar_df
Definition: dof_map.h:1605
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:1484
dof_id_type _n_SCALAR_dofs
Definition: dof_map.h:1582
DofConstraints _dof_constraints
Definition: dof_map.h:1614
CouplingMatrix * _dof_coupling
Definition: dof_map.h:1256
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1654
void * _extra_send_list_context
Definition: dof_map.h:1506
std::vector< SparseMatrix< Number > * > _matrices
Definition: dof_map.h:1452
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Definition: dof_map.h:1634
std::unique_ptr< DefaultCoupling > _default_coupling
Definition: dof_map.h:1514
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1616
std::vector< Variable > _variables
Definition: dof_map.h:1430
DofConstraints _stashed_dof_constraints
Definition: dof_map.h:1614
dof_id_type _n_old_dfs
Definition: dof_map.h:1589
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1462
std::vector< dof_id_type > _first_df
Definition: dof_map.h:1457
void(* _extra_send_list_function)(std::vector< dof_id_type > &, void *)
Definition: dof_map.h:1501
MeshBase & _mesh
Definition: dof_map.h:1445
std::unique_ptr< DefaultCoupling > _default_evaluating
Definition: dof_map.h:1522
dof_id_type _n_dfs
Definition: dof_map.h:1576
NodeConstraints _node_constraints
Definition: dof_map.h:1625
libMesh::DofMap::~DofMap ( )

Destructor.

Definition at line 197 of file dof_map.C.

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

198 {
199  this->clear();
200 
201  // clear() resets all but the default DofMap-based functors. We
202  // need to remove those from the mesh too before we die.
205 
206 #ifdef LIBMESH_ENABLE_DIRICHLET
207  for (std::size_t q = 0; q != _adjoint_dirichlet_boundaries.size(); ++q)
209 #endif
210 }
void remove_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: mesh_base.C:307
void clear()
Definition: dof_map.C:810
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1654
std::unique_ptr< DefaultCoupling > _default_coupling
Definition: dof_map.h:1514
MeshBase & _mesh
Definition: dof_map.h:1445
std::unique_ptr< DefaultCoupling > _default_evaluating
Definition: dof_map.h:1522

Member Function Documentation

void libMesh::DofMap::_dof_indices ( const Elem elem,
int  p_level,
std::vector< dof_id_type > &  di,
const unsigned int  v,
const Node *const *  nodes,
unsigned int n_nodes#ifdef  DEBUG,
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.

In DEBUG mode, the tot_size parameter will add up the total number of dof indices that should have been added to di.

Definition at line 2171 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(), 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(), and variable().

Referenced by dof_indices().

2182 {
2183  const Variable & var = this->variable(v);
2184 
2185  if (var.active_on_subdomain(elem.subdomain_id()))
2186  {
2187  const ElemType type = elem.type();
2188  const unsigned int sys_num = this->sys_number();
2189  const unsigned int dim = elem.dim();
2190 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2191  const bool is_inf = elem.infinite();
2192 #endif
2193 
2194  // Increase the polynomial order on p refined elements
2195  FEType fe_type = var.type();
2196  fe_type.order = static_cast<Order>(fe_type.order + p_level);
2197 
2198  const bool extra_hanging_dofs =
2200 
2201 #ifdef DEBUG
2202  // The number of dofs per element is non-static for subdivision FE
2203  if (fe_type.family == SUBDIVISION)
2204  tot_size += n_nodes;
2205  else
2206  tot_size += FEInterface::n_dofs(dim,fe_type,type);
2207 #endif
2208 
2209  const FEInterface::n_dofs_at_node_ptr ndan =
2211 
2212  // Get the node-based DOF numbers
2213  for (unsigned int n=0; n<n_nodes; n++)
2214  {
2215  const Node * node = nodes[n];
2216 
2217  // There is a potential problem with h refinement. Imagine a
2218  // quad9 that has a linear FE on it. Then, on the hanging side,
2219  // it can falsely identify a DOF at the mid-edge node. This is why
2220  // we go through FEInterface instead of node->n_comp() directly.
2221  const unsigned int nc =
2222 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2223  is_inf ?
2224  FEInterface::n_dofs_at_node(dim, fe_type, type, n) :
2225 #endif
2226  ndan (type, fe_type.order, n);
2227 
2228  // If this is a non-vertex on a hanging node with extra
2229  // degrees of freedom, we use the non-vertex dofs (which
2230  // come in reverse order starting from the end, to
2231  // simplify p refinement)
2232  if (extra_hanging_dofs && !elem.is_vertex(n))
2233  {
2234  const int dof_offset = node->n_comp(sys_num,v) - nc;
2235 
2236  // We should never have fewer dofs than necessary on a
2237  // node unless we're getting indices on a parent element,
2238  // and we should never need the indices on such a node
2239  if (dof_offset < 0)
2240  {
2241  libmesh_assert(!elem.active());
2242  di.resize(di.size() + nc, DofObject::invalid_id);
2243  }
2244  else
2245  for (int i=node->n_comp(sys_num,v)-1; i>=dof_offset; i--)
2246  {
2247  libmesh_assert_not_equal_to (node->dof_number(sys_num,v,i),
2249  di.push_back(node->dof_number(sys_num,v,i));
2250  }
2251  }
2252  // If this is a vertex or an element without extra hanging
2253  // dofs, our dofs come in forward order coming from the
2254  // beginning
2255  else
2256  for (unsigned int i=0; i<nc; i++)
2257  {
2258  libmesh_assert_not_equal_to (node->dof_number(sys_num,v,i),
2260  di.push_back(node->dof_number(sys_num,v,i));
2261  }
2262  }
2263 
2264  // If there are any element-based DOF numbers, get them
2265  const unsigned int nc = FEInterface::n_dofs_per_elem(dim,
2266  fe_type,
2267  type);
2268  // We should never have fewer dofs than necessary on an
2269  // element unless we're getting indices on a parent element,
2270  // and we should never need those indices
2271  if (nc != 0)
2272  {
2273  if (elem.n_systems() > sys_num &&
2274  nc <= elem.n_comp(sys_num,v))
2275  {
2276  for (unsigned int i=0; i<nc; i++)
2277  {
2278  libmesh_assert_not_equal_to (elem.dof_number(sys_num,v,i),
2280 
2281  di.push_back(elem.dof_number(sys_num,v,i));
2282  }
2283  }
2284  else
2285  {
2286  libmesh_assert(!elem.active() || fe_type.family == LAGRANGE || fe_type.family == SUBDIVISION);
2287  di.resize(di.size() + nc, DofObject::invalid_id);
2288  }
2289  }
2290  }
2291 }
static unsigned int n_dofs_per_elem(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:461
static unsigned int n_dofs(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:411
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:1689
const dof_id_type n_nodes
Definition: tecplot_io.C:67
static bool extra_hanging_dofs(const FEType &fe_t)
static const dof_id_type invalid_id
Definition: dof_object.h:324
unsigned int sys_number() const
Definition: dof_map.h:1671
static n_dofs_at_node_ptr n_dofs_at_node_function(const unsigned int dim, const FEType &fe_t)
Definition: fe_interface.C:450
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:430
unsigned int(* n_dofs_at_node_ptr)(const ElemType, const Order, const unsigned int)
Definition: fe_interface.h:113
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 1365 of file dof_map_constraints.C.

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

4187 {
4188  unsigned int old_size = cast_int<unsigned int>
4190  for (unsigned int i = old_size; i <= qoi_index; ++i)
4192 
4193  _adjoint_dirichlet_boundaries[qoi_index]->push_back
4194  (new DirichletBoundary(dirichlet_boundary));
4195 }
Class for specifying Dirichlet boundary conditions as constraints.
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1654
void libMesh::DofMap::add_algebraic_ghosting_functor ( GhostingFunctor ghosting_functor)

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.

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.

Definition at line 1820 of file dof_map.C.

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

Referenced by clear(), and DofMap().

1821 {
1822  _algebraic_ghosting_functors.insert(&algebraic_ghosting_functor);
1823  _mesh.add_ghosting_functor(algebraic_ghosting_functor);
1824 }
std::set< GhostingFunctor * > _algebraic_ghosting_functors
Definition: dof_map.h:1532
MeshBase & _mesh
Definition: dof_map.h:1445
void add_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: mesh_base.h:787
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 1342 of file dof_map_constraints.C.

1346 {
1347  // Optionally allow the user to overwrite constraints. Defaults to false.
1348  if (forbid_constraint_overwrite)
1349  if (this->is_constrained_dof(dof_number))
1350  libmesh_error_msg("ERROR: DOF " << dof_number << " was already constrained!");
1351 
1352  // We don't get insert_or_assign until C++17 so we make do.
1353  std::pair<DofConstraints::iterator, bool> it =
1354  _dof_constraints.insert(std::make_pair(dof_number, constraint_row));
1355  if (!it.second)
1356  it.first->second = constraint_row;
1357 
1358  std::pair<DofConstraintValueMap::iterator, bool> rhs_it =
1359  _primal_constraint_values.insert(std::make_pair(dof_number, constraint_rhs));
1360  if (!rhs_it.second)
1361  rhs_it.first->second = constraint_rhs;
1362 }
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1756
DofConstraints _dof_constraints
Definition: dof_map.h:1614
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1616
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 832 of file dof_map.h.

835  { 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)
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 4064 of file dof_map_constraints.C.

References libMesh::n_processors().

4065 {
4066  // This function must be run on all processors at once
4067  parallel_object_only();
4068 
4069  // Return immediately if there's nothing to gather
4070  if (this->n_processors() == 1)
4071  return;
4072 
4073  // We might get to return immediately if none of the processors
4074  // found any constraints
4075  unsigned int has_constraints = !_dof_constraints.empty();
4076  this->comm().max(has_constraints);
4077  if (!has_constraints)
4078  return;
4079 
4080  for (DofConstraints::iterator i = _dof_constraints.begin();
4081  i != _dof_constraints.end(); ++i)
4082  {
4083  dof_id_type constrained_dof = i->first;
4084 
4085  // We only need the dependencies of our own constrained dofs
4086  if (constrained_dof < this->first_dof() ||
4087  constrained_dof >= this->end_dof())
4088  continue;
4089 
4090  DofConstraintRow & constraint_row = i->second;
4091  for (DofConstraintRow::const_iterator
4092  j=constraint_row.begin(); j != constraint_row.end();
4093  ++j)
4094  {
4095  dof_id_type constraint_dependency = j->first;
4096 
4097  // No point in adding one of our own dofs to the send_list
4098  if (constraint_dependency >= this->first_dof() &&
4099  constraint_dependency < this->end_dof())
4100  continue;
4101 
4102  _send_list.push_back(constraint_dependency);
4103  }
4104  }
4105 }
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1474
processor_id_type n_processors() const
DofConstraints _dof_constraints
Definition: dof_map.h:1614
dof_id_type end_dof() const
Definition: dof_map.h:589
const Parallel::Communicator & comm() 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:89
dof_id_type first_dof() const
Definition: dof_map.h:547
uint8_t dof_id_type
Definition: id_types.h:64
void libMesh::DofMap::add_coupling_functor ( GhostingFunctor coupling_functor)

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.

Definition at line 1801 of file dof_map.C.

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

Referenced by clear(), and DofMap().

1802 {
1803  _coupling_functors.insert(&coupling_functor);
1804  _mesh.add_ghosting_functor(coupling_functor);
1805 }
std::set< GhostingFunctor * > _coupling_functors
Definition: dof_map.h:1545
MeshBase & _mesh
Definition: dof_map.h:1445
void add_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: mesh_base.h:787
void libMesh::DofMap::add_dirichlet_boundary ( const DirichletBoundary dirichlet_boundary)

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

Definition at line 4179 of file dof_map_constraints.C.

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

4180 {
4181  _dirichlet_boundaries->push_back(new DirichletBoundary(dirichlet_boundary));
4182 }
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Definition: dof_map.h:1648
Class for specifying Dirichlet boundary conditions as constraints.
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 1486 of file dof_map.C.

References _send_list, libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), algebraic_ghosting_functors_begin(), algebraic_ghosting_functors_end(), libMesh::ConstCouplingRow::begin(), coupling_functors_begin(), coupling_functors_end(), dof_indices(), end, libMesh::ConstCouplingRow::end(), end_dof(), first_dof(), merge_ghost_functor_outputs(), n_variables(), libMesh::ParallelObject::processor_id(), and libMesh::DofObject::processor_id().

Referenced by distribute_dofs().

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

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

Definition at line 4313 of file dof_map_constraints.C.

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

4314 {
4315  // See if we already have a periodic boundary associated myboundary...
4316  PeriodicBoundaryBase * existing_boundary = _periodic_boundaries->boundary(periodic_boundary.myboundary);
4317 
4318  if (existing_boundary == libmesh_nullptr)
4319  {
4320  // ...if not, clone the input (and its inverse) and add them to the PeriodicBoundaries object
4321  PeriodicBoundaryBase * boundary = periodic_boundary.clone().release();
4322  PeriodicBoundaryBase * inverse_boundary = periodic_boundary.clone(PeriodicBoundaryBase::INVERSE).release();
4323 
4324  // _periodic_boundaries takes ownership of the pointers
4325  _periodic_boundaries->insert(std::make_pair(boundary->myboundary, boundary));
4326  _periodic_boundaries->insert(std::make_pair(inverse_boundary->myboundary, inverse_boundary));
4327  }
4328  else
4329  {
4330  // ...otherwise, merge this object's variable IDs with the existing boundary object's.
4331  existing_boundary->merge(periodic_boundary);
4332 
4333  // Do the same merging process for the inverse boundary. Note: the inverse better already exist!
4334  PeriodicBoundaryBase * inverse_boundary = _periodic_boundaries->boundary(periodic_boundary.pairedboundary);
4335  libmesh_assert(inverse_boundary);
4336  inverse_boundary->merge(periodic_boundary);
4337  }
4338 }
const class libmesh_nullptr_t libmesh_nullptr
void merge(const PeriodicBoundaryBase &pb)
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Definition: dof_map.h:1634
Base class for all PeriodicBoundary implementations.
virtual std::unique_ptr< PeriodicBoundaryBase > clone(TransformationType t=FORWARD) const =0
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 4343 of file dof_map_constraints.C.

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

4345 {
4346  libmesh_assert_equal_to (boundary.myboundary, inverse_boundary.pairedboundary);
4347  libmesh_assert_equal_to (boundary.pairedboundary, inverse_boundary.myboundary);
4348 
4349  // Allocate copies on the heap. The _periodic_boundaries object will manage this memory.
4350  // Note: this also means that the copy constructor for the PeriodicBoundary (or user class
4351  // derived therefrom) must be implemented!
4352  // PeriodicBoundary * p_boundary = new PeriodicBoundary(boundary);
4353  // PeriodicBoundary * p_inverse_boundary = new PeriodicBoundary(inverse_boundary);
4354 
4355  // We can't use normal copy construction since this leads to slicing with derived classes.
4356  // Use clone() "virtual constructor" instead. But, this *requires* user to override the clone()
4357  // method. Note also that clone() allocates memory. In this case, the _periodic_boundaries object
4358  // takes responsibility for cleanup.
4359  PeriodicBoundaryBase * p_boundary = boundary.clone().release();
4360  PeriodicBoundaryBase * p_inverse_boundary = inverse_boundary.clone().release();
4361 
4362  // Add the periodic boundary and its inverse to the PeriodicBoundaries data structure. The
4363  // PeriodicBoundaries data structure takes ownership of the pointers.
4364  _periodic_boundaries->insert(std::make_pair(p_boundary->myboundary, p_boundary));
4365  _periodic_boundaries->insert(std::make_pair(p_inverse_boundary->myboundary, p_inverse_boundary));
4366 }
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Definition: dof_map.h:1634
Base class for all PeriodicBoundary implementations.
virtual std::unique_ptr< PeriodicBoundaryBase > clone(TransformationType t=FORWARD) const =0
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 241 of file dof_map.C.

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

242 {
243  _variable_groups.push_back(var_group);
244 
245  VariableGroup & new_var_group = _variable_groups.back();
246 
247  for (unsigned int var=0; var<new_var_group.n_variables(); var++)
248  _variables.push_back (new_var_group(var));
249 }
std::vector< VariableGroup > _variable_groups
Definition: dof_map.h:1435
std::vector< Variable > _variables
Definition: dof_map.h:1430
std::set<GhostingFunctor *>::const_iterator libMesh::DofMap::algebraic_ghosting_functors_begin ( ) const
inline

Beginning of range of algebraic ghosting functors

Definition at line 312 of file dof_map.h.

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

313  { return _algebraic_ghosting_functors.begin(); }
std::set< GhostingFunctor * > _algebraic_ghosting_functors
Definition: dof_map.h:1532
std::set<GhostingFunctor *>::const_iterator libMesh::DofMap::algebraic_ghosting_functors_end ( ) const
inline

End of range of algebraic ghosting functors

Definition at line 318 of file dof_map.h.

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

319  { return _algebraic_ghosting_functors.end(); }
std::set< GhostingFunctor * > _algebraic_ghosting_functors
Definition: dof_map.h:1532
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 2348 of file dof_map.C.

References semilocal_index().

Referenced by is_evaluable().

2349 {
2350  // We're all semilocal unless we find a counterexample
2351  for (std::size_t i=0; i != dof_indices_in.size(); ++i)
2352  {
2353  const dof_id_type di = dof_indices_in[i];
2354  if (!this->semilocal_index(di))
2355  return false;
2356  }
2357 
2358  return true;
2359 }
bool semilocal_index(dof_id_type dof_index) const
Definition: dof_map.C:2331
uint8_t dof_id_type
Definition: id_types.h:64
void libMesh::DofMap::allgather_recursive_constraints ( MeshBase mesh)

Gathers constraint equation dependencies from other processors

Definition at line 2613 of file dof_map_constraints.C.

References libMesh::MeshBase::active_not_local_elements_begin(), libMesh::MeshBase::active_not_local_elements_end(), libMesh::DofObject::dof_number(), end, libMesh::DofObject::id(), libMesh::MeshBase::is_serial(), libMesh::libmesh_isnan(), libmesh_nullptr, mesh, libMesh::DofObject::n_comp(), n_nodes, libMesh::Elem::n_nodes(), libMesh::n_processors(), n_vars, libMesh::DofObject::n_vars(), libMesh::Elem::node_id(), libMesh::Elem::node_ptr(), libMesh::MeshBase::node_ptr(), libMesh::Elem::node_ref(), libMesh::processor_id(), libMesh::DofObject::processor_id(), and libMesh::TypeVector< T >::size().

2614 {
2615  // This function must be run on all processors at once
2616  parallel_object_only();
2617 
2618  // Return immediately if there's nothing to gather
2619  if (this->n_processors() == 1)
2620  return;
2621 
2622  // We might get to return immediately if none of the processors
2623  // found any constraints
2624  unsigned int has_constraints = !_dof_constraints.empty()
2625 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2626  || !_node_constraints.empty()
2627 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
2628  ;
2629  this->comm().max(has_constraints);
2630  if (!has_constraints)
2631  return;
2632 
2633  // If we have heterogenous adjoint constraints we need to
2634  // communicate those too.
2635  const unsigned int max_qoi_num =
2636  _adjoint_constraint_values.empty() ?
2637  0 : _adjoint_constraint_values.rbegin()->first;
2638 
2639  // We might have calculated constraints for constrained dofs
2640  // which have support on other processors.
2641  // Push these out first.
2642  {
2643  std::vector<std::set<dof_id_type>> pushed_ids(this->n_processors());
2644 
2645 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2646  std::vector<std::set<dof_id_type>> pushed_node_ids(this->n_processors());
2647 #endif
2648 
2649  const unsigned int sys_num = this->sys_number();
2650 
2652  foreign_elem_it = mesh.active_not_local_elements_begin(),
2653  foreign_elem_end = mesh.active_not_local_elements_end();
2654 
2655  // Collect the constraints to push to each processor
2656  for (; foreign_elem_it != foreign_elem_end; ++foreign_elem_it)
2657  {
2658  const Elem * elem = *foreign_elem_it;
2659 
2660  const unsigned short n_nodes = elem->n_nodes();
2661 
2662  // Just checking dof_indices on the foreign element isn't
2663  // enough. Consider a central hanging node between a coarse
2664  // Q2/Q1 element and its finer neighbors on a higher-ranked
2665  // processor. The coarse element's processor will own the node,
2666  // and will thereby own the pressure dof on that node, despite
2667  // the fact that that pressure dof doesn't directly exist on the
2668  // coarse element!
2669  //
2670  // So, we loop through dofs manually.
2671 
2672  {
2673  const unsigned int n_vars = elem->n_vars(sys_num);
2674  for (unsigned int v=0; v != n_vars; ++v)
2675  {
2676  const unsigned int n_comp = elem->n_comp(sys_num,v);
2677  for (unsigned int c=0; c != n_comp; ++c)
2678  {
2679  const unsigned int id =
2680  elem->dof_number(sys_num,v,c);
2681  if (this->is_constrained_dof(id))
2682  pushed_ids[elem->processor_id()].insert(id);
2683  }
2684  }
2685  }
2686 
2687  for (unsigned short n = 0; n != n_nodes; ++n)
2688  {
2689  const Node & node = elem->node_ref(n);
2690  const unsigned int n_vars = node.n_vars(sys_num);
2691  for (unsigned int v=0; v != n_vars; ++v)
2692  {
2693  const unsigned int n_comp = node.n_comp(sys_num,v);
2694  for (unsigned int c=0; c != n_comp; ++c)
2695  {
2696  const unsigned int id =
2697  node.dof_number(sys_num,v,c);
2698  if (this->is_constrained_dof(id))
2699  pushed_ids[elem->processor_id()].insert(id);
2700  }
2701  }
2702  }
2703 
2704 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2705  for (unsigned short n = 0; n != n_nodes; ++n)
2706  if (this->is_constrained_node(elem->node_ptr(n)))
2707  pushed_node_ids[elem->processor_id()].insert(elem->node_id(n));
2708 #endif
2709  }
2710 
2711  // Now trade constraint rows
2712  for (processor_id_type p = 0; p != this->n_processors(); ++p)
2713  {
2714  // Push to processor procup while receiving from procdown
2715  processor_id_type procup =
2716  cast_int<processor_id_type>((this->processor_id() + p) %
2717  this->n_processors());
2718  processor_id_type procdown =
2719  cast_int<processor_id_type>((this->n_processors() +
2720  this->processor_id() - p) %
2721  this->n_processors());
2722 
2723  // Pack the dof constraint rows and rhs's to push to procup
2724  const std::size_t pushed_ids_size = pushed_ids[procup].size();
2725  std::vector<std::vector<dof_id_type>> pushed_keys(pushed_ids_size);
2726  std::vector<std::vector<Real>> pushed_vals(pushed_ids_size);
2727  std::vector<Number> pushed_rhss(pushed_ids_size);
2728 
2729  std::vector<std::vector<Number>>
2730  pushed_adj_rhss(max_qoi_num,
2731  std::vector<Number>(pushed_ids_size));
2732  std::set<dof_id_type>::const_iterator it = pushed_ids[procup].begin();
2733  for (std::size_t i = 0; it != pushed_ids[procup].end();
2734  ++i, ++it)
2735  {
2736  const dof_id_type pushed_id = *it;
2737  DofConstraintRow & row = _dof_constraints[pushed_id];
2738  std::size_t row_size = row.size();
2739  pushed_keys[i].reserve(row_size);
2740  pushed_vals[i].reserve(row_size);
2741  for (DofConstraintRow::iterator j = row.begin();
2742  j != row.end(); ++j)
2743  {
2744  pushed_keys[i].push_back(j->first);
2745  pushed_vals[i].push_back(j->second);
2746  }
2747 
2748  DofConstraintValueMap::const_iterator rhsit =
2749  _primal_constraint_values.find(pushed_id);
2750  pushed_rhss[i] =
2751  (rhsit == _primal_constraint_values.end()) ?
2752  0 : rhsit->second;
2753 
2754  for (unsigned int q = 0; q != max_qoi_num; ++q)
2755  {
2756  AdjointDofConstraintValues::const_iterator adjoint_map_it =
2758 
2759  if (adjoint_map_it == _adjoint_constraint_values.end())
2760  continue;
2761 
2762  const DofConstraintValueMap & constraint_map =
2763  adjoint_map_it->second;
2764 
2765  DofConstraintValueMap::const_iterator rhsit =
2766  constraint_map.find(pushed_id);
2767 
2768  pushed_adj_rhss[q][i] =
2769  (rhsit == constraint_map.end()) ?
2770  0 : rhsit->second;
2771  }
2772  }
2773 
2774 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2775  // Pack the node constraint rows to push to procup
2776  const std::size_t pushed_nodes_size = pushed_node_ids[procup].size();
2777  std::vector<std::vector<dof_id_type>> pushed_node_keys(pushed_nodes_size);
2778  std::vector<std::vector<Real>> pushed_node_vals(pushed_nodes_size);
2779  std::vector<Point> pushed_node_offsets(pushed_nodes_size);
2780  std::set<dof_id_type>::const_iterator node_it = pushed_node_ids[procup].begin();
2781  for (std::size_t i = 0; node_it != pushed_node_ids[procup].end();
2782  ++i, ++node_it)
2783  {
2784  const Node * node = mesh.node_ptr(*node_it);
2785  NodeConstraintRow & row = _node_constraints[node].first;
2786  std::size_t row_size = row.size();
2787  pushed_node_keys[i].reserve(row_size);
2788  pushed_node_vals[i].reserve(row_size);
2789  for (NodeConstraintRow::iterator j = row.begin();
2790  j != row.end(); ++j)
2791  {
2792  pushed_node_keys[i].push_back(j->first->id());
2793  pushed_node_vals[i].push_back(j->second);
2794  }
2795  pushed_node_offsets[i] = _node_constraints[node].second;
2796  }
2797 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
2798 
2799  // Trade pushed dof constraint rows
2800  std::vector<dof_id_type> pushed_ids_from_me
2801  (pushed_ids[procup].begin(), pushed_ids[procup].end());
2802  std::vector<dof_id_type> pushed_ids_to_me;
2803  std::vector<std::vector<dof_id_type>> pushed_keys_to_me;
2804  std::vector<std::vector<Real>> pushed_vals_to_me;
2805  std::vector<Number> pushed_rhss_to_me;
2806  std::vector<std::vector<Number>> pushed_adj_rhss_to_me;
2807  this->comm().send_receive(procup, pushed_ids_from_me,
2808  procdown, pushed_ids_to_me);
2809  this->comm().send_receive(procup, pushed_keys,
2810  procdown, pushed_keys_to_me);
2811  this->comm().send_receive(procup, pushed_vals,
2812  procdown, pushed_vals_to_me);
2813  this->comm().send_receive(procup, pushed_rhss,
2814  procdown, pushed_rhss_to_me);
2815  this->comm().send_receive(procup, pushed_adj_rhss,
2816  procdown, pushed_adj_rhss_to_me);
2817  libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_keys_to_me.size());
2818  libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_vals_to_me.size());
2819  libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_rhss_to_me.size());
2820 
2821 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2822  // Trade pushed node constraint rows
2823  std::vector<dof_id_type> pushed_node_ids_from_me
2824  (pushed_node_ids[procup].begin(), pushed_node_ids[procup].end());
2825  std::vector<dof_id_type> pushed_node_ids_to_me;
2826  std::vector<std::vector<dof_id_type>> pushed_node_keys_to_me;
2827  std::vector<std::vector<Real>> pushed_node_vals_to_me;
2828  std::vector<Point> pushed_node_offsets_to_me;
2829  this->comm().send_receive(procup, pushed_node_ids_from_me,
2830  procdown, pushed_node_ids_to_me);
2831  this->comm().send_receive(procup, pushed_node_keys,
2832  procdown, pushed_node_keys_to_me);
2833  this->comm().send_receive(procup, pushed_node_vals,
2834  procdown, pushed_node_vals_to_me);
2835  this->comm().send_receive(procup, pushed_node_offsets,
2836  procdown, pushed_node_offsets_to_me);
2837 
2838  // Note that we aren't doing a send_receive on the Nodes
2839  // themselves. At this point we should only be pushing out
2840  // "raw" constraints, and there should be no
2841  // constrained-by-constrained-by-etc. situations that could
2842  // involve non-semilocal nodes.
2843 
2844  libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_keys_to_me.size());
2845  libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_vals_to_me.size());
2846  libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_offsets_to_me.size());
2847 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
2848 
2849  // Add the dof constraints that I've been sent
2850  for (std::size_t i = 0; i != pushed_ids_to_me.size(); ++i)
2851  {
2852  libmesh_assert_equal_to (pushed_keys_to_me[i].size(), pushed_vals_to_me[i].size());
2853 
2854  dof_id_type constrained = pushed_ids_to_me[i];
2855 
2856  // If we don't already have a constraint for this dof,
2857  // add the one we were sent
2858  if (!this->is_constrained_dof(constrained))
2859  {
2860  DofConstraintRow & row = _dof_constraints[constrained];
2861  for (std::size_t j = 0; j != pushed_keys_to_me[i].size(); ++j)
2862  {
2863  row[pushed_keys_to_me[i][j]] = pushed_vals_to_me[i][j];
2864  }
2865  if (libmesh_isnan(pushed_rhss_to_me[i]))
2866  libmesh_assert(pushed_keys_to_me[i].empty());
2867  if (pushed_rhss_to_me[i] != Number(0))
2868  _primal_constraint_values[constrained] = pushed_rhss_to_me[i];
2869  else
2870  _primal_constraint_values.erase(constrained);
2871 
2872  for (unsigned int q = 0; q != max_qoi_num; ++q)
2873  {
2874  AdjointDofConstraintValues::iterator adjoint_map_it =
2876 
2877  if ((adjoint_map_it == _adjoint_constraint_values.end()) &&
2878  pushed_adj_rhss_to_me[q][constrained] == Number(0))
2879  continue;
2880 
2881  if (adjoint_map_it == _adjoint_constraint_values.end())
2882  adjoint_map_it = _adjoint_constraint_values.insert
2883  (std::make_pair(q,DofConstraintValueMap())).first;
2884 
2885  DofConstraintValueMap & constraint_map =
2886  adjoint_map_it->second;
2887 
2888  if (pushed_adj_rhss_to_me[q][i] != Number(0))
2889  constraint_map[constrained] =
2890  pushed_adj_rhss_to_me[q][i];
2891  else
2892  constraint_map.erase(constrained);
2893  }
2894  }
2895  }
2896 
2897 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2898  // Add the node constraints that I've been sent
2899  for (std::size_t i = 0; i != pushed_node_ids_to_me.size(); ++i)
2900  {
2901  libmesh_assert_equal_to (pushed_node_keys_to_me[i].size(), pushed_node_vals_to_me[i].size());
2902 
2903  dof_id_type constrained_id = pushed_node_ids_to_me[i];
2904 
2905  // If we don't already have a constraint for this node,
2906  // add the one we were sent
2907  const Node * constrained = mesh.node_ptr(constrained_id);
2908  if (!this->is_constrained_node(constrained))
2909  {
2910  NodeConstraintRow & row = _node_constraints[constrained].first;
2911  for (std::size_t j = 0; j != pushed_node_keys_to_me[i].size(); ++j)
2912  {
2913  const Node * key_node = mesh.node_ptr(pushed_node_keys_to_me[i][j]);
2914  libmesh_assert(key_node);
2915  row[key_node] = pushed_node_vals_to_me[i][j];
2916  }
2917  _node_constraints[constrained].second = pushed_node_offsets_to_me[i];
2918  }
2919  }
2920 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
2921  }
2922  }
2923 
2924  // Now start checking for any other constraints we need
2925  // to know about, requesting them recursively.
2926 
2927  // Create sets containing the DOFs and nodes we already depend on
2928  typedef std::set<dof_id_type> DoF_RCSet;
2929  DoF_RCSet unexpanded_dofs;
2930 
2931  for (DofConstraints::iterator i = _dof_constraints.begin();
2932  i != _dof_constraints.end(); ++i)
2933  {
2934  unexpanded_dofs.insert(i->first);
2935  }
2936 
2937  // Gather all the dof constraints we need
2938  this->gather_constraints(mesh, unexpanded_dofs, false);
2939 
2940  // Gather all the node constraints we need
2941 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2942  typedef std::set<const Node *> Node_RCSet;
2943  Node_RCSet unexpanded_nodes;
2944 
2945  for (NodeConstraints::iterator i = _node_constraints.begin();
2946  i != _node_constraints.end(); ++i)
2947  {
2948  unexpanded_nodes.insert(i->first);
2949  }
2950 
2951  // We have to keep recursing while the unexpanded set is
2952  // nonempty on *any* processor
2953  bool unexpanded_set_nonempty = !unexpanded_nodes.empty();
2954  this->comm().max(unexpanded_set_nonempty);
2955 
2956  while (unexpanded_set_nonempty)
2957  {
2958  // Let's make sure we don't lose sync in this loop.
2959  parallel_object_only();
2960 
2961  // Request sets
2962  Node_RCSet node_request_set;
2963 
2964  // Request sets to send to each processor
2965  std::vector<std::vector<dof_id_type>>
2966  requested_node_ids(this->n_processors());
2967 
2968  // And the sizes of each
2969  std::vector<dof_id_type>
2970  node_ids_on_proc(this->n_processors(), 0);
2971 
2972  // Fill (and thereby sort and uniq!) the main request sets
2973  for (Node_RCSet::iterator i = unexpanded_nodes.begin();
2974  i != unexpanded_nodes.end(); ++i)
2975  {
2976  NodeConstraintRow & row = _node_constraints[*i].first;
2977  for (NodeConstraintRow::iterator j = row.begin();
2978  j != row.end(); ++j)
2979  {
2980  const Node * const node = j->first;
2981  libmesh_assert(node);
2982 
2983  // If it's non-local and we haven't already got a
2984  // constraint for it, we might need to ask for one
2985  if ((node->processor_id() != this->processor_id()) &&
2986  !_node_constraints.count(node))
2987  node_request_set.insert(node);
2988  }
2989  }
2990 
2991  // Clear the unexpanded constraint sets; we're about to expand
2992  // them
2993  unexpanded_nodes.clear();
2994 
2995  // Count requests by processor
2996  for (Node_RCSet::iterator i = node_request_set.begin();
2997  i != node_request_set.end(); ++i)
2998  {
2999  libmesh_assert(*i);
3000  libmesh_assert_less ((*i)->processor_id(), this->n_processors());
3001  node_ids_on_proc[(*i)->processor_id()]++;
3002  }
3003 
3004  for (processor_id_type p = 0; p != this->n_processors(); ++p)
3005  {
3006  requested_node_ids[p].reserve(node_ids_on_proc[p]);
3007  }
3008 
3009  // Prepare each processor's request set
3010  for (Node_RCSet::iterator i = node_request_set.begin();
3011  i != node_request_set.end(); ++i)
3012  {
3013  requested_node_ids[(*i)->processor_id()].push_back((*i)->id());
3014  }
3015 
3016  // Now request constraint rows from other processors
3017  for (processor_id_type p=1; p != this->n_processors(); ++p)
3018  {
3019  // Trade my requests with processor procup and procdown
3020  processor_id_type procup =
3021  cast_int<processor_id_type>((this->processor_id() + p) %
3022  this->n_processors());
3023  processor_id_type procdown =
3024  cast_int<processor_id_type>((this->n_processors() +
3025  this->processor_id() - p) %
3026  this->n_processors());
3027  std::vector<dof_id_type> node_request_to_fill;
3028 
3029  this->comm().send_receive(procup, requested_node_ids[procup],
3030  procdown, node_request_to_fill);
3031 
3032  // Fill those requests
3033  std::vector<std::vector<dof_id_type>>
3034  node_row_keys(node_request_to_fill.size());
3035  std::vector<std::vector<Real>>
3036  node_row_vals(node_request_to_fill.size());
3037  std::vector<Point>
3038  node_row_rhss(node_request_to_fill.size());
3039 
3040  // FIXME - this could be an unordered set, given a
3041  // hash<pointers> specialization
3042  std::set<const Node *> nodes_requested;
3043 
3044  for (std::size_t i=0; i != node_request_to_fill.size(); ++i)
3045  {
3046  dof_id_type constrained_id = node_request_to_fill[i];
3047  const Node * constrained_node = mesh.node_ptr(constrained_id);
3048  if (_node_constraints.count(constrained_node))
3049  {
3050  const NodeConstraintRow & row = _node_constraints[constrained_node].first;
3051  std::size_t row_size = row.size();
3052  node_row_keys[i].reserve(row_size);
3053  node_row_vals[i].reserve(row_size);
3054  for (NodeConstraintRow::const_iterator j = row.begin();
3055  j != row.end(); ++j)
3056  {
3057  const Node * node = j->first;
3058  node_row_keys[i].push_back(node->id());
3059  node_row_vals[i].push_back(j->second);
3060 
3061  // If we're not sure whether our send
3062  // destination already has this node, let's give
3063  // it a copy.
3064  if (node->processor_id() != procdown)
3065  nodes_requested.insert(node);
3066 
3067  // We can have 0 nodal constraint
3068  // coefficients, where no Lagrange constraint
3069  // exists but non-Lagrange basis constraints
3070  // might.
3071  // libmesh_assert(j->second);
3072  }
3073  node_row_rhss[i] = _node_constraints[constrained_node].second;
3074  }
3075  }
3076 
3077  // Trade back the results
3078  std::vector<std::vector<dof_id_type>> node_filled_keys;
3079  std::vector<std::vector<Real>> node_filled_vals;
3080  std::vector<Point> node_filled_rhss;
3081 
3082  this->comm().send_receive(procdown, node_row_keys,
3083  procup, node_filled_keys);
3084  this->comm().send_receive(procdown, node_row_vals,
3085  procup, node_filled_vals);
3086  this->comm().send_receive(procdown, node_row_rhss,
3087  procup, node_filled_rhss);
3088 
3089  // Constraining nodes might not even exist on our subset of
3090  // a distributed mesh, so let's make them exist.
3091  if (!mesh.is_serial())
3093  (procdown, &mesh, nodes_requested.begin(), nodes_requested.end(),
3095  (Node**)libmesh_nullptr);
3096 
3097  libmesh_assert_equal_to (node_filled_keys.size(), requested_node_ids[procup].size());
3098  libmesh_assert_equal_to (node_filled_vals.size(), requested_node_ids[procup].size());
3099  libmesh_assert_equal_to (node_filled_rhss.size(), requested_node_ids[procup].size());
3100 
3101  for (std::size_t i=0; i != requested_node_ids[procup].size(); ++i)
3102  {
3103  libmesh_assert_equal_to (node_filled_keys[i].size(), node_filled_vals[i].size());
3104  if (!node_filled_keys[i].empty())
3105  {
3106  dof_id_type constrained_id = requested_node_ids[procup][i];
3107  const Node * constrained_node = mesh.node_ptr(constrained_id);
3108  NodeConstraintRow & row = _node_constraints[constrained_node].first;
3109  for (std::size_t j = 0; j != node_filled_keys[i].size(); ++j)
3110  {
3111  const Node * key_node =
3112  mesh.node_ptr(node_filled_keys[i][j]);
3113  libmesh_assert(key_node);
3114  row[key_node] = node_filled_vals[i][j];
3115  }
3116  _node_constraints[constrained_node].second = node_filled_rhss[i];
3117 
3118  // And prepare to check for more recursive constraints
3119  unexpanded_nodes.insert(constrained_node);
3120  }
3121  }
3122  }
3123 
3124  // We have to keep recursing while the unexpanded set is
3125  // nonempty on *any* processor
3126  unexpanded_set_nonempty = !unexpanded_nodes.empty();
3127  this->comm().max(unexpanded_set_nonempty);
3128  }
3129 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
3130 }
A geometric point in (x,y,z) space associated with a DOF.
Definition: node.h:52
virtual bool is_serial() const
Definition: mesh_base.h:141
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
Definition: dof_object.h:745
void send_receive_packed_range(const unsigned int dest_processor_id, const Context1 *context1, RangeIter send_begin, const RangeIter send_end, const unsigned int source_processor_id, Context2 *context2, OutputIter out, const T *output_type, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag) const
processor_id_type n_processors() const
The base class for all geometric element types.
Definition: elem.h:90
MeshBase & mesh
void gather_constraints(MeshBase &mesh, std::set< dof_id_type > &unexpanded_dofs, bool look_for_constrainees)
uint8_t processor_id_type
Definition: id_types.h:99
const class libmesh_nullptr_t libmesh_nullptr
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:810
virtual const Node * node_ptr(const dof_id_type i) const =0
IterBase * end
const unsigned int n_vars
Definition: tecplot_io.C:68
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1618
virtual unsigned int n_nodes() const =0
void send_receive(const unsigned int dest_processor_id, const T1 &send, const unsigned int source_processor_id, T2 &recv, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag) const
const dof_id_type n_nodes
Definition: tecplot_io.C:67
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1756
bool is_constrained_node(const Node *node) const
Definition: dof_map.h:1739
const Node * node_ptr(const unsigned int i) const
Definition: elem.h:1875
const Node & node_ref(const unsigned int i) const
Definition: elem.h:1897
DofConstraints _dof_constraints
Definition: dof_map.h:1614
unsigned int sys_number() const
Definition: dof_map.h:1671
An output iterator for use with packed_range functions.
virtual element_iterator active_not_local_elements_end()=0
bool libmesh_isnan(float a)
const Parallel::Communicator & comm() const
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1616
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:89
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:137
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:1832
unsigned int n_comp(const unsigned int s, const unsigned int var) const
Definition: dof_object.h:780
dof_id_type id() const
Definition: dof_object.h:632
uint8_t dof_id_type
Definition: id_types.h:64
processor_id_type processor_id() const
processor_id_type processor_id() const
Definition: dof_object.h:694
NodeConstraints _node_constraints
Definition: dof_map.h:1625
void libMesh::DofMap::attach_extra_send_list_function ( void(*)(std::vector< dof_id_type > &, void *)  func,
void *  context = libmesh_nullptr 
)
inline

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

Definition at line 374 of file dof_map.h.

void * _extra_send_list_context
Definition: dof_map.h:1506
void(* _extra_send_list_function)(std::vector< dof_id_type > &, void *)
Definition: dof_map.h:1501
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 365 of file dof_map.h.

366  {
367  _augment_send_list = &asl;
368  }
AugmentSendList * _augment_send_list
Definition: dof_map.h:1496
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 = libmesh_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 351 of file dof_map.h.

void * _extra_sparsity_context
Definition: dof_map.h:1491
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:1484
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 336 of file dof_map.h.

337  {
339  }
AugmentSparsityPattern * _augment_sparsity_pattern
Definition: dof_map.h:1479
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 253 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().

254 {
255  parallel_object_only();
256 
257  // We shouldn't be trying to re-attach the same matrices repeatedly
258  libmesh_assert (std::find(_matrices.begin(), _matrices.end(),
259  &matrix) == _matrices.end());
260 
261  _matrices.push_back(&matrix);
262 
263  matrix.attach_dof_map (*this);
264 
265  // If we've already computed sparsity, then it's too late
266  // to wait for "compute_sparsity" to help with sparse matrix
267  // initialization, and we need to handle this matrix individually
268  bool computed_sparsity_already =
269  ((_n_nz && !_n_nz->empty()) ||
270  (_n_oz && !_n_oz->empty()));
271  this->comm().max(computed_sparsity_already);
272  if (computed_sparsity_already &&
274  {
275  // We'd better have already computed the full sparsity pattern
276  // if we need it here
277  libmesh_assert(need_full_sparsity_pattern);
278  libmesh_assert(_sp.get());
279 
280  matrix.update_sparsity_pattern (_sp->sparsity_pattern);
281  }
282 
283  if (matrix.need_full_sparsity_pattern())
285 }
std::unique_ptr< SparsityPattern::Build > _sp
Definition: dof_map.h:1557
std::vector< dof_id_type > * _n_nz
Definition: dof_map.h:1565
std::vector< dof_id_type > * _n_oz
Definition: dof_map.h:1571
bool need_full_sparsity_pattern
Definition: dof_map.h:1551
virtual bool need_full_sparsity_pattern() const
std::vector< SparseMatrix< Number > * > _matrices
Definition: dof_map.h:1452
void attach_dof_map(const DofMap &dof_map)
virtual void update_sparsity_pattern(const SparsityPattern::Graph &)
const Parallel::Communicator & comm() const
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 507 of file dof_map.h.

508  {
509 #ifdef LIBMESH_ENABLE_BLOCKED_STORAGE
510  return (this->has_blocked_representation() ? this->n_variables() : 1);
511 #else
512  return 1;
513 #endif
514  }
unsigned int n_variables() const
Definition: dof_map.h:486
bool has_blocked_representation() const
Definition: dof_map.h:494
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 2360 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().

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

References libmesh_nullptr, 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().

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

Builds a sparsity pattern

Definition at line 55 of file dof_map.C.

References _augment_sparsity_pattern, _coupling_functors, _dof_coupling, _extra_sparsity_context, _extra_sparsity_function, libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::DofMap::AugmentSparsityPattern::augment_sparsity_pattern(), libMesh::MeshBase::is_prepared(), n_dofs_on_processor(), need_full_sparsity_pattern, libMesh::out, libMesh::Threads::parallel_reduce(), libMesh::ParallelObject::processor_id(), and use_coupled_neighbor_dofs().

Referenced by compute_sparsity().

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

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

4283 {
4284  const std::set<boundary_id_type>& mesh_bcids = mesh.get_boundary_info().get_boundary_ids();
4285  const std::set<boundary_id_type>& dbc_bcids = boundary.b;
4286 
4287  // DirichletBoundary id sets should be consistent across all ranks
4288  libmesh_assert(mesh.comm().verify(dbc_bcids.size()));
4289 
4290  for (std::set<boundary_id_type>::const_iterator bid = dbc_bcids.begin();
4291  bid != dbc_bcids.end(); ++bid)
4292  {
4293  // DirichletBoundary id sets should be consistent across all ranks
4294  libmesh_assert(mesh.comm().verify(*bid));
4295 
4296  bool found_bcid = (mesh_bcids.find(*bid) != mesh_bcids.end());
4297 
4298  // On a distributed mesh, boundary id sets may *not* be
4299  // consistent across all ranks, since not all ranks see all
4300  // boundaries
4301  mesh.comm().max(found_bcid);
4302 
4303  if (!found_bcid)
4304  libmesh_error_msg("Could not find Dirichlet boundary id " << *bid << " in mesh!");
4305  }
4306 }
const BoundaryInfo & get_boundary_info() const
Definition: mesh_base.h:118
const std::set< boundary_id_type > & get_boundary_ids() const
const Parallel::Communicator & comm() const
std::set< boundary_id_type > b
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 3249 of file dof_map_constraints.C.

References libMesh::Real.

3250 {
3251  // Create a set containing the DOFs we already depend on
3252  typedef std::set<dof_id_type> RCSet;
3253  RCSet unexpanded_set;
3254 
3255  // Use dof_constraints_copy in this method so that we don't
3256  // mess with _dof_constraints.
3257  DofConstraints dof_constraints_copy = _dof_constraints;
3258 
3259  for (DofConstraints::iterator i = dof_constraints_copy.begin();
3260  i != dof_constraints_copy.end(); ++i)
3261  unexpanded_set.insert(i->first);
3262 
3263  while (!unexpanded_set.empty())
3264  for (RCSet::iterator i = unexpanded_set.begin();
3265  i != unexpanded_set.end(); /* nothing */)
3266  {
3267  // If the DOF is constrained
3268  DofConstraints::iterator
3269  pos = dof_constraints_copy.find(*i);
3270 
3271  libmesh_assert (pos != dof_constraints_copy.end());
3272 
3273  DofConstraintRow & constraint_row = pos->second;
3274 
3275  // Comment out "rhs" parts of this method copied from process_constraints
3276  // DofConstraintValueMap::iterator rhsit =
3277  // _primal_constraint_values.find(*i);
3278  // Number constraint_rhs = (rhsit == _primal_constraint_values.end()) ?
3279  // 0 : rhsit->second;
3280 
3281  std::vector<dof_id_type> constraints_to_expand;
3282 
3283  for (DofConstraintRow::const_iterator
3284  it=constraint_row.begin(); it != constraint_row.end();
3285  ++it)
3286  if (it->first != *i && this->is_constrained_dof(it->first))
3287  {
3288  unexpanded_set.insert(it->first);
3289  constraints_to_expand.push_back(it->first);
3290  }
3291 
3292  for (std::size_t j = 0; j != constraints_to_expand.size();
3293  ++j)
3294  {
3295  dof_id_type expandable = constraints_to_expand[j];
3296 
3297  const Real this_coef = constraint_row[expandable];
3298 
3299  DofConstraints::const_iterator
3300  subpos = dof_constraints_copy.find(expandable);
3301 
3302  libmesh_assert (subpos != dof_constraints_copy.end());
3303 
3304  const DofConstraintRow & subconstraint_row = subpos->second;
3305 
3306  for (DofConstraintRow::const_iterator
3307  it=subconstraint_row.begin();
3308  it != subconstraint_row.end(); ++it)
3309  {
3310 
3311  if(it->first == expandable)
3312  {
3313  libmesh_error_msg("Cyclic constraint detected");
3314  }
3315 
3316  constraint_row[it->first] += it->second * this_coef;
3317  }
3318 
3319  // Comment out "rhs" parts of this method copied from process_constraints
3320  // DofConstraintValueMap::const_iterator subrhsit =
3321  // _primal_constraint_values.find(expandable);
3322  // if (subrhsit != _primal_constraint_values.end())
3323  // constraint_rhs += subrhsit->second * this_coef;
3324 
3325  constraint_row.erase(expandable);
3326  }
3327 
3328  // Comment out "rhs" parts of this method copied from process_constraints
3329  // if (rhsit == _primal_constraint_values.end())
3330  // {
3331  // if (constraint_rhs != Number(0))
3332  // _primal_constraint_values[*i] = constraint_rhs;
3333  // else
3334  // _primal_constraint_values.erase(*i);
3335  // }
3336  // else
3337  // {
3338  // if (constraint_rhs != Number(0))
3339  // rhsit->second = constraint_rhs;
3340  // else
3341  // _primal_constraint_values.erase(rhsit);
3342  // }
3343 
3344  if (constraints_to_expand.empty())
3345  unexpanded_set.erase(i++);
3346  else
3347  ++i;
3348  }
3349 }
DofConstraints _dof_constraints
Definition: dof_map.h:1614
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:89
uint8_t dof_id_type
Definition: id_types.h:64
void libMesh::DofMap::clear ( )

Free all memory associated with the object, but keep the mesh pointer.

Definition at line 810 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_groups, _variables, add_algebraic_ghosting_functor(), add_coupling_functor(), algebraic_ghosting_functors_begin(), algebraic_ghosting_functors_end(), clear_sparsity(), coupling_functors_begin(), coupling_functors_end(), need_full_sparsity_pattern, libMesh::MeshBase::remove_ghosting_functor(), and use_coupled_neighbor_dofs().

Referenced by ~DofMap().

811 {
812  // we don't want to clear
813  // the coupling matrix!
814  // It should not change...
815  //_dof_coupling->clear();
816  //
817  // But it would be inconsistent to leave our coupling settings
818  // through a clear()...
819  _dof_coupling = NULL;
820 
821  // Reset ghosting functor statuses
822  {
823  std::set<GhostingFunctor *>::iterator gf_it = this->coupling_functors_begin();
824  const std::set<GhostingFunctor *>::iterator gf_end = this->coupling_functors_end();
825  for (; gf_it != gf_end; ++gf_it)
826  {
827  GhostingFunctor * gf = *gf_it;
828  libmesh_assert(gf);
830  }
831  this->_coupling_functors.clear();
832 
833  // Go back to default coupling
834 
835  _default_coupling->set_dof_coupling(this->_dof_coupling);
836  _default_coupling->set_n_levels(this->use_coupled_neighbor_dofs(this->_mesh));
837 
839  }
840 
841 
842  {
843  std::set<GhostingFunctor *>::iterator gf_it = this->algebraic_ghosting_functors_begin();
844  const std::set<GhostingFunctor *>::iterator gf_end = this->algebraic_ghosting_functors_end();
845  for (; gf_it != gf_end; ++gf_it)
846  {
847  GhostingFunctor * gf = *gf_it;
848  libmesh_assert(gf);
850  }
851  this->_algebraic_ghosting_functors.clear();
852 
853  // Go back to default send_list generation
854 
855  // _default_evaluating->set_dof_coupling(this->_dof_coupling);
856  _default_evaluating->set_n_levels(1);
858  }
859 
860  _variables.clear();
861  _variable_groups.clear();
862  _first_df.clear();
863  _end_df.clear();
864  _first_scalar_df.clear();
865  _send_list.clear();
866  this->clear_sparsity();
868 
869 #ifdef LIBMESH_ENABLE_AMR
870 
871  _dof_constraints.clear();
872  _stashed_dof_constraints.clear();
875  _n_old_dfs = 0;
876  _first_old_df.clear();
877  _end_old_df.clear();
878  _first_old_scalar_df.clear();
879 
880 #endif
881 
882  _matrices.clear();
883 
884  _n_dfs = 0;
885 }
std::vector< VariableGroup > _variable_groups
Definition: dof_map.h:1435
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_begin() const
Definition: dof_map.h:312
std::set< GhostingFunctor * >::const_iterator coupling_functors_begin() const
Definition: dof_map.h:276
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1474
void remove_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: mesh_base.C:307
std::set< GhostingFunctor * > _algebraic_ghosting_functors
Definition: dof_map.h:1532
std::vector< dof_id_type > _end_old_df
Definition: dof_map.h:1599
void add_coupling_functor(GhostingFunctor &coupling_functor)
Definition: dof_map.C:1801
std::vector< dof_id_type > _first_old_df
Definition: dof_map.h:1594
std::vector< dof_id_type > _first_scalar_df
Definition: dof_map.h:1468
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1618
bool need_full_sparsity_pattern
Definition: dof_map.h:1551
void add_algebraic_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: dof_map.C:1820
std::vector< dof_id_type > _first_old_scalar_df
Definition: dof_map.h:1605
DofConstraints _dof_constraints
Definition: dof_map.h:1614
CouplingMatrix * _dof_coupling
Definition: dof_map.h:1256
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_end() const
Definition: dof_map.h:318
std::vector< SparseMatrix< Number > * > _matrices
Definition: dof_map.h:1452
std::unique_ptr< DefaultCoupling > _default_coupling
Definition: dof_map.h:1514
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1616
std::vector< Variable > _variables
Definition: dof_map.h:1430
DofConstraints _stashed_dof_constraints
Definition: dof_map.h:1614
dof_id_type _n_old_dfs
Definition: dof_map.h:1589
void clear_sparsity()
Definition: dof_map.C:1779
std::set< GhostingFunctor * > _coupling_functors
Definition: dof_map.h:1545
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1462
std::vector< dof_id_type > _first_df
Definition: dof_map.h:1457
MeshBase & _mesh
Definition: dof_map.h:1445
std::unique_ptr< DefaultCoupling > _default_evaluating
Definition: dof_map.h:1522
std::set< GhostingFunctor * >::const_iterator coupling_functors_end() const
Definition: dof_map.h:282
bool use_coupled_neighbor_dofs(const MeshBase &mesh) const
Definition: dof_map.C:1685
dof_id_type _n_dfs
Definition: dof_map.h:1576
void libMesh::DofMap::clear_sparsity ( )

Clears the sparsity pattern

Definition at line 1779 of file dof_map.C.

References _n_nz, _n_oz, _sp, libmesh_nullptr, and need_full_sparsity_pattern.

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

1780 {
1782  {
1783  libmesh_assert(_sp.get());
1784  libmesh_assert(!_n_nz || _n_nz == &_sp->n_nz);
1785  libmesh_assert(!_n_oz || _n_oz == &_sp->n_oz);
1786  _sp.reset();
1787  }
1788  else
1789  {
1790  libmesh_assert(!_sp.get());
1791  delete _n_nz;
1792  delete _n_oz;
1793  }
1796 }
std::unique_ptr< SparsityPattern::Build > _sp
Definition: dof_map.h:1557
const class libmesh_nullptr_t libmesh_nullptr
std::vector< dof_id_type > * _n_nz
Definition: dof_map.h:1565
std::vector< dof_id_type > * _n_oz
Definition: dof_map.h:1571
bool need_full_sparsity_pattern
Definition: dof_map.h:1551
const Parallel::Communicator& libMesh::ParallelObject::comm ( ) const
inlineinherited
Returns
A reference to the Parallel::Communicator object used by this mesh.

Definition at line 87 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_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_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::ParmetisPartitioner::_do_repartition(), libMesh::UniformRefinementEstimator::_estimate_error(), libMesh::BoundaryInfo::_find_id_maps(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_get_diagonal(), libMesh::SlepcEigenSolver< T >::_petsc_shell_matrix_get_diagonal(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_mult(), libMesh::SlepcEigenSolver< 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::ImplicitSystem::add_matrix(), libMesh::System::add_vector(), libMesh::EigenSparseLinearSolver< T >::adjoint_solve(), libMesh::UnstructuredMesh::all_second_order(), libMesh::MeshTools::Modification::all_tri(), libMesh::LaplaceMeshSmoother::allgather_graph(), libMesh::FEMSystem::assemble_qoi(), libMesh::MeshCommunication::assign_global_indices(), libMesh::ParmetisPartitioner::assign_partitioning(), attach_matrix(), libMesh::Parallel::BinSorter< KeyType, IdxType >::binsort(), libMesh::Parallel::Sort< KeyType, IdxType >::binsort(), libMesh::MeshCommunication::broadcast(), libMesh::SparseMatrix< T >::build(), libMesh::MeshTools::Generation::build_extrusion(), libMesh::Parallel::Histogram< KeyType, IdxType >::build_histogram(), libMesh::PetscNonlinearSolver< T >::build_mat_null_space(), libMesh::BoundaryInfo::build_node_list_from_side_list(), libMesh::EquationSystems::build_parallel_solution_vector(), libMesh::MeshBase::cache_elem_dims(), libMesh::System::calculate_norm(), check_dirichlet_bcid_consistency(), libMesh::DistributedVector< T >::clone(), libMesh::EigenSparseVector< T >::clone(), libMesh::LaspackVector< T >::clone(), libMesh::EpetraVector< T >::clone(), libMesh::PetscVector< T >::clone(), libMesh::EpetraVector< T >::close(), libMesh::Parallel::Sort< KeyType, IdxType >::communicate_bins(), 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::MeshCommunication::gather(), libMesh::MeshCommunication::gather_neighboring_elements(), libMesh::CondensedEigenSystem::get_eigenpair(), get_info(), libMesh::ImplicitSystem::get_linear_solver(), libMesh::EquationSystems::get_solution(), libMesh::LocationMap< T >::init(), libMesh::TopologyMap::init(), libMesh::TimeSolver::init(), libMesh::TaoOptimizationSolver< T >::init(), libMesh::PetscNonlinearSolver< T >::init(), libMesh::DistributedVector< T >::init(), libMesh::EpetraVector< T >::init(), libMesh::PetscVector< T >::init(), libMesh::SystemSubsetBySubdomain::init(), libMesh::EigenSystem::init_data(), libMesh::EigenSystem::init_matrices(), libMesh::ParmetisPartitioner::initialize(), libMesh::OptimizationSystem::initialize_equality_constraints_storage(), libMesh::OptimizationSystem::initialize_inequality_constraints_storage(), 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_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::DistributedVector< T >::max(), libMesh::FEMSystem::mesh_position_set(), libMesh::MeshSerializer::MeshSerializer(), libMesh::DistributedVector< T >::min(), 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::Partitioner::partition(), libMesh::LinearPartitioner::partition_range(), libMesh::MetisPartitioner::partition_range(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::petsc_auto_fieldsplit(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), libMesh::MeshBase::prepare_for_use(), libMesh::SparseMatrix< T >::print(), libMesh::Nemesis_IO::read(), libMesh::XdrIO::read(), libMesh::CheckpointIO::read_header(), libMesh::XdrIO::read_header(), libMesh::XdrIO::read_serialized_bc_names(), libMesh::XdrIO::read_serialized_bcs_helper(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::MeshBase::recalculate_n_partitions(), libMesh::MeshCommunication::redistribute(), libMesh::MeshRefinement::refine_and_coarsen_elements(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::CheckpointIO::select_split_config(), libMesh::MeshCommunication::send_coarse_ghosts(), libMesh::Partitioner::set_node_processor_ids(), set_nonlocal_dof_objects(), libMesh::Partitioner::set_parent_processor_ids(), libMesh::PetscDiffSolver::setup_petsc_data(), libMesh::LaplaceMeshSmoother::smooth(), libMesh::Parallel::Sort< KeyType, IdxType >::sort(), libMesh::split_mesh(), libMesh::MeshBase::subdomain_ids(), libMesh::BoundaryInfo::sync(), libMesh::Parallel::sync_element_data_by_parent_id(), libMesh::Parallel::sync_node_data_by_element_id(), libMesh::MeshRefinement::test_level_one(), libMesh::MeshRefinement::test_unflagged(), libMesh::MeshTools::total_weight(), libMesh::MeshRefinement::uniformly_coarsen(), libMesh::NameBasedIO::write(), libMesh::XdrIO::write(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), libMesh::XdrIO::write_serialized_nodesets(), libMesh::DistributedVector< T >::zero_clone(), libMesh::EigenSparseVector< T >::zero_clone(), libMesh::LaspackVector< T >::zero_clone(), libMesh::EpetraVector< T >::zero_clone(), and libMesh::PetscVector< T >::zero_clone().

88  { return _communicator; }
const Parallel::Communicator & _communicator
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 1742 of file dof_map.C.

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

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

1743 {
1744  _sp = this->build_sparsity(mesh);
1745 
1746  // It is possible that some \p SparseMatrix implementations want to
1747  // see it. Let them see it before we throw it away.
1748  std::vector<SparseMatrix<Number> *>::const_iterator
1749  pos = _matrices.begin(),
1750  end = _matrices.end();
1751 
1752  // If we need the full sparsity pattern, then we share a view of its
1753  // arrays, and we pass it in to the matrices.
1755  {
1756  _n_nz = &_sp->n_nz;
1757  _n_oz = &_sp->n_oz;
1758 
1759  for (; pos != end; ++pos)
1760  (*pos)->update_sparsity_pattern (_sp->sparsity_pattern);
1761  }
1762  // If we don't need the full sparsity pattern anymore, steal the
1763  // arrays we do need and free the rest of the memory
1764  else
1765  {
1766  if (!_n_nz)
1767  _n_nz = new std::vector<dof_id_type>();
1768  _n_nz->swap(_sp->n_nz);
1769  if (!_n_oz)
1770  _n_oz = new std::vector<dof_id_type>();
1771  _n_oz->swap(_sp->n_oz);
1772 
1773  _sp.reset();
1774  }
1775 }
std::unique_ptr< SparsityPattern::Build > _sp
Definition: dof_map.h:1557
MeshBase & mesh
IterBase * end
std::vector< dof_id_type > * _n_nz
Definition: dof_map.h:1565
std::vector< dof_id_type > * _n_oz
Definition: dof_map.h:1571
bool need_full_sparsity_pattern
Definition: dof_map.h:1551
std::vector< SparseMatrix< Number > * > _matrices
Definition: dof_map.h:1452
std::unique_ptr< SparsityPattern::Build > build_sparsity(const MeshBase &mesh) const
Definition: dof_map.C:55
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 2016 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().

Referenced by get_primal_constraint_values().

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

Referenced by get_primal_constraint_values().

1558 {
1559  libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
1560  libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
1561 
1562  // check for easy return
1563  if (this->_dof_constraints.empty())
1564  return;
1565 
1566  // The constrained matrix is built up as C^T K C.
1568 
1569 
1570  this->build_constraint_matrix (C, elem_dofs);
1571 
1572  LOG_SCOPE("constrain_elem_matrix()", "DofMap");
1573 
1574  // It is possible that the matrix is not constrained at all.
1575  if ((C.m() == matrix.m()) &&
1576  (C.n() == elem_dofs.size())) // It the matrix is constrained
1577  {
1578  // Compute the matrix-matrix-matrix product C^T K C
1579  matrix.left_multiply_transpose (C);
1580  matrix.right_multiply (C);
1581 
1582 
1583  libmesh_assert_equal_to (matrix.m(), matrix.n());
1584  libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
1585  libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
1586 
1587 
1588  for (std::size_t i=0; i<elem_dofs.size(); i++)
1589  // If the DOF is constrained
1590  if (this->is_constrained_dof(elem_dofs[i]))
1591  {
1592  for (unsigned int j=0; j<matrix.n(); j++)
1593  matrix(i,j) = 0.;
1594 
1595  matrix(i,i) = 1.;
1596 
1597  if (asymmetric_constraint_rows)
1598  {
1599  DofConstraints::const_iterator
1600  pos = _dof_constraints.find(elem_dofs[i]);
1601 
1602  libmesh_assert (pos != _dof_constraints.end());
1603 
1604  const DofConstraintRow & constraint_row = pos->second;
1605 
1606  // This is an overzealous assertion in the presence of
1607  // heterogenous constraints: we now can constrain "u_i = c"
1608  // with no other u_j terms involved.
1609  //
1610  // libmesh_assert (!constraint_row.empty());
1611 
1612  for (DofConstraintRow::const_iterator
1613  it=constraint_row.begin(); it != constraint_row.end();
1614  ++it)
1615  for (std::size_t j=0; j<elem_dofs.size(); j++)
1616  if (elem_dofs[j] == it->first)
1617  matrix(i,j) = -it->second;
1618  }
1619  }
1620  } // end if is constrained...
1621 }
unsigned int n() const
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1756
virtual void right_multiply(const DenseMatrixBase< T > &M2) libmesh_override
unsigned int m() const
DofConstraints _dof_constraints
Definition: dof_map.h:1614
void build_constraint_matrix(DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
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:89
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 1886 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().

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

Referenced by get_primal_constraint_values().

1629 {
1630  libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
1631  libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
1632  libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
1633 
1634  // check for easy return
1635  if (this->_dof_constraints.empty())
1636  return;
1637 
1638  // The constrained matrix is built up as C^T K C.
1639  // The constrained RHS is built up as C^T F
1641 
1642  this->build_constraint_matrix (C, elem_dofs);
1643 
1644  LOG_SCOPE("cnstrn_elem_mat_vec()", "DofMap");
1645 
1646  // It is possible that the matrix is not constrained at all.
1647  if ((C.m() == matrix.m()) &&
1648  (C.n() == elem_dofs.size())) // It the matrix is constrained
1649  {
1650  // Compute the matrix-matrix-matrix product C^T K C
1651  matrix.left_multiply_transpose (C);
1652  matrix.right_multiply (C);
1653 
1654 
1655  libmesh_assert_equal_to (matrix.m(), matrix.n());
1656  libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
1657  libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
1658 
1659 
1660  for (std::size_t i=0; i<elem_dofs.size(); i++)
1661  if (this->is_constrained_dof(elem_dofs[i]))
1662  {
1663  for (unsigned int j=0; j<matrix.n(); j++)
1664  matrix(i,j) = 0.;
1665 
1666  // If the DOF is constrained
1667  matrix(i,i) = 1.;
1668 
1669  // This will put a nonsymmetric entry in the constraint
1670  // row to ensure that the linear system produces the
1671  // correct value for the constrained DOF.
1672  if (asymmetric_constraint_rows)
1673  {
1674  DofConstraints::const_iterator
1675  pos = _dof_constraints.find(elem_dofs[i]);
1676 
1677  libmesh_assert (pos != _dof_constraints.end());
1678 
1679  const DofConstraintRow & constraint_row = pos->second;
1680 
1681  // p refinement creates empty constraint rows
1682  // libmesh_assert (!constraint_row.empty());
1683 
1684  for (DofConstraintRow::const_iterator
1685  it=constraint_row.begin(); it != constraint_row.end();
1686  ++it)
1687  for (std::size_t j=0; j<elem_dofs.size(); j++)
1688  if (elem_dofs[j] == it->first)
1689  matrix(i,j) = -it->second;
1690  }
1691  }
1692 
1693 
1694  // Compute the matrix-vector product C^T F
1695  DenseVector<Number> old_rhs(rhs);
1696 
1697  // compute matrix/vector product
1698  C.vector_mult_transpose(rhs, old_rhs);
1699  } // end if is constrained...
1700 }
unsigned int n() const
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
virtual unsigned int size() const libmesh_override
Definition: dense_vector.h:87
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1756
virtual void right_multiply(const DenseMatrixBase< T > &M2) libmesh_override
unsigned int m() const
DofConstraints _dof_constraints
Definition: dof_map.h:1614
void build_constraint_matrix(DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
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:89
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 1976 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().

Referenced by get_primal_constraint_values().

1979 {
1980  libmesh_assert_equal_to (rhs.size(), row_dofs.size());
1981 
1982  // check for easy return
1983  if (this->_dof_constraints.empty())
1984  return;
1985 
1986  // The constrained RHS is built up as R^T F.
1988 
1989  this->build_constraint_matrix (R, row_dofs);
1990 
1991  LOG_SCOPE("constrain_elem_vector()", "DofMap");
1992 
1993  // It is possible that the vector is not constrained at all.
1994  if ((R.m() == rhs.size()) &&
1995  (R.n() == row_dofs.size())) // if the RHS is constrained
1996  {
1997  // Compute the matrix-vector product
1998  DenseVector<Number> old_rhs(rhs);
1999  R.vector_mult_transpose(rhs, old_rhs);
2000 
2001  libmesh_assert_equal_to (row_dofs.size(), rhs.size());
2002 
2003  for (std::size_t i=0; i<row_dofs.size(); i++)
2004  if (this->is_constrained_dof(row_dofs[i]))
2005  {
2006  // If the DOF is constrained
2007  libmesh_assert (_dof_constraints.find(row_dofs[i]) != _dof_constraints.end());
2008 
2009  rhs(i) = 0;
2010  }
2011  } // end if the RHS is constrained.
2012 }
unsigned int n() const
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
virtual unsigned int size() const libmesh_override
Definition: dense_vector.h:87
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1756
unsigned int m() const
DofConstraints _dof_constraints
Definition: dof_map.h:1614
void build_constraint_matrix(DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
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 2065 of file dof_map_constraints.C.

2066 {
2067  // check for easy return
2068  if (this->_dof_constraints.empty())
2069  return;
2070 
2071  // All the work is done by \p build_constraint_matrix. We just need
2072  // a dummy matrix.
2074  this->build_constraint_matrix (R, dofs);
2075 }
DofConstraints _dof_constraints
Definition: dof_map.h:1614
void build_constraint_matrix(DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
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 4114 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< OutputType >::compute_periodic_constraints(), and libMesh::FEGenericBase< OutputType >::compute_proj_constraints().

4118 {
4119  // We're constraining dofs on elem which correspond to p refinement
4120  // levels above p - this only makes sense if elem's p refinement
4121  // level is above p.
4122  libmesh_assert_greater (elem->p_level(), p);
4123  libmesh_assert_less (s, elem->n_sides());
4124 
4125  const unsigned int sys_num = this->sys_number();
4126  const unsigned int dim = elem->dim();
4127  ElemType type = elem->type();
4128  FEType low_p_fe_type = this->variable_type(var);
4129  FEType high_p_fe_type = this->variable_type(var);
4130  low_p_fe_type.order = static_cast<Order>(low_p_fe_type.order + p);
4131  high_p_fe_type.order = static_cast<Order>(high_p_fe_type.order +
4132  elem->p_level());
4133 
4134  const unsigned int n_nodes = elem->n_nodes();
4135  for (unsigned int n = 0; n != n_nodes; ++n)
4136  if (elem->is_node_on_side(n, s))
4137  {
4138  const Node & node = elem->node_ref(n);
4139  const unsigned int low_nc =
4140  FEInterface::n_dofs_at_node (dim, low_p_fe_type, type, n);
4141  const unsigned int high_nc =
4142  FEInterface::n_dofs_at_node (dim, high_p_fe_type, type, n);
4143 
4144  // since we may be running this method concurrently
4145  // on multiple threads we need to acquire a lock
4146  // before modifying the _dof_constraints object.
4147  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
4148 
4149  if (elem->is_vertex(n))
4150  {
4151  // Add "this is zero" constraint rows for high p vertex
4152  // dofs
4153  for (unsigned int i = low_nc; i != high_nc; ++i)
4154  {
4155  _dof_constraints[node.dof_number(sys_num,var,i)].clear();
4156  _primal_constraint_values.erase(node.dof_number(sys_num,var,i));
4157  }
4158  }
4159  else
4160  {
4161  const unsigned int total_dofs = node.n_comp(sys_num, var);
4162  libmesh_assert_greater_equal (total_dofs, high_nc);
4163  // Add "this is zero" constraint rows for high p
4164  // non-vertex dofs, which are numbered in reverse
4165  for (unsigned int j = low_nc; j != high_nc; ++j)
4166  {
4167  const unsigned int i = total_dofs - j - 1;
4168  _dof_constraints[node.dof_number(sys_num,var,i)].clear();
4169  _primal_constraint_values.erase(node.dof_number(sys_num,var,i));
4170  }
4171  }
4172  }
4173 }
Manages the family, order, etc. parameters for a given FE.
Definition: fe_type.h:179
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
A geometric point in (x,y,z) space associated with a DOF.
Definition: node.h:52
virtual ElemType type() const =0
unsigned int p_level() const
Definition: elem.h:2423
const FEType & variable_type(const unsigned int c) const
Definition: dof_map.h:1719
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:810
OrderWrapper order
Definition: fe_type.h:198
virtual unsigned int n_nodes() const =0
const dof_id_type n_nodes
Definition: tecplot_io.C:67
spin_mutex spin_mtx
Definition: threads.C:29
const Node & node_ref(const unsigned int i) const
Definition: elem.h:1897
DofConstraints _dof_constraints
Definition: dof_map.h:1614
virtual unsigned int n_sides() const =0
unsigned int sys_number() const
Definition: dof_map.h:1671
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:430
virtual bool is_vertex(const unsigned int i) const =0
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1616
virtual unsigned int dim() const =0
unsigned int n_comp(const unsigned int s, const unsigned int var) const
Definition: dof_object.h:780
DofConstraints::const_iterator libMesh::DofMap::constraint_rows_begin ( ) const
inline
Returns
An iterator pointing to the first DoF constraint row.

Definition at line 840 of file dof_map.h.

841  { return _dof_constraints.begin(); }
DofConstraints _dof_constraints
Definition: dof_map.h:1614
DofConstraints::const_iterator libMesh::DofMap::constraint_rows_end ( ) const
inline
Returns
An iterator pointing just past the last DoF constraint row.

Definition at line 846 of file dof_map.h.

847  { return _dof_constraints.end(); }
DofConstraints _dof_constraints
Definition: dof_map.h:1614
std::set<GhostingFunctor *>::const_iterator libMesh::DofMap::coupling_functors_begin ( ) const
inline

Beginning of range of coupling functors

Definition at line 276 of file dof_map.h.

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

277  { return _coupling_functors.begin(); }
std::set< GhostingFunctor * > _coupling_functors
Definition: dof_map.h:1545
std::set<GhostingFunctor *>::const_iterator libMesh::DofMap::coupling_functors_end ( ) const
inline

End of range of coupling functors

Definition at line 282 of file dof_map.h.

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

283  { return _coupling_functors.end(); }
std::set< GhostingFunctor * > _coupling_functors
Definition: dof_map.h:1545
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 1185 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(), libMesh::MeshBase::mesh_dimension(), libMesh::MeshBase::n_elem(), libMesh::Threads::parallel_for(), libMesh::StoredRange< iterator_type, object_type >::reset(), libMesh::MeshBase::sub_point_locator(), and libMesh::Parallel::verify().

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

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

Default algebraic ghosting functor

Definition at line 324 of file dof_map.h.

324 { return *_default_evaluating; }
std::unique_ptr< DefaultCoupling > _default_evaluating
Definition: dof_map.h:1522
DefaultCoupling& libMesh::DofMap::default_coupling ( )
inline

Default coupling functor

Definition at line 288 of file dof_map.h.

288 { return *_default_coupling; }
std::unique_ptr< DefaultCoupling > _default_coupling
Definition: dof_map.h:1514
void libMesh::ReferenceCounter::disable_print_counter_info ( )
staticinherited
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 889 of file dof_map.C.

References _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(), algebraic_ghosting_functors_begin(), algebraic_ghosting_functors_end(), libMesh::Parallel::Communicator::allgather(), libMesh::ParallelObject::comm(), coupling_functors_begin(), coupling_functors_end(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), libMesh::DofObject::dof_number(), libMesh::GhostingFunctor::dofmap_reinit(), elem_ptr(), libMesh::MeshBase::element_ptr_range(), libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), end_dof(), libMesh::FEType::family, first_dof(), libMesh::OrderWrapper::get_order(), libMesh::DofObject::invalid_id, invalidate_dofs(), libMesh::MeshBase::is_prepared(), 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::node_ptr_range(), libMesh::MeshBase::nodes_begin(), libMesh::MeshBase::nodes_end(), 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().

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

References _n_SCALAR_dofs, libMesh::MeshBase::active_local_element_ptr_range(), libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::OrderWrapper::get_order(), libMesh::DofObject::invalid_id, libMesh::MeshBase::local_node_ptr_range(), 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().

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

References _n_SCALAR_dofs, libMesh::MeshBase::active_local_element_ptr_range(), libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::OrderWrapper::get_order(), libMesh::DofObject::invalid_id, libMesh::MeshBase::local_node_ptr_range(), merge_ghost_functor_outputs(), 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().

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

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_solution_vector(), libMesh::System::calculate_norm(), libMesh::FEGenericBase< OutputType >::coarsened_dof_values(), libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), libMesh::FEGenericBase< OutputType >::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::EquationSystems::get_solution(), 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::SparsityPattern::Build::sorted_connected_dofs(), libMesh::EnsightIO::write_scalar_ascii(), and libMesh::EnsightIO::write_vector_ascii().

1926 {
1927  // We now allow elem==NULL to request just SCALAR dofs
1928  // libmesh_assert(elem);
1929 
1930  // If we are asking for current indices on an element, it ought to
1931  // be an active element (or a Side proxy, which also thinks it's
1932  // active)
1933  libmesh_assert(!elem || elem->active());
1934 
1935  LOG_SCOPE("dof_indices()", "DofMap");
1936 
1937  // Clear the DOF indices vector
1938  di.clear();
1939 
1940  const unsigned int n_vars = this->n_variables();
1941 
1942 #ifdef DEBUG
1943  // Check that sizes match in DEBUG mode
1944  std::size_t tot_size = 0;
1945 #endif
1946 
1947  if (elem && elem->type() == TRI3SUBDIVISION)
1948  {
1949  // Subdivision surface FE require the 1-ring around elem
1950  const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
1951 
1952  // Ghost subdivision elements have no real dofs
1953  if (!sd_elem->is_ghost())
1954  {
1955  // Determine the nodes contributing to element elem
1956  std::vector<const Node *> elem_nodes;
1957  MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
1958 
1959  // Get the dof numbers
1960  for (unsigned int v=0; v<n_vars; v++)
1961  {
1962  const Variable & var = this->variable(v);
1963  if (var.type().family == SCALAR &&
1964  var.active_on_subdomain(elem->subdomain_id()))
1965  {
1966 #ifdef DEBUG
1967  tot_size += this->variable(v).type().order;
1968 #endif
1969  std::vector<dof_id_type> di_new;
1970  this->SCALAR_dof_indices(di_new,v);
1971  di.insert( di.end(), di_new.begin(), di_new.end());
1972  }
1973  else
1974  _dof_indices(*elem, elem->p_level(), di, v,
1975  &elem_nodes[0], elem_nodes.size()
1976 #ifdef DEBUG
1977  , tot_size
1978 #endif
1979  );
1980  }
1981  }
1982 
1983  return;
1984  }
1985 
1986  // Get the dof numbers for each variable
1987  const unsigned int n_nodes = elem ? elem->n_nodes() : 0;
1988  for (unsigned int v=0; v<n_vars; v++)
1989  {
1990  const Variable & var = this->variable(v);
1991  if (var.type().family == SCALAR &&
1992  (!elem ||
1993  var.active_on_subdomain(elem->subdomain_id())))
1994  {
1995 #ifdef DEBUG
1996  tot_size += var.type().order;
1997 #endif
1998  std::vector<dof_id_type> di_new;
1999  this->SCALAR_dof_indices(di_new,v);
2000  di.insert( di.end(), di_new.begin(), di_new.end());
2001  }
2002  else if (elem)
2003  _dof_indices(*elem, elem->p_level(), di, v, elem->get_nodes(),
2004  n_nodes
2005 #ifdef DEBUG
2006  , tot_size
2007 #endif
2008  );
2009  }
2010 
2011 #ifdef DEBUG
2012  libmesh_assert_equal_to (tot_size, di.size());
2013 #endif
2014 }
const FEType & type() const
Definition: variable.h:119
OrderWrapper order
Definition: fe_type.h:198
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:1689
const unsigned int n_vars
Definition: tecplot_io.C:68
const dof_id_type n_nodes
Definition: tecplot_io.C:67
void _dof_indices(const Elem &elem, int p_level, std::vector< dof_id_type > &di, const unsigned int v, const Node *const *nodes, unsigned int n_nodes#ifdef DEBUG, std::size_t &tot_size#endif) const
Definition: dof_map.C:2171
unsigned int n_variables() const
Definition: dof_map.h:486
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Definition: dof_map.C:2295
void find_one_ring(const Tri3Subdivision *elem, std::vector< const Node * > &nodes)
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 2017 of file dof_map.C.

References _dof_indices(), 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::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().

2021 {
2022  // We now allow elem==NULL to request just SCALAR dofs
2023  // libmesh_assert(elem);
2024 
2025  LOG_SCOPE("dof_indices()", "DofMap");
2026 
2027  // Clear the DOF indices vector
2028  di.clear();
2029 
2030  // Use the default p refinement level?
2031  if (p_level == -12345)
2032  p_level = elem ? elem->p_level() : 0;
2033 
2034 #ifdef DEBUG
2035  // Check that sizes match in DEBUG mode
2036  std::size_t tot_size = 0;
2037 #endif
2038 
2039  if (elem && elem->type() == TRI3SUBDIVISION)
2040  {
2041  // Subdivision surface FE require the 1-ring around elem
2042  const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
2043 
2044  // Ghost subdivision elements have no real dofs
2045  if (!sd_elem->is_ghost())
2046  {
2047  // Determine the nodes contributing to element elem
2048  std::vector<const Node *> elem_nodes;
2049  MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
2050 
2051  _dof_indices(*elem, p_level, di, vn, &elem_nodes[0],
2052  elem_nodes.size()
2053 #ifdef DEBUG
2054  , tot_size
2055 #endif
2056  );
2057  }
2058 
2059  return;
2060  }
2061 
2062  const Variable & var = this->variable(vn);
2063 
2064  // Get the dof numbers
2065  if (var.type().family == SCALAR &&
2066  (!elem ||
2067  var.active_on_subdomain(elem->subdomain_id())))
2068  {
2069 #ifdef DEBUG
2070  tot_size += var.type().order;
2071 #endif
2072  std::vector<dof_id_type> di_new;
2073  this->SCALAR_dof_indices(di_new,vn);
2074  di.insert( di.end(), di_new.begin(), di_new.end());
2075  }
2076  else if (elem)
2077  _dof_indices(*elem, p_level, di, vn, elem->get_nodes(),
2078  elem->n_nodes()
2079 #ifdef DEBUG
2080  , tot_size
2081 #endif
2082  );
2083 
2084 #ifdef DEBUG
2085  libmesh_assert_equal_to (tot_size, di.size());
2086 #endif
2087 }
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:1689
void _dof_indices(const Elem &elem, int p_level, std::vector< dof_id_type > &di, const unsigned int v, const Node *const *nodes, unsigned int n_nodes#ifdef DEBUG, std::size_t &tot_size#endif) const
Definition: dof_map.C:2171
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Definition: dof_map.C:2295
void find_one_ring(const Tri3Subdivision *elem, std::vector< const Node * > &nodes)
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 2090 of file dof_map.C.

References libMesh::DofObject::dof_number(), libMesh::FEType::family, libMesh::DofObject::invalid_id, libMesh::DofObject::n_comp(), n_variables(), n_vars, libMesh::SCALAR, SCALAR_dof_indices(), sys_number(), libMesh::Variable::type(), and variable().

2092 {
2093  // We allow node==NULL to request just SCALAR dofs
2094  // libmesh_assert(elem);
2095 
2096  LOG_SCOPE("dof_indices(Node)", "DofMap");
2097 
2098  // Clear the DOF indices vector
2099  di.clear();
2100 
2101  const unsigned int n_vars = this->n_variables();
2102  const unsigned int sys_num = this->sys_number();
2103 
2104  // Get the dof numbers
2105  for (unsigned int v=0; v<n_vars; v++)
2106  {
2107  const Variable & var = this->variable(v);
2108  if (var.type().family == SCALAR)
2109  {
2110  std::vector<dof_id_type> di_new;
2111  this->SCALAR_dof_indices(di_new,v);
2112  di.insert( di.end(), di_new.begin(), di_new.end());
2113  }
2114  else
2115  {
2116  const int n_comp = node->n_comp(sys_num,v);
2117  for (int i=0; i != n_comp; ++i)
2118  {
2119  libmesh_assert_not_equal_to
2120  (node->dof_number(sys_num,v,i),
2122  di.push_back(node->dof_number(sys_num,v,i));
2123  }
2124  }
2125  }
2126 }
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:1689
const unsigned int n_vars
Definition: tecplot_io.C:68
static const dof_id_type invalid_id
Definition: dof_object.h:324
unsigned int sys_number() const
Definition: dof_map.h:1671
unsigned int n_variables() const
Definition: dof_map.h:486
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Definition: dof_map.C:2295
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 2129 of file dof_map.C.

References dof_indices(), libMesh::DofObject::dof_number(), libMesh::FEType::family, libMesh::DofObject::invalid_id, libMesh::invalid_uint, libMesh::DofObject::n_comp(), libMesh::SCALAR, SCALAR_dof_indices(), sys_number(), libMesh::Variable::type(), and variable().

2132 {
2133  if (vn == libMesh::invalid_uint)
2134  {
2135  this->dof_indices(node, di);
2136  return;
2137  }
2138 
2139  // We allow node==NULL to request just SCALAR dofs
2140  // libmesh_assert(elem);
2141 
2142  LOG_SCOPE("dof_indices(Node)", "DofMap");
2143 
2144  // Clear the DOF indices vector
2145  di.clear();
2146 
2147  const unsigned int sys_num = this->sys_number();
2148 
2149  // Get the dof numbers
2150  const Variable & var = this->variable(vn);
2151  if (var.type().family == SCALAR)
2152  {
2153  std::vector<dof_id_type> di_new;
2154  this->SCALAR_dof_indices(di_new,vn);
2155  di.insert( di.end(), di_new.begin(), di_new.end());
2156  }
2157  else
2158  {
2159  const int n_comp = node->n_comp(sys_num,vn);
2160  for (int i=0; i != n_comp; ++i)
2161  {
2162  libmesh_assert_not_equal_to
2163  (node->dof_number(sys_num,vn,i),
2165  di.push_back(node->dof_number(sys_num,vn,i));
2166  }
2167  }
2168 }
const unsigned int invalid_uint
Definition: libmesh.h:184
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:1689
static const dof_id_type invalid_id
Definition: dof_object.h:324
unsigned int sys_number() const
Definition: dof_map.h:1671
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Definition: dof_map.C:2295
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition: dof_map.C:1924
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 595 of file dof_map.h.

596  { std::vector<dof_id_type>::const_iterator ub =
597  std::upper_bound(_end_df.begin(), _end_df.end(), dof);
598  libmesh_assert (ub != _end_df.end());
599  return (ub - _end_df.begin());
600  }
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1462
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 304 of file dof_map.C.

References libMesh::MeshBase::elem_ptr().

Referenced by distribute_dofs().

305 {
306  return mesh.elem_ptr(i);
307 }
MeshBase & mesh
void libMesh::ReferenceCounter::enable_print_counter_info ( )
staticinherited

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

Definition at line 101 of file reference_counter.C.

References libMesh::ReferenceCounter::_enable_print_counter.

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

102 {
103  _enable_print_counter = true;
104  return;
105 }
dof_id_type libMesh::DofMap::end_dof ( const processor_id_type  proc) const
inline
dof_id_type libMesh::DofMap::end_dof ( ) const
inline

Definition at line 589 of file dof_map.h.

References libMesh::processor_id().

Referenced by add_neighbors_to_send_list(), distribute_dofs(), get_info(), local_variable_indices(), and semilocal_index().

590  { return this->end_dof(this->processor_id()); }
dof_id_type end_dof() const
Definition: dof_map.h:589
processor_id_type processor_id() const
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 609 of file dof_map.h.

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

610  { 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:1599
dof_id_type libMesh::DofMap::end_old_dof ( ) const
inline

Definition at line 612 of file dof_map.h.

References libMesh::MeshTools::Generation::Private::idx(), libMesh::invalid_uint, and libMesh::processor_id().

613  { return this->end_old_dof(this->processor_id()); }
dof_id_type end_old_dof() const
Definition: dof_map.h:612
processor_id_type processor_id() const
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 2178 of file dof_map_constraints.C.

References libMesh::NumericVector< T >::close(), libMesh::NumericVector< T >::closed(), libMesh::NumericVector< T >::get(), libMesh::GHOSTED, libmesh_nullptr, 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(), libMesh::AdjointRefinementEstimator::estimate_error(), and get_primal_constraint_values().

2180 {
2181  parallel_object_only();
2182 
2183  if (!this->n_constrained_dofs())
2184  return;
2185 
2186  LOG_SCOPE("enforce_adjoint_constraints_exactly()", "DofMap");
2187 
2188  NumericVector<Number> * v_local = libmesh_nullptr; // will be initialized below
2189  NumericVector<Number> * v_global = libmesh_nullptr; // will be initialized below
2190  std::unique_ptr<NumericVector<Number>> v_built;
2191  if (v.type() == SERIAL)
2192  {
2193  v_built = NumericVector<Number>::build(this->comm());
2194  v_built->init(this->n_dofs(), this->n_local_dofs(), true, PARALLEL);
2195  v_built->close();
2196 
2197  for (dof_id_type i=v_built->first_local_index();
2198  i<v_built->last_local_index(); i++)
2199  v_built->set(i, v(i));
2200  v_built->close();
2201  v_global = v_built.get();
2202 
2203  v_local = &v;
2204  libmesh_assert (v_local->closed());
2205  }
2206  else if (v.type() == PARALLEL)
2207  {
2208  v_built = NumericVector<Number>::build(this->comm());
2209  v_built->init (v.size(), v.size(), true, SERIAL);
2210  v.localize(*v_built);
2211  v_built->close();
2212  v_local = v_built.get();
2213 
2214  v_global = &v;
2215  }
2216  else if (v.type() == GHOSTED)
2217  {
2218  v_local = &v;
2219  v_global = &v;
2220  }
2221  else // unknown v.type()
2222  libmesh_error_msg("ERROR: Unknown v.type() == " << v.type());
2223 
2224  // We should never hit these asserts because we should error-out in
2225  // else clause above. Just to be sure we don't try to use v_local
2226  // and v_global uninitialized...
2227  libmesh_assert(v_local);
2228  libmesh_assert(v_global);
2229 
2230  // Do we have any non_homogeneous constraints?
2231  const AdjointDofConstraintValues::const_iterator
2232  adjoint_constraint_map_it = _adjoint_constraint_values.find(q);
2233  const DofConstraintValueMap * constraint_map =
2234  (adjoint_constraint_map_it == _adjoint_constraint_values.end()) ?
2235  libmesh_nullptr : &adjoint_constraint_map_it->second;
2236 
2237  DofConstraints::const_iterator c_it = _dof_constraints.begin();
2238  const DofConstraints::const_iterator c_end = _dof_constraints.end();
2239 
2240  for ( ; c_it != c_end; ++c_it)
2241  {
2242  dof_id_type constrained_dof = c_it->first;
2243  if (constrained_dof < this->first_dof() ||
2244  constrained_dof >= this->end_dof())
2245  continue;
2246 
2247  const DofConstraintRow constraint_row = c_it->second;
2248 
2249  Number exact_value = 0;
2250  if (constraint_map)
2251  {
2252  const DofConstraintValueMap::const_iterator
2253  adjoint_constraint_it =
2254  constraint_map->find(constrained_dof);
2255  if (adjoint_constraint_it != constraint_map->end())
2256  exact_value = adjoint_constraint_it->second;
2257  }
2258 
2259  for (DofConstraintRow::const_iterator
2260  j=constraint_row.begin(); j != constraint_row.end();
2261  ++j)
2262  exact_value += j->second * (*v_local)(j->first);
2263 
2264  v_global->set(constrained_dof, exact_value);
2265  }
2266 
2267  // If the old vector was serial, we probably need to send our values
2268  // to other processors
2269  if (v.type() == SERIAL)
2270  {
2271 #ifndef NDEBUG
2272  v_global->close();
2273 #endif
2274  v_global->localize (v);
2275  }
2276  v.close();
2277 }
virtual bool closed() const
virtual numeric_index_type size() const =0
dof_id_type n_constrained_dofs() const
const class libmesh_nullptr_t libmesh_nullptr
dof_id_type n_dofs() const
Definition: dof_map.h:519
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1618
DofConstraints _dof_constraints
Definition: dof_map.h:1614
virtual void close()=0
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package())
dof_id_type end_dof() const
Definition: dof_map.h:589
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
const Parallel::Communicator & comm() const
dof_id_type n_local_dofs() const
Definition: dof_map.h:529
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:89
ParallelType type() const
virtual void set(const numeric_index_type i, const T value)=0
virtual void localize(std::vector< T > &v_local) const =0
dof_id_type first_dof() const
Definition: dof_map.h:547
uint8_t dof_id_type
Definition: id_types.h:64
void libMesh::DofMap::enforce_constraints_exactly ( const System system,
NumericVector< Number > *  v = libmesh_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 == libmesh_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 2079 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_nullptr, 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::__libmesh_petsc_snes_postcheck(), libMesh::Problem_Interface::computeF(), libMesh::Problem_Interface::computeJacobian(), libMesh::Problem_Interface::computePreconditioner(), DMlibMeshFunction(), DMlibMeshJacobian(), get_primal_constraint_values(), libMesh::ImplicitSystem::sensitivity_solve(), libMesh::NewtonSolver::solve(), libMesh::PetscDiffSolver::solve(), libMesh::PetscNonlinearSolver< T >::solve(), libMesh::ImplicitSystem::weighted_sensitivity_adjoint_solve(), and libMesh::ImplicitSystem::weighted_sensitivity_solve().

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

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

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 2568 of file dof_map.C.

References _dof_constraints, and is_constrained_dof().

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

2569 {
2570  typedef std::set<dof_id_type> RCSet;
2571 
2572  // First insert the DOFS we already depend on into the set.
2573  RCSet dof_set (elem_dofs.begin(), elem_dofs.end());
2574 
2575  bool done = true;
2576 
2577  // Next insert any dofs those might be constrained in terms
2578  // of. Note that in this case we may not be done: Those may
2579  // in turn depend on others. So, we need to repeat this process
2580  // in that case until the system depends only on unconstrained
2581  // degrees of freedom.
2582  for (std::size_t i=0; i<elem_dofs.size(); i++)
2583  if (this->is_constrained_dof(elem_dofs[i]))
2584  {
2585  // If the DOF is constrained
2586  DofConstraints::const_iterator
2587  pos = _dof_constraints.find(elem_dofs[i]);
2588 
2589  libmesh_assert (pos != _dof_constraints.end());
2590 
2591  const DofConstraintRow & constraint_row = pos->second;
2592 
2593  // adaptive p refinement currently gives us lots of empty constraint
2594  // rows - we should optimize those DoFs away in the future. [RHS]
2595  //libmesh_assert (!constraint_row.empty());
2596 
2597  DofConstraintRow::const_iterator it = constraint_row.begin();
2598  DofConstraintRow::const_iterator it_end = constraint_row.end();
2599 
2600 
2601  // Add the DOFs this dof is constrained in terms of.
2602  // note that these dofs might also be constrained, so
2603  // we will need to call this function recursively.
2604  for ( ; it != it_end; ++it)
2605  if (!dof_set.count (it->first))
2606  {
2607  dof_set.insert (it->first);
2608  done = false;
2609  }
2610  }
2611 
2612 
2613  // If not done then we need to do more work
2614  // (obviously :-) )!
2615  if (!done)
2616  {
2617  // Fill the vector with the contents of the set
2618  elem_dofs.clear();
2619  elem_dofs.insert (elem_dofs.end(),
2620  dof_set.begin(), dof_set.end());
2621 
2622 
2623  // May need to do this recursively. It is possible
2624  // that we just replaced a constrained DOF with another
2625  // constrained DOF.
2626  this->find_connected_dofs (elem_dofs);
2627 
2628  } // end if (!done)
2629 }
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1756
DofConstraints _dof_constraints
Definition: dof_map.h:1614
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:89
void find_connected_dofs(std::vector< dof_id_type > &elem_dofs) const
Definition: dof_map.C:2568
dof_id_type libMesh::DofMap::first_dof ( ) const
inline

Definition at line 547 of file dof_map.h.

References libMesh::processor_id().

Referenced by add_neighbors_to_send_list(), distribute_dofs(), get_info(), local_variable_indices(), and semilocal_index().

548  { return this->first_dof(this->processor_id()); }
dof_id_type first_dof() const
Definition: dof_map.h:547
processor_id_type processor_id() const
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 554 of file dof_map.h.

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

555  { 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:1594
dof_id_type libMesh::DofMap::first_old_dof ( ) const
inline

Definition at line 557 of file dof_map.h.

References libMesh::processor_id().

558  { return this->first_old_dof(this->processor_id()); }
dof_id_type first_old_dof() const
Definition: dof_map.h:557
processor_id_type processor_id() const
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 3809 of file dof_map_constraints.C.

References libMesh::libmesh_isnan(), libMesh::n_processors(), and libMesh::processor_id().

3812 {
3813  typedef std::set<dof_id_type> DoF_RCSet;
3814 
3815  // If we have heterogenous adjoint constraints we need to
3816  // communicate those too.
3817  const unsigned int max_qoi_num =
3818  _adjoint_constraint_values.empty() ?
3819  0 : _adjoint_constraint_values.rbegin()->first;
3820 
3821  // We have to keep recursing while the unexpanded set is
3822  // nonempty on *any* processor
3823  bool unexpanded_set_nonempty = !unexpanded_dofs.empty();
3824  this->comm().max(unexpanded_set_nonempty);
3825 
3826  while (unexpanded_set_nonempty)
3827  {
3828  // Let's make sure we don't lose sync in this loop.
3829  parallel_object_only();
3830 
3831  // Request sets
3832  DoF_RCSet dof_request_set;
3833 
3834  // Request sets to send to each processor
3835  std::vector<std::vector<dof_id_type>>
3836  requested_dof_ids(this->n_processors());
3837 
3838  // And the sizes of each
3839  std::vector<dof_id_type>
3840  dof_ids_on_proc(this->n_processors(), 0);
3841 
3842  // Fill (and thereby sort and uniq!) the main request sets
3843  for (DoF_RCSet::iterator i = unexpanded_dofs.begin();
3844  i != unexpanded_dofs.end(); ++i)
3845  {
3846  const dof_id_type unexpanded_dof = *i;
3847  DofConstraints::const_iterator
3848  pos = _dof_constraints.find(unexpanded_dof);
3849 
3850  // If we were asked for a DoF and we don't already have a
3851  // constraint for it, then we need to check for one.
3852  if (pos == _dof_constraints.end())
3853  {
3854  if (((unexpanded_dof < this->first_dof()) ||
3855  (unexpanded_dof >= this->end_dof())) &&
3856  !