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)
 
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
 
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 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 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 *const 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
 
UniquePtr< 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

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
 
UniquePtr< DefaultCoupling_default_coupling
 
UniquePtr< DefaultCoupling_default_evaluating
 
std::set< GhostingFunctor * > _algebraic_ghosting_functors
 
std::set< GhostingFunctor * > _coupling_functors
 
bool need_full_sparsity_pattern
 
UniquePtr< 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
 
UniquePtr< PeriodicBoundaries_periodic_boundaries
 
UniquePtr< 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 167 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 110 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 1262 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()),
131  _variables(),
133  _sys_number(number),
134  _mesh(mesh),
135  _matrices(),
136  _first_df(),
137  _end_df(),
139  _send_list(),
146  _default_coupling(new DefaultCoupling()),
147  _default_evaluating(new DefaultCoupling()),
151  _n_dfs(0),
152  _n_SCALAR_dofs(0)
153 #ifdef LIBMESH_ENABLE_AMR
154  , _n_old_dfs(0),
155  _first_old_df(),
156  _end_old_df(),
158 #endif
159 #ifdef LIBMESH_ENABLE_CONSTRAINTS
160  , _dof_constraints()
164 #endif
165 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
167 #endif
168 #ifdef LIBMESH_ENABLE_PERIODIC
169  , _periodic_boundaries(new PeriodicBoundaries)
170 #endif
171 #ifdef LIBMESH_ENABLE_DIRICHLET
172  , _dirichlet_boundaries(new DirichletBoundaries)
174 #endif
177 {
178  _matrices.clear();
179 
180  _default_coupling->set_mesh(&_mesh);
181  _default_evaluating->set_mesh(&_mesh);
182  _default_evaluating->set_n_levels(1);
183 
184 #ifdef LIBMESH_ENABLE_PERIODIC
185  _default_coupling->set_periodic_boundaries(_periodic_boundaries.get());
186  _default_evaluating->set_periodic_boundaries(_periodic_boundaries.get());
187 #endif
188 
191 }
std::vector< VariableGroup > _variable_groups
Definition: dof_map.h:1384
ParallelObject(const Parallel::Communicator &comm_in)
bool _implicit_neighbor_dofs_initialized
Definition: dof_map.h:1612
const unsigned int _sys_number
Definition: dof_map.h:1389
bool _implicit_neighbor_dofs
Definition: dof_map.h:1613
UniquePtr< DefaultCoupling > _default_coupling
Definition: dof_map.h:1463
void * _extra_sparsity_context
Definition: dof_map.h:1440
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1423
MeshBase & mesh
AugmentSparsityPattern * _augment_sparsity_pattern
Definition: dof_map.h:1428
const class libmesh_nullptr_t libmesh_nullptr
std::vector< dof_id_type > _end_old_df
Definition: dof_map.h:1548
void add_coupling_functor(GhostingFunctor &coupling_functor)
Definition: dof_map.C:1898
UniquePtr< DefaultCoupling > _default_evaluating
Definition: dof_map.h:1471
std::vector< dof_id_type > _first_old_df
Definition: dof_map.h:1543
std::vector< dof_id_type > _first_scalar_df
Definition: dof_map.h:1417
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1567
std::vector< dof_id_type > * _n_nz
Definition: dof_map.h:1514
AugmentSendList * _augment_send_list
Definition: dof_map.h:1445
std::vector< dof_id_type > * _n_oz
Definition: dof_map.h:1520
bool need_full_sparsity_pattern
Definition: dof_map.h:1500
void add_algebraic_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: dof_map.C:1917
std::vector< dof_id_type > _first_old_scalar_df
Definition: dof_map.h:1554
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:1433
dof_id_type _n_SCALAR_dofs
Definition: dof_map.h:1531
DofConstraints _dof_constraints
Definition: dof_map.h:1563
CouplingMatrix * _dof_coupling
Definition: dof_map.h:1210
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1603
void * _extra_send_list_context
Definition: dof_map.h:1455
std::vector< SparseMatrix< Number > * > _matrices
Definition: dof_map.h:1401
UniquePtr< DirichletBoundaries > _dirichlet_boundaries
Definition: dof_map.h:1597
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1565
std::vector< Variable > _variables
Definition: dof_map.h:1379
DofConstraints _stashed_dof_constraints
Definition: dof_map.h:1563
dof_id_type _n_old_dfs
Definition: dof_map.h:1538
UniquePtr< PeriodicBoundaries > _periodic_boundaries
Definition: dof_map.h:1583
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1411
std::vector< dof_id_type > _first_df
Definition: dof_map.h:1406
void(* _extra_send_list_function)(std::vector< dof_id_type > &, void *)
Definition: dof_map.h:1450
MeshBase & _mesh
Definition: dof_map.h:1394
dof_id_type _n_dfs
Definition: dof_map.h:1525
NodeConstraints _node_constraints
Definition: dof_map.h:1574
libMesh::DofMap::~DofMap ( )

Destructor.

Definition at line 196 of file dof_map.C.

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

197 {
198  this->clear();
199 
200  // clear() resets all but the default DofMap-based functors. We
201  // need to remove those from the mesh too before we die.
204 
205 #ifdef LIBMESH_ENABLE_DIRICHLET
206  for (std::size_t q = 0; q != _adjoint_dirichlet_boundaries.size(); ++q)
208 #endif
209 }
UniquePtr< DefaultCoupling > _default_coupling
Definition: dof_map.h:1463
void remove_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: mesh_base.C:303
UniquePtr< DefaultCoupling > _default_evaluating
Definition: dof_map.h:1471
void clear()
Definition: dof_map.C:842
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1603
MeshBase & _mesh
Definition: dof_map.h:1394

Member Function Documentation

void libMesh::DofMap::_dof_indices ( const Elem *const  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 2267 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::DofObject::invalid_id, libMesh::Elem::is_vertex(), libMesh::LAGRANGE, libMesh::libmesh_assert(), libMesh::DofObject::n_comp(), libMesh::FEInterface::n_dofs(), libMesh::FEInterface::n_dofs_at_node(), 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().

2278 {
2279  // This internal function is only useful on valid elements
2280  libmesh_assert(elem);
2281 
2282  const Variable & var = this->variable(v);
2283 
2284  if (var.active_on_subdomain(elem->subdomain_id()))
2285  {
2286  const ElemType type = elem->type();
2287  const unsigned int sys_num = this->sys_number();
2288  const unsigned int dim = elem->dim();
2289 
2290  // Increase the polynomial order on p refined elements
2291  FEType fe_type = var.type();
2292  fe_type.order = static_cast<Order>(fe_type.order + p_level);
2293 
2294  const bool extra_hanging_dofs =
2296 
2297 #ifdef DEBUG
2298  // The number of dofs per element is non-static for subdivision FE
2299  if (fe_type.family == SUBDIVISION)
2300  tot_size += n_nodes;
2301  else
2302  tot_size += FEInterface::n_dofs(dim,fe_type,type);
2303 #endif
2304 
2305  // Get the node-based DOF numbers
2306  for (unsigned int n=0; n<n_nodes; n++)
2307  {
2308  const Node * node = nodes[n];
2309 
2310  // There is a potential problem with h refinement. Imagine a
2311  // quad9 that has a linear FE on it. Then, on the hanging side,
2312  // it can falsely identify a DOF at the mid-edge node. This is why
2313  // we call FEInterface instead of node->n_comp() directly.
2314  const unsigned int nc = FEInterface::n_dofs_at_node (dim,
2315  fe_type,
2316  type,
2317  n);
2318 
2319  // If this is a non-vertex on a hanging node with extra
2320  // degrees of freedom, we use the non-vertex dofs (which
2321  // come in reverse order starting from the end, to
2322  // simplify p refinement)
2323  if (extra_hanging_dofs && !elem->is_vertex(n))
2324  {
2325  const int dof_offset = node->n_comp(sys_num,v) - nc;
2326 
2327  // We should never have fewer dofs than necessary on a
2328  // node unless we're getting indices on a parent element,
2329  // and we should never need the indices on such a node
2330  if (dof_offset < 0)
2331  {
2332  libmesh_assert(!elem->active());
2333  di.resize(di.size() + nc, DofObject::invalid_id);
2334  }
2335  else
2336  for (int i=node->n_comp(sys_num,v)-1; i>=dof_offset; i--)
2337  {
2338  libmesh_assert_not_equal_to (node->dof_number(sys_num,v,i),
2340  di.push_back(node->dof_number(sys_num,v,i));
2341  }
2342  }
2343  // If this is a vertex or an element without extra hanging
2344  // dofs, our dofs come in forward order coming from the
2345  // beginning
2346  else
2347  for (unsigned int i=0; i<nc; i++)
2348  {
2349  libmesh_assert_not_equal_to (node->dof_number(sys_num,v,i),
2351  di.push_back(node->dof_number(sys_num,v,i));
2352  }
2353  }
2354 
2355  // If there are any element-based DOF numbers, get them
2356  const unsigned int nc = FEInterface::n_dofs_per_elem(dim,
2357  fe_type,
2358  type);
2359  // We should never have fewer dofs than necessary on an
2360  // element unless we're getting indices on a parent element,
2361  // and we should never need those indices
2362  if (nc != 0)
2363  {
2364  if (elem->n_systems() > sys_num &&
2365  nc <= elem->n_comp(sys_num,v))
2366  {
2367  for (unsigned int i=0; i<nc; i++)
2368  {
2369  libmesh_assert_not_equal_to (elem->dof_number(sys_num,v,i),
2371 
2372  di.push_back(elem->dof_number(sys_num,v,i));
2373  }
2374  }
2375  else
2376  {
2377  libmesh_assert(!elem->active() || fe_type.family == LAGRANGE || fe_type.family == SUBDIVISION);
2378  di.resize(di.size() + nc, DofObject::invalid_id);
2379  }
2380  }
2381  }
2382 }
static unsigned int n_dofs_per_elem(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:460
static unsigned int n_dofs(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:414
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:1638
libmesh_assert(j)
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:335
unsigned int sys_number() const
Definition: dof_map.h:1620
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:436
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 1364 of file dof_map_constraints.C.

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

4070 {
4071  unsigned int old_size = cast_int<unsigned int>
4073  for (unsigned int i = old_size; i <= qoi_index; ++i)
4075 
4076  _adjoint_dirichlet_boundaries[qoi_index]->push_back
4077  (new DirichletBoundary(dirichlet_boundary));
4078 }
Class for specifying Dirichlet boundary conditions as constraints.
std::vector< DirichletBoundaries * > _adjoint_dirichlet_boundaries
Definition: dof_map.h:1603
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 1917 of file dof_map.C.

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

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

1918 {
1919  _algebraic_ghosting_functors.insert(&algebraic_ghosting_functor);
1920  _mesh.add_ghosting_functor(algebraic_ghosting_functor);
1921 }
std::set< GhostingFunctor * > _algebraic_ghosting_functors
Definition: dof_map.h:1481
MeshBase & _mesh
Definition: dof_map.h:1394
void add_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: mesh_base.h:743
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 1341 of file dof_map_constraints.C.

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

788  { 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 3947 of file dof_map_constraints.C.

References libMesh::n_processors().

3948 {
3949  // This function must be run on all processors at once
3950  parallel_object_only();
3951 
3952  // Return immediately if there's nothing to gather
3953  if (this->n_processors() == 1)
3954  return;
3955 
3956  // We might get to return immediately if none of the processors
3957  // found any constraints
3958  unsigned int has_constraints = !_dof_constraints.empty();
3959  this->comm().max(has_constraints);
3960  if (!has_constraints)
3961  return;
3962 
3963  for (DofConstraints::iterator i = _dof_constraints.begin();
3964  i != _dof_constraints.end(); ++i)
3965  {
3966  dof_id_type constrained_dof = i->first;
3967 
3968  // We only need the dependencies of our own constrained dofs
3969  if (constrained_dof < this->first_dof() ||
3970  constrained_dof >= this->end_dof())
3971  continue;
3972 
3973  DofConstraintRow & constraint_row = i->second;
3974  for (DofConstraintRow::const_iterator
3975  j=constraint_row.begin(); j != constraint_row.end();
3976  ++j)
3977  {
3978  dof_id_type constraint_dependency = j->first;
3979 
3980  // No point in adding one of our own dofs to the send_list
3981  if (constraint_dependency >= this->first_dof() &&
3982  constraint_dependency < this->end_dof())
3983  continue;
3984 
3985  _send_list.push_back(constraint_dependency);
3986  }
3987  }
3988 }
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1423
processor_id_type n_processors() const
DofConstraints _dof_constraints
Definition: dof_map.h:1563
dof_id_type end_dof() const
Definition: dof_map.h:572
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:88
dof_id_type first_dof() const
Definition: dof_map.h:534
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 1898 of file dof_map.C.

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

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

1899 {
1900  _coupling_functors.insert(&coupling_functor);
1901  _mesh.add_ghosting_functor(coupling_functor);
1902 }
std::set< GhostingFunctor * > _coupling_functors
Definition: dof_map.h:1494
MeshBase & _mesh
Definition: dof_map.h:1394
void add_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: mesh_base.h:743
void libMesh::DofMap::add_dirichlet_boundary ( const DirichletBoundary dirichlet_boundary)

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

Definition at line 4062 of file dof_map_constraints.C.

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

4063 {
4064  _dirichlet_boundaries->push_back(new DirichletBoundary(dirichlet_boundary));
4065 }
Class for specifying Dirichlet boundary conditions as constraints.
UniquePtr< DirichletBoundaries > _dirichlet_boundaries
Definition: dof_map.h:1597
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 1574 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().

1575 {
1576  LOG_SCOPE("add_neighbors_to_send_list()", "DofMap");
1577 
1578  const unsigned int n_var = this->n_variables();
1579 
1580  MeshBase::const_element_iterator local_elem_it
1581  = mesh.active_local_elements_begin();
1582  const MeshBase::const_element_iterator local_elem_end
1583  = mesh.active_local_elements_end();
1584 
1585  GhostingFunctor::map_type elements_to_send;
1586 
1587  // Man, I wish we had guaranteed unique_ptr availability...
1588  std::set<CouplingMatrix*> temporary_coupling_matrices;
1589 
1590  // We need to add dofs to the send list if they've been directly
1591  // requested by an algebraic ghosting functor or they've been
1592  // indirectly requested by a coupling functor.
1594  (elements_to_send,
1595  temporary_coupling_matrices,
1598  local_elem_it, local_elem_end, mesh.processor_id());
1599 
1601  (elements_to_send,
1602  temporary_coupling_matrices,
1603  this->coupling_functors_begin(),
1604  this->coupling_functors_end(),
1605  local_elem_it, local_elem_end, mesh.processor_id());
1606 
1607  // Making a list of non-zero coupling matrix columns is an
1608  // O(N_var^2) operation. We cache it so we only have to do it once
1609  // per CouplingMatrix and not once per element.
1610  std::map<const CouplingMatrix*, std::vector<unsigned int> >
1611  column_variable_lists;
1612 
1613  GhostingFunctor::map_type::iterator etg_it = elements_to_send.begin();
1614  const GhostingFunctor::map_type::iterator etg_end = elements_to_send.end();
1615  for (; etg_it != etg_end; ++etg_it)
1616  {
1617  const Elem * const partner = etg_it->first;
1618 
1619  // We asked ghosting functors not to give us local elements
1620  libmesh_assert_not_equal_to
1621  (partner->processor_id(), this->processor_id());
1622 
1623  const CouplingMatrix *ghost_coupling = etg_it->second;
1624 
1625  // Loop over any present coupling matrix column variables if we
1626  // have a coupling matrix, or just add all variables to
1627  // send_list if not.
1628  if (ghost_coupling)
1629  {
1630  libmesh_assert_equal_to (ghost_coupling->size(), n_var);
1631 
1632  // Try to find a cached list of column variables.
1633  std::map<const CouplingMatrix*,
1634  std::vector<unsigned int> >::const_iterator
1635  column_variable_list =
1636  column_variable_lists.find(ghost_coupling);
1637 
1638  // If we didn't find it, then we need to create it.
1639  if (column_variable_list == column_variable_lists.end())
1640  {
1641  std::pair<
1642  std::map<const CouplingMatrix*,
1643  std::vector<unsigned int> >::iterator,
1644  bool>
1645  inserted_variable_list_pair =
1646  column_variable_lists.insert
1647  (std::pair<const CouplingMatrix*,
1648  std::vector<unsigned int> >
1649  (ghost_coupling, std::vector<unsigned int>()));
1650  column_variable_list = inserted_variable_list_pair.first;
1651 
1652  std::vector<unsigned int> & new_variable_list =
1653  inserted_variable_list_pair.first->second;
1654 
1655  std::vector<unsigned char> has_variable(n_var, false);
1656 
1657  for (unsigned int vi = 0; vi != n_var; ++vi)
1658  {
1659  ConstCouplingRow ccr(vi, *ghost_coupling);
1660 
1661  for (ConstCouplingRow::const_iterator it = ccr.begin(),
1662  end = ccr.end();
1663  it != end; ++it)
1664  {
1665  const unsigned int vj = *it;
1666  has_variable[vj] = true;
1667  }
1668  }
1669  for (unsigned int vj = 0; vj != n_var; ++vj)
1670  {
1671  if (has_variable[vj])
1672  new_variable_list.push_back(vj);
1673  }
1674  }
1675 
1676  const std::vector<unsigned int> & variable_list =
1677  column_variable_list->second;
1678 
1679  for (std::size_t j=0; j != variable_list.size(); ++j)
1680  {
1681  const unsigned int vj=variable_list[j];
1682 
1683  std::vector<dof_id_type> di;
1684  this->dof_indices (partner, di, vj);
1685 
1686  // Insert the remote DOF indices into the send list
1687  for (std::size_t j=0; j != di.size(); ++j)
1688  if (di[j] < this->first_dof() ||
1689  di[j] >= this->end_dof())
1690  _send_list.push_back(di[j]);
1691  }
1692  }
1693  else
1694  {
1695  std::vector<dof_id_type> di;
1696  this->dof_indices (partner, di);
1697 
1698  // Insert the remote DOF indices into the send list
1699  for (std::size_t j=0; j != di.size(); ++j)
1700  if (di[j] < this->first_dof() ||
1701  di[j] >= this->end_dof())
1702  _send_list.push_back(di[j]);
1703  }
1704 
1705  }
1706 
1707  // We're now done with any merged coupling matrices we had to create.
1708  for (std::set<CouplingMatrix*>::iterator
1709  it = temporary_coupling_matrices.begin(),
1710  end = temporary_coupling_matrices.begin();
1711  it != end; ++it)
1712  delete *it;
1713 
1714  //-------------------------------------------------------------------------
1715  // Our coupling functors added dofs from neighboring elements to the
1716  // send list, but we may still need to add non-local dofs from local
1717  // elements.
1718  //-------------------------------------------------------------------------
1719 
1720  // Loop over the active local elements, adding all active elements
1721  // that neighbor an active local element to the send list.
1722  for ( ; local_elem_it != local_elem_end; ++local_elem_it)
1723  {
1724  const Elem * elem = *local_elem_it;
1725 
1726  std::vector<dof_id_type> di;
1727  this->dof_indices (elem, di);
1728 
1729  // Insert the remote DOF indices into the send list
1730  for (std::size_t j=0; j != di.size(); ++j)
1731  if (di[j] < this->first_dof() ||
1732  di[j] >= this->end_dof())
1733  _send_list.push_back(di[j]);
1734  }
1735 }
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_begin() const
Definition: dof_map.h:311
LIBMESH_BEST_UNORDERED_MAP< const Elem *, const CouplingMatrix * > map_type
std::set< GhostingFunctor * >::const_iterator coupling_functors_begin() const
Definition: dof_map.h:275
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1423
MeshBase & mesh
IterBase * end
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:1499
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_end() const
Definition: dof_map.h:317
dof_id_type end_dof() const
Definition: dof_map.h:572
unsigned int n_variables() const
Definition: dof_map.h:473
std::set< GhostingFunctor * >::const_iterator coupling_functors_end() const
Definition: dof_map.h:281
ConstCouplingRowConstIterator const_iterator
dof_id_type first_dof() const
Definition: dof_map.h:534
processor_id_type processor_id() const
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition: dof_map.C:2022
void libMesh::DofMap::add_periodic_boundary ( const PeriodicBoundaryBase periodic_boundary)

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

Definition at line 4196 of file dof_map_constraints.C.

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

4197 {
4198  // See if we already have a periodic boundary associated myboundary...
4199  PeriodicBoundaryBase * existing_boundary = _periodic_boundaries->boundary(periodic_boundary.myboundary);
4200 
4201  if ( existing_boundary == libmesh_nullptr )
4202  {
4203  // ...if not, clone the input (and its inverse) and add them to the PeriodicBoundaries object
4204  PeriodicBoundaryBase * boundary = periodic_boundary.clone().release();
4205  PeriodicBoundaryBase * inverse_boundary = periodic_boundary.clone(PeriodicBoundaryBase::INVERSE).release();
4206 
4207  // _periodic_boundaries takes ownership of the pointers
4208  _periodic_boundaries->insert(std::make_pair(boundary->myboundary, boundary));
4209  _periodic_boundaries->insert(std::make_pair(inverse_boundary->myboundary, inverse_boundary));
4210  }
4211  else
4212  {
4213  // ...otherwise, merge this object's variable IDs with the existing boundary object's.
4214  existing_boundary->merge(periodic_boundary);
4215 
4216  // Do the same merging process for the inverse boundary. Note: the inverse better already exist!
4217  PeriodicBoundaryBase * inverse_boundary = _periodic_boundaries->boundary(periodic_boundary.pairedboundary);
4218  libmesh_assert(inverse_boundary);
4219  inverse_boundary->merge(periodic_boundary);
4220  }
4221 }
const class libmesh_nullptr_t libmesh_nullptr
libmesh_assert(j)
void merge(const PeriodicBoundaryBase &pb)
virtual UniquePtr< PeriodicBoundaryBase > clone(TransformationType t=FORWARD) const =0
UniquePtr< PeriodicBoundaries > _periodic_boundaries
Definition: dof_map.h:1583
Base class for all PeriodicBoundary implementations.
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 4226 of file dof_map_constraints.C.

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

4228 {
4229  libmesh_assert_equal_to (boundary.myboundary, inverse_boundary.pairedboundary);
4230  libmesh_assert_equal_to (boundary.pairedboundary, inverse_boundary.myboundary);
4231 
4232  // Allocate copies on the heap. The _periodic_boundaries object will manage this memory.
4233  // Note: this also means that the copy constructor for the PeriodicBoundary (or user class
4234  // derived therefrom) must be implemented!
4235  // PeriodicBoundary * p_boundary = new PeriodicBoundary(boundary);
4236  // PeriodicBoundary * p_inverse_boundary = new PeriodicBoundary(inverse_boundary);
4237 
4238  // We can't use normal copy construction since this leads to slicing with derived classes.
4239  // Use clone() "virtual constructor" instead. But, this *requires* user to override the clone()
4240  // method. Note also that clone() allocates memory. In this case, the _periodic_boundaries object
4241  // takes responsibility for cleanup.
4242  PeriodicBoundaryBase * p_boundary = boundary.clone().release();
4243  PeriodicBoundaryBase * p_inverse_boundary = inverse_boundary.clone().release();
4244 
4245  // Add the periodic boundary and its inverse to the PeriodicBoundaries data structure. The
4246  // PeriodicBoundaries data structure takes ownership of the pointers.
4247  _periodic_boundaries->insert(std::make_pair(p_boundary->myboundary, p_boundary));
4248  _periodic_boundaries->insert(std::make_pair(p_inverse_boundary->myboundary, p_inverse_boundary));
4249 }
virtual UniquePtr< PeriodicBoundaryBase > clone(TransformationType t=FORWARD) const =0
UniquePtr< PeriodicBoundaries > _periodic_boundaries
Definition: dof_map.h:1583
Base class for all PeriodicBoundary implementations.
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 234 of file dof_map.C.

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

235 {
236  _variable_groups.push_back(var_group);
237 
238  VariableGroup & new_var_group = _variable_groups.back();
239 
240  for (unsigned int var=0; var<new_var_group.n_variables(); var++)
241  _variables.push_back (new_var_group(var));
242 }
std::vector< VariableGroup > _variable_groups
Definition: dof_map.h:1384
std::vector< Variable > _variables
Definition: dof_map.h:1379
std::set<GhostingFunctor *>::const_iterator libMesh::DofMap::algebraic_ghosting_functors_begin ( ) const
inline

Beginning of range of algebraic ghosting functors

Definition at line 311 of file dof_map.h.

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

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

End of range of algebraic ghosting functors

Definition at line 317 of file dof_map.h.

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

318  { return _algebraic_ghosting_functors.end(); }
std::set< GhostingFunctor * > _algebraic_ghosting_functors
Definition: dof_map.h:1481
bool libMesh::DofMap::all_semilocal_indices ( const std::vector< dof_id_type > &  dof_indices) const

Returns true iff all degree of freedom indices in dof_indices are either local indices or in the send_list. Note that this is an O(logN) operation, not O(1); we don't cache enough information for O(1) right now.

Definition at line 2422 of file dof_map.C.

References _send_list, end_dof(), and first_dof().

2423 {
2424  // We're all semilocal unless we find a counterexample
2425  for (std::size_t i=0; i != dof_indices_in.size(); ++i)
2426  {
2427  const dof_id_type di = dof_indices_in[i];
2428  // If it's not in the local indices
2429  if (di < this->first_dof() ||
2430  di >= this->end_dof())
2431  {
2432  // and if it's not in the ghost indices, then we're not
2433  // semilocal
2434  if (!std::binary_search(_send_list.begin(), _send_list.end(), di))
2435  return false;
2436  }
2437  }
2438 
2439  return true;
2440 }
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1423
dof_id_type end_dof() const
Definition: dof_map.h:572
dof_id_type first_dof() const
Definition: dof_map.h:534
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 2619 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_assert(), libMesh::libmesh_isnan(), libmesh_nullptr, mesh, libMesh::DofObject::n_comp(), 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().

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

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

365  {
366  _augment_send_list = &asl;
367  }
AugmentSendList * _augment_send_list
Definition: dof_map.h:1445
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 350 of file dof_map.h.

void * _extra_sparsity_context
Definition: dof_map.h:1440
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:1433
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 335 of file dof_map.h.

336  {
338  }
AugmentSparsityPattern * _augment_sparsity_pattern
Definition: dof_map.h:1428
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 246 of file dof_map.C.

References _matrices, _n_nz, _n_oz, _sp, libMesh::SparseMatrix< T >::attach_dof_map(), libMesh::ParallelObject::comm(), libMesh::libmesh_assert(), 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().

247 {
248  parallel_object_only();
249 
250  // We shouldn't be trying to re-attach the same matrices repeatedly
251  libmesh_assert (std::find(_matrices.begin(), _matrices.end(),
252  &matrix) == _matrices.end());
253 
254  _matrices.push_back(&matrix);
255 
256  matrix.attach_dof_map (*this);
257 
258  // If we've already computed sparsity, then it's too late
259  // to wait for "compute_sparsity" to help with sparse matrix
260  // initialization, and we need to handle this matrix individually
261  bool computed_sparsity_already =
262  ((_n_nz && !_n_nz->empty()) ||
263  (_n_oz && !_n_oz->empty()));
264  this->comm().max(computed_sparsity_already);
265  if (computed_sparsity_already &&
267  {
268  // We'd better have already computed the full sparsity pattern
269  // if we need it here
271  libmesh_assert(_sp.get());
272 
273  matrix.update_sparsity_pattern (_sp->sparsity_pattern);
274  }
275 
276  if (matrix.need_full_sparsity_pattern())
278 }
libmesh_assert(j)
std::vector< dof_id_type > * _n_nz
Definition: dof_map.h:1514
std::vector< dof_id_type > * _n_oz
Definition: dof_map.h:1520
bool need_full_sparsity_pattern
Definition: dof_map.h:1500
UniquePtr< SparsityPattern::Build > _sp
Definition: dof_map.h:1506
virtual bool need_full_sparsity_pattern() const
std::vector< SparseMatrix< Number > * > _matrices
Definition: dof_map.h:1401
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 494 of file dof_map.h.

495  {
496 #ifdef LIBMESH_ENABLE_BLOCKED_STORAGE
497  return (this->has_blocked_representation() ? this->n_variables() : 1);
498 #else
499  return 1;
500 #endif
501  }
unsigned int n_variables() const
Definition: dof_map.h:473
bool has_blocked_representation() const
Definition: dof_map.h:481
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 2366 of file dof_map_constraints.C.

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

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

Definition at line 2478 of file dof_map_constraints.C.

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

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

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

4166 {
4167  const std::set<boundary_id_type>& mesh_bcids = mesh.get_boundary_info().get_boundary_ids();
4168  const std::set<boundary_id_type>& dbc_bcids = boundary.b;
4169 
4170  // DirichletBoundary id sets should be consistent across all ranks
4171  libmesh_assert(mesh.comm().verify(dbc_bcids.size()));
4172 
4173  for (std::set<boundary_id_type>::const_iterator bid = dbc_bcids.begin();
4174  bid != dbc_bcids.end(); ++bid)
4175  {
4176  // DirichletBoundary id sets should be consistent across all ranks
4177  libmesh_assert(mesh.comm().verify(*bid));
4178 
4179  bool found_bcid = (mesh_bcids.find(*bid) != mesh_bcids.end());
4180 
4181  // On a distributed mesh, boundary id sets may *not* be
4182  // consistent across all ranks, since not all ranks see all
4183  // boundaries
4184  mesh.comm().max(found_bcid);
4185 
4186  if (!found_bcid)
4187  libmesh_error_msg("Could not find Dirichlet boundary id " << *bid << " in mesh!");
4188  }
4189 }
const BoundaryInfo & get_boundary_info() const
Definition: mesh_base.h:111
const std::set< boundary_id_type > & get_boundary_ids() const
libmesh_assert(j)
const Parallel::Communicator & comm() const
std::set< boundary_id_type > b
void libMesh::DofMap::clear ( )

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

Definition at line 842 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(), libMesh::libmesh_assert(), need_full_sparsity_pattern, libMesh::MeshBase::remove_ghosting_functor(), and use_coupled_neighbor_dofs().

Referenced by ~DofMap().

843 {
844  // we don't want to clear
845  // the coupling matrix!
846  // It should not change...
847  //_dof_coupling->clear();
848  //
849  // But it would be inconsistent to leave our coupling settings
850  // through a clear()...
851  _dof_coupling = NULL;
852 
853  // Reset ghosting functor statuses
854  {
855  std::set<GhostingFunctor *>::iterator gf_it = this->coupling_functors_begin();
856  const std::set<GhostingFunctor *>::iterator gf_end = this->coupling_functors_end();
857  for (; gf_it != gf_end; ++gf_it)
858  {
859  GhostingFunctor *gf = *gf_it;
860  libmesh_assert(gf);
862  }
863  this->_coupling_functors.clear();
864 
865  // Go back to default coupling
866 
867  _default_coupling->set_dof_coupling(this->_dof_coupling);
868  _default_coupling->set_n_levels
869  (this->use_coupled_neighbor_dofs(this->_mesh));
870 
872  }
873 
874 
875  {
876  std::set<GhostingFunctor *>::iterator gf_it = this->algebraic_ghosting_functors_begin();
877  const std::set<GhostingFunctor *>::iterator gf_end = this->algebraic_ghosting_functors_end();
878  for (; gf_it != gf_end; ++gf_it)
879  {
880  GhostingFunctor *gf = *gf_it;
881  libmesh_assert(gf);
883  }
884  this->_algebraic_ghosting_functors.clear();
885 
886  // Go back to default send_list generation
887 
888  // _default_evaluating->set_dof_coupling(this->_dof_coupling);
889  _default_evaluating->set_n_levels(1);
891  }
892 
893  _variables.clear();
894  _variable_groups.clear();
895  _first_df.clear();
896  _end_df.clear();
897  _first_scalar_df.clear();
898  _send_list.clear();
899  this->clear_sparsity();
901 
902 #ifdef LIBMESH_ENABLE_AMR
903 
904  _dof_constraints.clear();
905  _stashed_dof_constraints.clear();
908  _n_old_dfs = 0;
909  _first_old_df.clear();
910  _end_old_df.clear();
911  _first_old_scalar_df.clear();
912 
913 #endif
914 
915  _matrices.clear();
916 
917  _n_dfs = 0;
918 }
std::vector< VariableGroup > _variable_groups
Definition: dof_map.h:1384
UniquePtr< DefaultCoupling > _default_coupling
Definition: dof_map.h:1463
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_begin() const
Definition: dof_map.h:311
std::set< GhostingFunctor * >::const_iterator coupling_functors_begin() const
Definition: dof_map.h:275
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1423
void remove_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: mesh_base.C:303
std::set< GhostingFunctor * > _algebraic_ghosting_functors
Definition: dof_map.h:1481
std::vector< dof_id_type > _end_old_df
Definition: dof_map.h:1548
void add_coupling_functor(GhostingFunctor &coupling_functor)
Definition: dof_map.C:1898
UniquePtr< DefaultCoupling > _default_evaluating
Definition: dof_map.h:1471
std::vector< dof_id_type > _first_old_df
Definition: dof_map.h:1543
std::vector< dof_id_type > _first_scalar_df
Definition: dof_map.h:1417
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:1567
libmesh_assert(j)
bool need_full_sparsity_pattern
Definition: dof_map.h:1500
void add_algebraic_ghosting_functor(GhostingFunctor &ghosting_functor)
Definition: dof_map.C:1917
std::vector< dof_id_type > _first_old_scalar_df
Definition: dof_map.h:1554
DofConstraints _dof_constraints
Definition: dof_map.h:1563
CouplingMatrix * _dof_coupling
Definition: dof_map.h:1210
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_end() const
Definition: dof_map.h:317
std::vector< SparseMatrix< Number > * > _matrices
Definition: dof_map.h:1401
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1565
std::vector< Variable > _variables
Definition: dof_map.h:1379
DofConstraints _stashed_dof_constraints
Definition: dof_map.h:1563
dof_id_type _n_old_dfs
Definition: dof_map.h:1538
void clear_sparsity()
Definition: dof_map.C:1876
std::set< GhostingFunctor * > _coupling_functors
Definition: dof_map.h:1494
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1411
std::vector< dof_id_type > _first_df
Definition: dof_map.h:1406
MeshBase & _mesh
Definition: dof_map.h:1394
std::set< GhostingFunctor * >::const_iterator coupling_functors_end() const
Definition: dof_map.h:281
bool use_coupled_neighbor_dofs(const MeshBase &mesh) const
Definition: dof_map.C:1782
dof_id_type _n_dfs
Definition: dof_map.h:1525
void libMesh::DofMap::clear_sparsity ( )

Clears the sparsity pattern

Definition at line 1876 of file dof_map.C.

References _n_nz, _n_oz, _sp, add_coupling_functor(), libMesh::libmesh_assert(), libmesh_nullptr, and need_full_sparsity_pattern.

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

1877 {
1879  {
1880  libmesh_assert(_sp.get());
1881  libmesh_assert(!_n_nz || _n_nz == &_sp->n_nz);
1882  libmesh_assert(!_n_oz || _n_oz == &_sp->n_oz);
1883  _sp.reset();
1884  }
1885  else
1886  {
1887  libmesh_assert(!_sp.get());
1888  delete _n_nz;
1889  delete _n_oz;
1890  }
1893 }
const class libmesh_nullptr_t libmesh_nullptr
libmesh_assert(j)
std::vector< dof_id_type > * _n_nz
Definition: dof_map.h:1514
std::vector< dof_id_type > * _n_oz
Definition: dof_map.h:1520
bool need_full_sparsity_pattern
Definition: dof_map.h:1500
UniquePtr< SparsityPattern::Build > _sp
Definition: dof_map.h:1506
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_monitor(), libMesh::__libmesh_petsc_diff_solver_residual(), libMesh::__libmesh_petsc_snes_jacobian(), 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::MeshTools::bounding_box(), 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::MeshTools::correct_node_proc_ids(), libMesh::MeshRefinement::create_parent_error_vector(), 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::PetscDiffSolver::init(), libMesh::TimeSolver::init(), libMesh::TopologyMap::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::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::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::MeshTools::processor_bounding_box(), libMesh::Nemesis_IO::read(), libMesh::XdrIO::read(), 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::DistributedMesh::renumber_dof_objects(), libMesh::MeshCommunication::send_coarse_ghosts(), libMesh::Partitioner::set_node_processor_ids(), set_nonlocal_dof_objects(), libMesh::Partitioner::set_parent_processor_ids(), libMesh::LaplaceMeshSmoother::smooth(), libMesh::Parallel::Sort< KeyType, IdxType >::sort(), libMesh::MeshTools::subdomain_bounding_box(), 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::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::LaspackVector< T >::zero_clone(), libMesh::EigenSparseVector< 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 1839 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().

1840 {
1841  _sp = this->build_sparsity(mesh);
1842 
1843  // It is possible that some \p SparseMatrix implementations want to
1844  // see it. Let them see it before we throw it away.
1845  std::vector<SparseMatrix<Number> *>::const_iterator
1846  pos = _matrices.begin(),
1847  end = _matrices.end();
1848 
1849  // If we need the full sparsity pattern, then we share a view of its
1850  // arrays, and we pass it in to the matrices.
1852  {
1853  _n_nz = &_sp->n_nz;
1854  _n_oz = &_sp->n_oz;
1855 
1856  for (; pos != end; ++pos)
1857  (*pos)->update_sparsity_pattern (_sp->sparsity_pattern);
1858  }
1859  // If we don't need the full sparsity pattern anymore, steal the
1860  // arrays we do need and free the rest of the memory
1861  else
1862  {
1863  if (!_n_nz)
1864  _n_nz = new std::vector<dof_id_type>();
1865  _n_nz->swap(_sp->n_nz);
1866  if (!_n_oz)
1867  _n_oz = new std::vector<dof_id_type>();
1868  _n_oz->swap(_sp->n_oz);
1869 
1870  _sp.reset();
1871  }
1872 }
MeshBase & mesh
IterBase * end
std::vector< dof_id_type > * _n_nz
Definition: dof_map.h:1514
std::vector< dof_id_type > * _n_oz
Definition: dof_map.h:1520
bool need_full_sparsity_pattern
Definition: dof_map.h:1500
UniquePtr< SparsityPattern::Build > _sp
Definition: dof_map.h:1506
UniquePtr< SparsityPattern::Build > build_sparsity(const MeshBase &mesh) const
Definition: dof_map.C:55
std::vector< SparseMatrix< Number > * > _matrices
Definition: dof_map.h:1401
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 2015 of file dof_map_constraints.C.

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

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

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

Referenced by get_primal_constraint_values().

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

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

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

References libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::libmesh_assert(), 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().

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

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

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

2065 {
2066  // check for easy return
2067  if (this->_dof_constraints.empty())
2068  return;
2069 
2070  // All the work is done by \p build_constraint_matrix. We just need
2071  // a dummy matrix.
2073  this->build_constraint_matrix (R, dofs);
2074 }
DofConstraints _dof_constraints
Definition: dof_map.h:1563
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 3997 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().

4001 {
4002  // We're constraining dofs on elem which correspond to p refinement
4003  // levels above p - this only makes sense if elem's p refinement
4004  // level is above p.
4005  libmesh_assert_greater (elem->p_level(), p);
4006  libmesh_assert_less (s, elem->n_sides());
4007 
4008  const unsigned int sys_num = this->sys_number();
4009  const unsigned int dim = elem->dim();
4010  ElemType type = elem->type();
4011  FEType low_p_fe_type = this->variable_type(var);
4012  FEType high_p_fe_type = this->variable_type(var);
4013  low_p_fe_type.order = static_cast<Order>(low_p_fe_type.order + p);
4014  high_p_fe_type.order = static_cast<Order>(high_p_fe_type.order +
4015  elem->p_level());
4016 
4017  const unsigned int n_nodes = elem->n_nodes();
4018  for (unsigned int n = 0; n != n_nodes; ++n)
4019  if (elem->is_node_on_side(n, s))
4020  {
4021  const Node & node = elem->node_ref(n);
4022  const unsigned int low_nc =
4023  FEInterface::n_dofs_at_node (dim, low_p_fe_type, type, n);
4024  const unsigned int high_nc =
4025  FEInterface::n_dofs_at_node (dim, high_p_fe_type, type, n);
4026 
4027  // since we may be running this method concurrently
4028  // on multiple threads we need to acquire a lock
4029  // before modifying the _dof_constraints object.
4030  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
4031 
4032  if (elem->is_vertex(n))
4033  {
4034  // Add "this is zero" constraint rows for high p vertex
4035  // dofs
4036  for (unsigned int i = low_nc; i != high_nc; ++i)
4037  {
4038  _dof_constraints[node.dof_number(sys_num,var,i)].clear();
4039  _primal_constraint_values.erase(node.dof_number(sys_num,var,i));
4040  }
4041  }
4042  else
4043  {
4044  const unsigned int total_dofs = node.n_comp(sys_num, var);
4045  libmesh_assert_greater_equal (total_dofs, high_nc);
4046  // Add "this is zero" constraint rows for high p
4047  // non-vertex dofs, which are numbered in reverse
4048  for (unsigned int j = low_nc; j != high_nc; ++j)
4049  {
4050  const unsigned int i = total_dofs - j - 1;
4051  _dof_constraints[node.dof_number(sys_num,var,i)].clear();
4052  _primal_constraint_values.erase(node.dof_number(sys_num,var,i));
4053  }
4054  }
4055  }
4056 }
Manages the family, order, etc. parameters for a given FE.
Definition: fe_type.h:178
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:2149
const FEType & variable_type(const unsigned int c) const
Definition: dof_map.h:1668
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:802
OrderWrapper order
Definition: fe_type.h:200
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:1680
DofConstraints _dof_constraints
Definition: dof_map.h:1563
virtual unsigned int n_sides() const =0
unsigned int sys_number() const
Definition: dof_map.h:1620
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:436
virtual bool is_vertex(const unsigned int i) const =0
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:1565
virtual unsigned int dim() const =0
unsigned int n_comp(const unsigned int s, const unsigned int var) const
Definition: dof_object.h:772
DofConstraints::const_iterator libMesh::DofMap::constraint_rows_begin ( ) const
inline

Returns an iterator pointing to the first DoF constraint row

Definition at line 793 of file dof_map.h.

794  { return _dof_constraints.begin(); }
DofConstraints _dof_constraints
Definition: dof_map.h:1563
DofConstraints::const_iterator libMesh::DofMap::constraint_rows_end ( ) const
inline

Returns an iterator pointing just past the last DoF constraint row

Definition at line 799 of file dof_map.h.

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

Beginning of range of coupling functors

Definition at line 275 of file dof_map.h.

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

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

End of range of coupling functors

Definition at line 281 of file dof_map.h.

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

282  { return _coupling_functors.end(); }
std::set< GhostingFunctor * > _coupling_functors
Definition: dof_map.h:1494
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 1184 of file dof_map_constraints.C.

References libMesh::StoredRange< iterator_type, object_type >::empty(), libMesh::MeshBase::is_prepared(), libMesh::MeshBase::is_serial(), libMesh::libmesh_assert(), 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().

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

Default algebraic ghosting functor

Definition at line 323 of file dof_map.h.

323 { return *_default_evaluating; }
UniquePtr< DefaultCoupling > _default_evaluating
Definition: dof_map.h:1471
DefaultCoupling& libMesh::DofMap::default_coupling ( )
inline

Default coupling functor

Definition at line 287 of file dof_map.h.

287 { return *_default_coupling; }
UniquePtr< DefaultCoupling > _default_coupling
Definition: dof_map.h:1463
void libMesh::ReferenceCounter::disable_print_counter_info ( )
staticinherited
void libMesh::DofMap::distribute_dofs ( MeshBase mesh)

Distrubute 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 922 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::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::libmesh_assert(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), mesh, libMesh::DofObject::n_comp(), n_dofs(), libMesh::ParallelObject::n_processors(), n_SCALAR_dofs(), n_variables(), libMesh::DofObject::n_vars(), node_ptr(), libMesh::MeshBase::nodes_begin(), libMesh::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().

923 {
924  // This function must be run on all processors at once
925  parallel_object_only();
926 
927  // Log how long it takes to distribute the degrees of freedom
928  LOG_SCOPE("distribute_dofs()", "DofMap");
929 
930  libmesh_assert (mesh.is_prepared());
931 
932  const processor_id_type proc_id = this->processor_id();
933  const processor_id_type n_proc = this->n_processors();
934 
935  // libmesh_assert_greater (this->n_variables(), 0);
936  libmesh_assert_less (proc_id, n_proc);
937 
938  // re-init in case the mesh has changed
939  this->reinit(mesh);
940 
941  // By default distribute variables in a
942  // var-major fashion, but allow run-time
943  // specification
944  bool node_major_dofs = libMesh::on_command_line ("--node_major_dofs");
945 
946  // The DOF counter, will be incremented as we encounter
947  // new degrees of freedom
948  dof_id_type next_free_dof = 0;
949 
950  // Clear the send list before we rebuild it
951  _send_list.clear();
952 
953  // Set temporary DOF indices on this processor
954  if (node_major_dofs)
955  this->distribute_local_dofs_node_major (next_free_dof, mesh);
956  else
957  this->distribute_local_dofs_var_major (next_free_dof, mesh);
958 
959  // Get DOF counts on all processors
960  std::vector<dof_id_type> dofs_on_proc(n_proc, 0);
961  this->comm().allgather(next_free_dof, dofs_on_proc);
962 
963  // Resize and fill the _first_df and _end_df arrays
964 #ifdef LIBMESH_ENABLE_AMR
967 #endif
968 
969  _first_df.resize(n_proc);
970  _end_df.resize (n_proc);
971 
972  // Get DOF offsets
973  _first_df[0] = 0;
974  for (processor_id_type i=1; i < n_proc; ++i)
975  _first_df[i] = _end_df[i-1] = _first_df[i-1] + dofs_on_proc[i-1];
976  _end_df[n_proc-1] = _first_df[n_proc-1] + dofs_on_proc[n_proc-1];
977 
978  // Clear all the current DOF indices
979  // (distribute_dofs expects them cleared!)
980  this->invalidate_dofs(mesh);
981 
982  next_free_dof = _first_df[proc_id];
983 
984  // Set permanent DOF indices on this processor
985  if (node_major_dofs)
986  this->distribute_local_dofs_node_major (next_free_dof, mesh);
987  else
988  this->distribute_local_dofs_var_major (next_free_dof, mesh);
989 
990  libmesh_assert_equal_to (next_free_dof, _end_df[proc_id]);
991 
992  //------------------------------------------------------------
993  // At this point, all n_comp and dof_number values on local
994  // DofObjects should be correct, but a DistributedMesh might have
995  // incorrect values on non-local DofObjects. Let's request the
996  // correct values from each other processor.
997 
998  if (this->n_processors() > 1)
999  {
1000  this->set_nonlocal_dof_objects(mesh.nodes_begin(),
1001  mesh.nodes_end(),
1003 
1004  this->set_nonlocal_dof_objects(mesh.elements_begin(),
1005  mesh.elements_end(),
1007  }
1008 
1009 #ifdef DEBUG
1010  {
1011  const unsigned int
1012  sys_num = this->sys_number();
1013 
1014  // Processors should all agree on DoF ids for the newly numbered
1015  // system.
1017 
1018  // DoF processor ids should match DofObject processor ids
1019  MeshBase::const_node_iterator node_it = mesh.nodes_begin();
1020  const MeshBase::const_node_iterator node_end = mesh.nodes_end();
1021  for ( ; node_it != node_end; ++node_it)
1022  {
1023  DofObject const * const dofobj = *node_it;
1024  const processor_id_type obj_proc_id = dofobj->processor_id();
1025 
1026  for (unsigned int v=0; v != dofobj->n_vars(sys_num); ++v)
1027  for (unsigned int c=0; c != dofobj->n_comp(sys_num,v); ++c)
1028  {
1029  const dof_id_type dofid = dofobj->dof_number(sys_num,v,c);
1030  libmesh_assert_greater_equal (dofid, this->first_dof(obj_proc_id));
1031  libmesh_assert_less (dofid, this->end_dof(obj_proc_id));
1032  }
1033  }
1034 
1035  MeshBase::const_element_iterator elem_it = mesh.elements_begin();
1036  const MeshBase::const_element_iterator elem_end = mesh.elements_end();
1037  for ( ; elem_it != elem_end; ++elem_it)
1038  {
1039  DofObject const * const dofobj = *elem_it;
1040  const processor_id_type obj_proc_id = dofobj->processor_id();
1041 
1042  for (unsigned int v=0; v != dofobj->n_vars(sys_num); ++v)
1043  for (unsigned int c=0; c != dofobj->n_comp(sys_num,v); ++c)
1044  {
1045  const dof_id_type dofid = dofobj->dof_number(sys_num,v,c);
1046  libmesh_assert_greater_equal (dofid, this->first_dof(obj_proc_id));
1047  libmesh_assert_less (dofid, this->end_dof(obj_proc_id));
1048  }
1049  }
1050  }
1051 #endif
1052 
1053  // Set the total number of degrees of freedom, then start finding
1054  // SCALAR degrees of freedom
1055 #ifdef LIBMESH_ENABLE_AMR
1056  _n_old_dfs = _n_dfs;
1058 #endif
1059  _n_dfs = _end_df[n_proc-1];
1060  _first_scalar_df.clear();
1062  dof_id_type current_SCALAR_dof_index = n_dofs() - n_SCALAR_dofs();
1063 
1064  // Calculate and cache the initial DoF indices for SCALAR variables.
1065  // This is an O(N_vars) calculation so we want to do it once per
1066  // renumbering rather than once per SCALAR_dof_indices() call
1067 
1068  for (unsigned int v=0; v<this->n_variables(); v++)
1069  if(this->variable(v).type().family == SCALAR)
1070  {
1071  _first_scalar_df[v] = current_SCALAR_dof_index;
1072  current_SCALAR_dof_index += this->variable(v).type().order.get_order();
1073  }
1074 
1075  // Allow our GhostingFunctor objects to reinit if necessary
1076  {
1077  std::set<GhostingFunctor *>::iterator gf_it = this->algebraic_ghosting_functors_begin();
1078  const std::set<GhostingFunctor *>::iterator gf_end = this->algebraic_ghosting_functors_end();
1079  for (; gf_it != gf_end; ++gf_it)
1080  {
1081  GhostingFunctor *gf = *gf_it;
1082  libmesh_assert(gf);
1083  gf->dofmap_reinit();
1084  }
1085  }
1086 
1087  {
1088  std::set<GhostingFunctor *>::iterator gf_it = this->coupling_functors_begin();
1089  const std::set<GhostingFunctor *>::iterator gf_end = this->coupling_functors_end();
1090  for (; gf_it != gf_end; ++gf_it)
1091  {
1092  GhostingFunctor *gf = *gf_it;
1093  libmesh_assert(gf);
1094  gf->dofmap_reinit();
1095  }
1096  }
1097 
1098  // Note that in the add_neighbors_to_send_list nodes on processor
1099  // boundaries that are shared by multiple elements are added for
1100  // each element.
1102 
1103  // Here we used to clean up that data structure; now System and
1104  // EquationSystems call that for us, after we've added constraint
1105  // dependencies to the send_list too.
1106  // this->sort_send_list ();
1107 }
DofObject * elem_ptr(MeshBase &mesh, dof_id_type i) const
Definition: dof_map.C:297
FEFamily family
Definition: fe_type.h:206
int get_order() const
Definition: fe_type.h:77
void distribute_local_dofs_node_major(dof_id_type &next_free_dof, MeshBase &mesh)
Definition: dof_map.C:1199
const FEType & type() const
Definition: variable.h:119
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_begin() const
Definition: dof_map.h:311
std::set< GhostingFunctor * >::const_iterator coupling_functors_begin() const
Definition: dof_map.h:275
std::vector< dof_id_type > _send_list
Definition: dof_map.h:1423
processor_id_type n_processors() const
DofObject * node_ptr(MeshBase &mesh, dof_id_type i) const
Definition: dof_map.C:290
MeshBase & mesh
uint8_t processor_id_type
Definition: id_types.h:99
std::vector< dof_id_type > _end_old_df
Definition: dof_map.h:1548
OrderWrapper order
Definition: fe_type.h:200
void invalidate_dofs(MeshBase &mesh) const
Definition: dof_map.C:821
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:1638
dof_id_type n_dofs() const
Definition: dof_map.h:506
std::vector< dof_id_type > _first_old_df
Definition: dof_map.h:1543
std::vector< dof_id_type > _first_scalar_df
Definition: dof_map.h:1417
libmesh_assert(j)
void add_neighbors_to_send_list(MeshBase &mesh)
Definition: dof_map.C:1574
std::vector< dof_id_type > _first_old_scalar_df
Definition: dof_map.h:1554
void libmesh_assert_valid_dof_ids(const MeshBase &mesh, unsigned int sysnum)
Definition: mesh_tools.C:1334
void set_nonlocal_dof_objects(iterator_type objects_begin, iterator_type objects_end, MeshBase &mesh, dofobject_accessor objects)
Definition: dof_map.C:305
static const dof_id_type invalid_id
Definition: dof_object.h:335
void reinit(MeshBase &mesh)
Definition: dof_map.C:455
unsigned int sys_number() const
Definition: dof_map.h:1620
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_end() const
Definition: dof_map.h:317
dof_id_type end_dof() const
Definition: dof_map.h:572
unsigned int n_variables() const
Definition: dof_map.h:473
bool on_command_line(const std::string &arg)
Definition: libmesh.C:914
const Parallel::Communicator & comm() const
dof_id_type _n_old_dfs
Definition: dof_map.h:1538
std::vector< dof_id_type > _end_df
Definition: dof_map.h:1411
dof_id_type n_SCALAR_dofs() const
Definition: dof_map.h:511
std::vector< dof_id_type > _first_df
Definition: dof_map.h:1406
std::set< GhostingFunctor * >::const_iterator coupling_functors_end() const
Definition: dof_map.h:281
void distribute_local_dofs_var_major(dof_id_type &next_free_dof, MeshBase &mesh)
Definition: dof_map.C:1353
dof_id_type first_dof() const
Definition: dof_map.h:534
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:1525
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. Note in particular that the degrees of freedom for a given variable are not in contiguous blocks, as in the case of distribute_local_dofs_var_major. 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

Definition at line 1199 of file dof_map.C.

References _n_SCALAR_dofs, libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::OrderWrapper::get_order(), libMesh::DofObject::invalid_id, libMesh::libmesh_assert(), libMesh::MeshBase::local_nodes_begin(), libMesh::MeshBase::local_nodes_end(), mesh, libMesh::DofObject::n_comp(), libMesh::DofObject::n_comp_group(), n_nodes, libMesh::Elem::n_nodes(), libMesh::ParallelObject::n_processors(), libMesh::DofObject::n_var_groups(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::Elem::node_ref(), libMesh::FEType::order, libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), libMesh::SCALAR, libMesh::DofObject::set_vg_dof_base(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::Variable::type(), variable_group(), and libMesh::DofObject::vg_dof_base().

Referenced by distribute_dofs().

1201 {
1202  const unsigned int sys_num = this->sys_number();
1203  const unsigned int n_var_groups = this->n_variable_groups();
1204 
1205  //-------------------------------------------------------------------------
1206  // First count and assign temporary numbers to local dofs
1207  MeshBase::element_iterator elem_it = mesh.active_local_elements_begin();
1208  const MeshBase::element_iterator elem_end = mesh.active_local_elements_end();
1209 
1210  for ( ; elem_it != elem_end; ++elem_it)
1211  {
1212  // Only number dofs connected to active
1213  // elements on this processor.
1214  Elem * elem = *elem_it;
1215  const unsigned int n_nodes = elem->n_nodes();
1216 
1217  // First number the nodal DOFS
1218  for (unsigned int n=0; n<n_nodes; n++)
1219  {
1220  Node & node = elem->node_ref(n);
1221 
1222  for (unsigned vg=0; vg<n_var_groups; vg++)
1223  {
1224  const VariableGroup & vg_description(this->variable_group(vg));
1225 
1226  if( (vg_description.type().family != SCALAR) &&
1227  (vg_description.active_on_subdomain(elem->subdomain_id())) )
1228  {
1229  // assign dof numbers (all at once) if this is
1230  // our node and if they aren't already there
1231  if ((node.n_comp_group(sys_num,vg) > 0) &&
1232  (node.processor_id() == this->processor_id()) &&
1233  (node.vg_dof_base(sys_num,vg) ==
1235  {
1236  node.set_vg_dof_base(sys_num, vg,
1237  next_free_dof);
1238  next_free_dof += (vg_description.n_variables()*
1239  node.n_comp_group(sys_num,vg));
1240  //node.debug_buffer();
1241  }
1242  }
1243  }
1244  }
1245 
1246  // Now number the element DOFS
1247  for (unsigned vg=0; vg<n_var_groups; vg++)
1248  {
1249  const VariableGroup & vg_description(this->variable_group(vg));
1250 
1251  if ( (vg_description.type().family != SCALAR) &&
1252  (vg_description.active_on_subdomain(elem->subdomain_id())) )
1253  if (elem->n_comp_group(sys_num,vg) > 0)
1254  {
1255  libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg),
1257 
1258  elem->set_vg_dof_base(sys_num,
1259  vg,
1260  next_free_dof);
1261 
1262  next_free_dof += (vg_description.n_variables()*
1263  elem->n_comp(sys_num,vg));
1264  }
1265  }
1266  } // done looping over elements
1267 
1268 
1269  // we may have missed assigning DOFs to nodes that we own
1270  // but to which we have no connected elements matching our
1271  // variable restriction criterion. this will happen, for example,
1272  // if variable V is restricted to subdomain S. We may not own
1273  // any elements which live in S, but we may own nodes which are
1274  // *connected* to elements which do. in this scenario these nodes
1275  // will presently have unnumbered DOFs. we need to take care of
1276  // them here since we own them and no other processor will touch them.
1277  {
1278  MeshBase::node_iterator node_it = mesh.local_nodes_begin();
1279  const MeshBase::node_iterator node_end = mesh.local_nodes_end();
1280 
1281  for (; node_it != node_end; ++node_it)
1282  {
1283  Node * node = *node_it;
1284  libmesh_assert(node);
1285 
1286  for (unsigned vg=0; vg<n_var_groups; vg++)
1287  {
1288  const VariableGroup & vg_description(this->variable_group(vg));
1289 
1290  if (node->n_comp_group(sys_num,vg))
1291  if (node->vg_dof_base(sys_num,vg) == DofObject::invalid_id)
1292  {
1293  node->set_vg_dof_base (sys_num,
1294  vg,
1295  next_free_dof);
1296 
1297  next_free_dof += (vg_description.n_variables()*
1298  node->n_comp(sys_num,vg));
1299  }
1300  }
1301  }
1302  }
1303 
1304  // Finally, count up the SCALAR dofs
1305  this->_n_SCALAR_dofs = 0;
1306  for (unsigned vg=0; vg<n_var_groups; vg++)
1307  {
1308  const VariableGroup & vg_description(this->variable_group(vg));
1309 
1310  if( vg_description.type().family == SCALAR )
1311  {
1312  this->_n_SCALAR_dofs += (vg_description.n_variables()*
1313  vg_description.type().order.get_order());
1314  continue;
1315  }
1316  }
1317 
1318  // Only increment next_free_dof if we're on the processor
1319  // that holds this SCALAR variable
1320  if ( this->processor_id() == (this->n_processors()-1) )
1321  next_free_dof += _n_SCALAR_dofs;
1322 
1323 #ifdef DEBUG
1324  {
1325  // libMesh::out << "next_free_dof=" << next_free_dof << std::endl
1326  // << "_n_SCALAR_dofs=" << _n_SCALAR_dofs << std::endl;
1327 
1328  // Make sure we didn't miss any nodes
1329  MeshTools::libmesh_assert_valid_procids<Node>(mesh);
1330 
1331  MeshBase::node_iterator node_it = mesh.local_nodes_begin();
1332  const MeshBase::node_iterator node_end = mesh.local_nodes_end();
1333  for (; node_it != node_end; ++node_it)
1334  {
1335  Node * obj = *node_it;
1336  libmesh_assert(obj);
1337  unsigned int n_var_g = obj->n_var_groups(this->sys_number());
1338  for (unsigned int vg=0; vg != n_var_g; ++vg)
1339  {
1340  unsigned int n_comp_g =
1341  obj->n_comp_group(this->sys_number(), vg);
1342  dof_id_type my_first_dof = n_comp_g ?
1343  obj->vg_dof_base(this->sys_number(), vg) : 0;
1344  libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
1345  }
1346  }
1347  }
1348 #endif // DEBUG
1349 }
processor_id_type n_processors() const
MeshBase & mesh
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:1628
libmesh_assert(j)
const dof_id_type n_nodes
Definition: tecplot_io.C:67
dof_id_type _n_SCALAR_dofs
Definition: dof_map.h:1531
static const dof_id_type invalid_id
Definition: dof_object.h:335
unsigned int n_variable_groups() const
Definition: dof_map.h:465
unsigned int sys_number() const
Definition: dof_map.h:1620
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 1353 of file dof_map.C.

References _n_SCALAR_dofs, libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::OrderWrapper::get_order(), libMesh::DofObject::invalid_id, libMesh::libmesh_assert(), libMesh::MeshBase::local_nodes_begin(), libMesh::MeshBase::local_nodes_end(), merge_ghost_functor_outputs(), mesh, libMesh::DofObject::n_comp_group(), n_nodes, libMesh::Elem::n_nodes(), libMesh::ParallelObject::n_processors(), libMesh::DofObject::n_var_groups(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::Elem::node_ref(), libMesh::FEType::order, libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), libMesh::SCALAR, libMesh::DofObject::set_vg_dof_base(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::Variable::type(), variable_group(), and libMesh::DofObject::vg_dof_base().

Referenced by distribute_dofs().

1355 {
1356  const unsigned int sys_num = this->sys_number();
1357  const unsigned int n_var_groups = this->n_variable_groups();
1358 
1359  //-------------------------------------------------------------------------
1360  // First count and assign temporary numbers to local dofs
1361  for (unsigned vg=0; vg<n_var_groups; vg++)
1362  {
1363  const VariableGroup & vg_description(this->variable_group(vg));
1364 
1365  const unsigned int n_vars_in_group = vg_description.n_variables();
1366 
1367  // Skip the SCALAR dofs
1368  if (vg_description.type().family == SCALAR)
1369  continue;
1370 
1371  MeshBase::element_iterator elem_it = mesh.active_local_elements_begin();
1372  const MeshBase::element_iterator elem_end = mesh.active_local_elements_end();
1373 
1374  for ( ; elem_it != elem_end; ++elem_it)
1375  {
1376  // Only number dofs connected to active
1377  // elements on this processor.
1378  Elem * elem = *elem_it;
1379 
1380  // ... and only variables which are active on
1381  // on this element's subdomain
1382  if (!vg_description.active_on_subdomain(elem->subdomain_id()))
1383  continue;
1384 
1385  const unsigned int n_nodes = elem->n_nodes();
1386 
1387  // First number the nodal DOFS
1388  for (unsigned int n=0; n<n_nodes; n++)
1389  {
1390  Node & node = elem->node_ref(n);
1391 
1392  // assign dof numbers (all at once) if this is
1393  // our node and if they aren't already there
1394  if ((node.n_comp_group(sys_num,vg) > 0) &&
1395  (node.processor_id() == this->processor_id()) &&
1396  (node.vg_dof_base(sys_num,vg) ==
1398  {
1399  node.set_vg_dof_base(sys_num, vg, next_free_dof);
1400 
1401  next_free_dof += (n_vars_in_group*
1402  node.n_comp_group(sys_num,vg));
1403  }
1404  }
1405 
1406  // Now number the element DOFS
1407  if (elem->n_comp_group(sys_num,vg) > 0)
1408  {
1409  libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg),
1411 
1412  elem->set_vg_dof_base(sys_num,
1413  vg,
1414  next_free_dof);
1415 
1416  next_free_dof += (n_vars_in_group*
1417  elem->n_comp_group(sys_num,vg));
1418  }
1419  } // end loop on elements
1420 
1421  // we may have missed assigning DOFs to nodes that we own
1422  // but to which we have no connected elements matching our
1423  // variable restriction criterion. this will happen, for example,
1424  // if variable V is restricted to subdomain S. We may not own
1425  // any elements which live in S, but we may own nodes which are
1426  // *connected* to elements which do. in this scenario these nodes
1427  // will presently have unnumbered DOFs. we need to take care of
1428  // them here since we own them and no other processor will touch them.
1429  {
1430  MeshBase::node_iterator node_it = mesh.local_nodes_begin();
1431  const MeshBase::node_iterator node_end = mesh.local_nodes_end();
1432 
1433  for (; node_it != node_end; ++node_it)
1434  {
1435  Node * node = *node_it;
1436  libmesh_assert(node);
1437 
1438  if (node->n_comp_group(sys_num,vg))
1439  if (node->vg_dof_base(sys_num,vg) == DofObject::invalid_id)
1440  {
1441  node->set_vg_dof_base (sys_num,
1442  vg,
1443  next_free_dof);
1444 
1445  next_free_dof += (n_vars_in_group*
1446  node->n_comp_group(sys_num,vg));
1447  }
1448  }
1449  }
1450  } // end loop on variable groups
1451 
1452  // Finally, count up the SCALAR dofs
1453  this->_n_SCALAR_dofs = 0;
1454  for (unsigned vg=0; vg<n_var_groups; vg++)
1455  {
1456  const VariableGroup & vg_description(this->variable_group(vg));
1457 
1458  if( vg_description.type().family == SCALAR )
1459  {
1460  this->_n_SCALAR_dofs += (vg_description.n_variables()*
1461  vg_description.type().order.get_order());
1462  continue;
1463  }
1464  }
1465 
1466  // Only increment next_free_dof if we're on the processor
1467  // that holds this SCALAR variable
1468  if ( this->processor_id() == (this->n_processors()-1) )
1469  next_free_dof += _n_SCALAR_dofs;
1470 
1471 #ifdef DEBUG
1472  {
1473  // Make sure we didn't miss any nodes
1474  MeshTools::libmesh_assert_valid_procids<Node>(mesh);
1475 
1476  MeshBase::node_iterator node_it = mesh.local_nodes_begin();
1477  const MeshBase::node_iterator node_end = mesh.local_nodes_end();
1478  for (; node_it != node_end; ++node_it)
1479  {
1480  Node * obj = *node_it;
1481  libmesh_assert(obj);
1482  unsigned int n_var_g = obj->n_var_groups(this->sys_number());
1483  for (unsigned int vg=0; vg != n_var_g; ++vg)
1484  {
1485  unsigned int n_comp_g =
1486  obj->n_comp_group(this->sys_number(), vg);
1487  dof_id_type my_first_dof = n_comp_g ?
1488  obj->vg_dof_base(this->sys_number(), vg) : 0;
1489  libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
1490  }
1491  }
1492  }
1493 #endif // DEBUG
1494 }
processor_id_type n_processors() const
MeshBase & mesh
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:1628
libmesh_assert(j)
const dof_id_type n_nodes
Definition: tecplot_io.C:67
dof_id_type _n_SCALAR_dofs
Definition: dof_map.h:1531
static const dof_id_type invalid_id
Definition: dof_object.h:335
unsigned int n_variable_groups() const
Definition: dof_map.h:465
unsigned int sys_number() const
Definition: dof_map.h:1620
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 2022 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(), libMesh::libmesh_assert(), 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::SparsityPattern::Build::handle_vi_vj(), libMesh::MeshFunction::hessian(), libMesh::SystemSubsetBySubdomain::init(), is_evaluable(), libMesh::System::local_dof_indices(), libMesh::DGFEMContext::neighbor_side_fe_reinit(), libMesh::WeightedPatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::SparsityPattern::Build::operator()(), libMesh::PatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::MeshFunction::operator()(), libMesh::BoundaryProjectSolution::operator()(), libMesh::ErrorVector::plot_error(), libMesh::FEMContext::pre_fe_reinit(), libMesh::HPCoarsenTest::select_refinement(), libMesh::EnsightIO::write_scalar_ascii(), and libMesh::EnsightIO::write_vector_ascii().

2024 {
2025  // We now allow elem==NULL to request just SCALAR dofs
2026  // libmesh_assert(elem);
2027 
2028  // If we are asking for current indices on an element, it ought to
2029  // be an active element (or a Side proxy, which also thinks it's
2030  // active)
2031  libmesh_assert(!elem || elem->active());
2032 
2033  LOG_SCOPE("dof_indices()", "DofMap");
2034 
2035  // Clear the DOF indices vector
2036  di.clear();
2037 
2038  const unsigned int n_vars = this->n_variables();
2039 
2040 #ifdef DEBUG
2041  // Check that sizes match in DEBUG mode
2042  std::size_t tot_size = 0;
2043 #endif
2044 
2045  if (elem && elem->type() == TRI3SUBDIVISION)
2046  {
2047  // Subdivision surface FE require the 1-ring around elem
2048  const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
2049 
2050  // Ghost subdivision elements have no real dofs
2051  if (!sd_elem->is_ghost())
2052  {
2053  // Determine the nodes contributing to element elem
2054  std::vector<const Node *> elem_nodes;
2055  MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
2056 
2057  // Get the dof numbers
2058  for (unsigned int v=0; v<n_vars; v++)
2059  {
2060  if(this->variable(v).type().family == SCALAR &&
2061  this->variable(v).active_on_subdomain(elem->subdomain_id()))
2062  {
2063 #ifdef DEBUG
2064  tot_size += this->variable(v).type().order;
2065 #endif
2066  std::vector<dof_id_type> di_new;
2067  this->SCALAR_dof_indices(di_new,v);
2068  di.insert( di.end(), di_new.begin(), di_new.end());
2069  }
2070  else
2071  _dof_indices(elem, elem->p_level(), di, v,
2072  &elem_nodes[0], elem_nodes.size()
2073 #ifdef DEBUG
2074  , tot_size
2075 #endif
2076  );
2077  }
2078  }
2079 
2080  return;
2081  }
2082 
2083  // Get the dof numbers
2084  for (unsigned int v=0; v<n_vars; v++)
2085  {
2086  const Variable & var = this->variable(v);
2087  if(var.type().family == SCALAR &&
2088  (!elem ||
2089  var.active_on_subdomain(elem->subdomain_id())))
2090  {
2091 #ifdef DEBUG
2092  tot_size += var.type().order;
2093 #endif
2094  std::vector<dof_id_type> di_new;
2095  this->SCALAR_dof_indices(di_new,v);
2096  di.insert( di.end(), di_new.begin(), di_new.end());
2097  }
2098  else if (elem)
2099  _dof_indices(elem, elem->p_level(), di, v, elem->get_nodes(),
2100  elem->n_nodes()
2101 #ifdef DEBUG
2102  , tot_size
2103 #endif
2104  );
2105  }
2106 
2107 #ifdef DEBUG
2108  libmesh_assert_equal_to (tot_size, di.size());
2109 #endif
2110 }
const FEType & type() const
Definition: variable.h:119
void _dof_indices(const Elem *const 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:2267
OrderWrapper order
Definition: fe_type.h:200
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:1638
const unsigned int n_vars
Definition: tecplot_io.C:68
libmesh_assert(j)
unsigned int n_variables() const
Definition: dof_map.h:473
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Definition: dof_map.C:2386
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 2113 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().

2117 {
2118  // We now allow elem==NULL to request just SCALAR dofs
2119  // libmesh_assert(elem);
2120 
2121  LOG_SCOPE("dof_indices()", "DofMap");
2122 
2123  // Clear the DOF indices vector
2124  di.clear();
2125 
2126  // Use the default p refinement level?
2127  if (p_level == -12345)
2128  p_level = elem ? elem->p_level() : 0;
2129 
2130 #ifdef DEBUG
2131  // Check that sizes match in DEBUG mode
2132  std::size_t tot_size = 0;
2133 #endif
2134 
2135  if (elem && elem->type() == TRI3SUBDIVISION)
2136  {
2137  // Subdivision surface FE require the 1-ring around elem
2138  const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
2139 
2140  // Ghost subdivision elements have no real dofs
2141  if (!sd_elem->is_ghost())
2142  {
2143  // Determine the nodes contributing to element elem
2144  std::vector<const Node *> elem_nodes;
2145  MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
2146 
2147  _dof_indices(elem, p_level, di, vn, &elem_nodes[0],
2148  elem_nodes.size()
2149 #ifdef DEBUG
2150  , tot_size
2151 #endif
2152  );
2153  }
2154 
2155  return;
2156  }
2157 
2158  const Variable & var = this->variable(vn);
2159 
2160  // Get the dof numbers
2161  if(var.type().family == SCALAR &&
2162  (!elem ||
2163  var.active_on_subdomain(elem->subdomain_id())))
2164  {
2165 #ifdef DEBUG
2166  tot_size += var.type().order;
2167 #endif
2168  std::vector<dof_id_type> di_new;
2169  this->SCALAR_dof_indices(di_new,vn);
2170  di.insert( di.end(), di_new.begin(), di_new.end());
2171  }
2172  else if (elem)
2173  _dof_indices(elem, p_level, di, vn, elem->get_nodes(),
2174  elem->n_nodes()
2175 #ifdef DEBUG
2176  , tot_size
2177 #endif
2178  );
2179 
2180 #ifdef DEBUG
2181  libmesh_assert_equal_to (tot_size, di.size());
2182 #endif
2183 }
void _dof_indices(const Elem *const 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:2267
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:1638
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Definition: dof_map.C:2386
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 2186 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().

2188 {
2189  // We allow node==NULL to request just SCALAR dofs
2190  // libmesh_assert(elem);
2191 
2192  LOG_SCOPE("dof_indices(Node)", "DofMap");
2193 
2194  // Clear the DOF indices vector
2195  di.clear();
2196 
2197  const unsigned int n_vars = this->n_variables();
2198  const unsigned int sys_num = this->sys_number();
2199 
2200  // Get the dof numbers
2201  for (unsigned int v=0; v<n_vars; v++)
2202  {
2203  const Variable & var = this->variable(v);
2204  if (var.type().family == SCALAR)
2205  {
2206  std::vector<dof_id_type> di_new;
2207  this->SCALAR_dof_indices(di_new,v);
2208  di.insert( di.end(), di_new.begin(), di_new.end());
2209  }
2210  else
2211  {
2212  const int n_comp = node->n_comp(sys_num,v);
2213  for (int i=0; i != n_comp; ++i)
2214  {
2215  libmesh_assert_not_equal_to
2216  (node->dof_number(sys_num,v,i),
2218  di.push_back(node->dof_number(sys_num,v,i));
2219  }
2220  }
2221  }
2222 }
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:1638
const unsigned int n_vars
Definition: tecplot_io.C:68
static const dof_id_type invalid_id
Definition: dof_object.h:335
unsigned int sys_number() const
Definition: dof_map.h:1620
unsigned int n_variables() const
Definition: dof_map.h:473
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Definition: dof_map.C:2386
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 2225 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().

2228 {
2229  if (vn == libMesh::invalid_uint)
2230  {
2231  this->dof_indices(node, di);
2232  return;
2233  }
2234 
2235  // We allow node==NULL to request just SCALAR dofs
2236  // libmesh_assert(elem);
2237 
2238  LOG_SCOPE("dof_indices(Node)", "DofMap");
2239 
2240  // Clear the DOF indices vector
2241  di.clear();
2242 
2243  const unsigned int sys_num = this->sys_number();
2244 
2245  // Get the dof numbers
2246  const Variable & var = this->variable(vn);
2247  if (var.type().family == SCALAR)
2248  {
2249  std::vector<dof_id_type> di_new;
2250  this->SCALAR_dof_indices(di_new,vn);
2251  di.insert( di.end(), di_new.begin(), di_new.end());
2252  }
2253  else
2254  {
2255  const int n_comp = node->n_comp(sys_num,vn);
2256  for (int i=0; i != n_comp; ++i)
2257  {
2258  libmesh_assert_not_equal_to
2259  (node->dof_number(sys_num,vn,i),
2261  di.push_back(node->dof_number(sys_num,vn,i));
2262  }
2263  }
2264 }
const unsigned int invalid_uint
Definition: libmesh.h:184
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:1638
static const dof_id_type invalid_id
Definition: dof_object.h:335
unsigned int sys_number() const
Definition: dof_map.h:1620
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Definition: dof_map.C:2386
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition: dof_map.C:2022
DofObject * libMesh::DofMap::elem_ptr ( MeshBase mesh,
dof_id_type  i 
) const
private

An adapter function that returns Elem pointers by index

Definition at line 297 of file dof_map.C.

References libMesh::MeshBase::elem_ptr().

Referenced by distribute_dofs().

298 {
299  return mesh.elem_ptr(i);
300 }
MeshBase & mesh
void libMesh::ReferenceCounter::enable_print_counter_info ( )
staticinherited

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

Definition at line 100 of file reference_counter.C.

References libMesh::ReferenceCounter::_enable_print_counter.

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

101 {
102  _enable_print_counter = true;
103  return;
104 }
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 572 of file dof_map.h.

References libMesh::processor_id().

Referenced by add_neighbors_to_send_list(), all_semilocal_indices(), distribute_dofs(), get_info(), is_evaluable(), and local_variable_indices().

573  { return this->end_dof(this->processor_id()); }
dof_id_type end_dof() const
Definition: dof_map.h:572
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 581 of file dof_map.h.

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

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

Definition at line 584 of file dof_map.h.

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

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

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

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

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

1939 {
1940 #ifdef LIBMESH_ENABLE_AMR
1941 
1942  // Trivial mapping
1943  libmesh_assert_equal_to (dof_indices_in.size(), Ue.size());
1944  bool has_constrained_dofs = false;
1945 
1946  for (unsigned int il=0;
1947  il != cast_int<unsigned int>(dof_indices_in.size()); il++)
1948  {
1949  const dof_id_type ig = dof_indices_in[il];
1950 
1951  if (this->is_constrained_dof (ig)) has_constrained_dofs = true;
1952 
1953  libmesh_assert_less (ig, Ug.size());
1954 
1955  Ue.el(il) = Ug(ig);
1956  }
1957 
1958  // If the element has any constrained DOFs then we need
1959  // to account for them in the mapping. This will handle
1960  // the case that the input vector is not constrained.
1961  if (has_constrained_dofs)
1962  {
1963  // Copy the input DOF indices.
1964  std::vector<dof_id_type> constrained_dof_indices(dof_indices_in);
1965 
1966  DenseMatrix<Number> C;
1967  DenseVector<Number> H;
1968 
1969  this->build_constraint_matrix_and_vector (C, H, constrained_dof_indices);
1970 
1971  libmesh_assert_equal_to (dof_indices_in.size(), C.m());
1972  libmesh_assert_equal_to (constrained_dof_indices.size(), C.n());
1973 
1974  // zero-out Ue
1975  Ue.zero();
1976 
1977  // compute Ue = C Ug, with proper mapping.
1978  const unsigned int n_original_dofs =
1979  cast_int<unsigned int>(dof_indices_in.size());
1980  for (unsigned int i=0; i != n_original_dofs; i++)
1981  {
1982  Ue.el(i) = H(i);
1983 
1984  const unsigned int n_constrained =
1985  cast_int<unsigned int>(constrained_dof_indices.size());
1986  for (unsigned int j=0; j<n_constrained; j++)
1987  {
1988  const dof_id_type jg = constrained_dof_indices[j];
1989 
1990  // If Ug is a serial or ghosted vector, then this assert is
1991  // overzealous. If Ug is a parallel vector, then this assert
1992  // is redundant.
1993  // libmesh_assert ((jg >= Ug.first_local_index()) &&
1994  // (jg < Ug.last_local_index()));
1995 
1996  Ue.el(i) += C(i,j)*Ug(jg);
1997  }
1998  }
1999  }
2000 
2001 #else
2002 
2003  // Trivial mapping
2004 
2005  const unsigned int n_original_dofs =
2006  cast_int<unsigned int>(dof_indices_in.size());
2007 
2008  libmesh_assert_equal_to (n_original_dofs, Ue.size());
2009 
2010  for (unsigned int il=0; il<n_original_dofs; il++)
2011  {
2012  const dof_id_type ig = dof_indices_in[il];
2013 
2014  libmesh_assert ((ig >= Ug.first_local_index()) && (ig < Ug.last_local_index()));
2015 
2016  Ue.el(il) = Ug(ig);
2017  }
2018 
2019 #endif
2020 }
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
libmesh_assert(j)
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1705
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 2707 of file dof_map.C.

References _dof_constraints, is_constrained_dof(), and libMesh::libmesh_assert().

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

2708 {
2709  typedef std::set<dof_id_type> RCSet;
2710 
2711  // First insert the DOFS we already depend on into the set.
2712  RCSet dof_set (elem_dofs.begin(), elem_dofs.end());
2713 
2714  bool done = true;
2715 
2716  // Next insert any dofs those might be constrained in terms
2717  // of. Note that in this case we may not be done: Those may
2718  // in turn depend on others. So, we need to repeat this process
2719  // in that case until the system depends only on unconstrained
2720  // degrees of freedom.
2721  for (std::size_t i=0; i<elem_dofs.size(); i++)
2722  if (this->is_constrained_dof(elem_dofs[i]))
2723  {
2724  // If the DOF is constrained
2725  DofConstraints::const_iterator
2726  pos = _dof_constraints.find(elem_dofs[i]);
2727 
2728  libmesh_assert (pos != _dof_constraints.end());
2729 
2730  const DofConstraintRow & constraint_row = pos->second;
2731 
2732  // adaptive p refinement currently gives us lots of empty constraint
2733  // rows - we should optimize those DoFs away in the future. [RHS]
2734  //libmesh_assert (!constraint_row.empty());
2735 
2736  DofConstraintRow::const_iterator it = constraint_row.begin();
2737  DofConstraintRow::const_iterator it_end = constraint_row.end();
2738 
2739 
2740  // Add the DOFs this dof is constrained in terms of.
2741  // note that these dofs might also be constrained, so
2742  // we will need to call this function recursively.
2743  for ( ; it != it_end; ++it)
2744  if (!dof_set.count (it->first))
2745  {
2746  dof_set.insert (it->first);
2747  done = false;
2748  }
2749  }
2750 
2751 
2752  // If not done then we need to do more work
2753  // (obviously :-) )!
2754  if (!done)
2755  {
2756  // Fill the vector with the contents of the set
2757  elem_dofs.clear();
2758  elem_dofs.insert (elem_dofs.end(),
2759  dof_set.begin(), dof_set.end());
2760 
2761 
2762  // May need to do this recursively. It is possible
2763  // that we just replaced a constrained DOF with another
2764  // constrained DOF.
2765  this->find_connected_dofs (elem_dofs);
2766 
2767  } // end if (!done)
2768 }
libmesh_assert(j)
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:1705
DofConstraints _dof_constraints
Definition: dof_map.h:1563
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:88
void find_connected_dofs(std::vector< dof_id_type > &elem_dofs) const
Definition: dof_map.C:2707
dof_id_type libMesh::DofMap::first_dof ( ) const
inline

Definition at line 534 of file dof_map.h.

References libMesh::processor_id().

Referenced by add_neighbors_to_send_list(), all_semilocal_indices(), distribute_dofs(), get_info(), is_evaluable(), and local_variable_indices().

535  { return this->first_dof(this->processor_id()); }
dof_id_type first_dof() const
Definition: dof_map.h:534
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 541 of file dof_map.h.

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

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

Definition at line 544 of file dof_map.h.

References libMesh::processor_id().

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

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

3695 {
3696  typedef std::set<dof_id_type> DoF_RCSet;
3697 
3698  // If we have heterogenous adjoint constraints we need to
3699  // communicate those too.
3700  const unsigned int max_qoi_num =
3701  _adjoint_constraint_values.empty() ?
3702  0 : _adjoint_constraint_values.rbegin()->first;
3703 
3704  // We have to keep recursing while the unexpanded set is
3705  // nonempty on *any* processor
3706  bool unexpanded_set_nonempty = !unexpanded_dofs.empty();
3707  this->comm().max(unexpanded_set_nonempty);
3708 
3709  while (unexpanded_set_nonempty)
3710  {
3711  // Let's make sure we don't lose sync in this loop.
3712  parallel_object_only();
3713 
3714  // Request sets
3715  DoF_RCSet dof_request_set;
3716 
3717  // Request sets to send to each processor
3718  std::vector<std::vector<dof_id_type> >
3719  requested_dof_ids(this->n_processors());
3720 
3721  // And the sizes of each
3722  std::vector<dof_id_type>
3723  dof_ids_on_proc(this->n_processors(), 0);
3724 
3725  // Fill (and thereby sort and uniq!) the main request sets
3726  for (DoF_RCSet::iterator i = unexpanded_dofs.begin();
3727  i != unexpanded_dofs.end(); ++i)
3728  {
3729  const dof_id_type unexpanded_dof = *i;
3730  DofConstraints::const_iterator
3731  pos = _dof_constraints.find(unexpanded_dof);
3732 
3733  // If we were asked for a DoF and we don't already have a
3734  // constraint for it, then we need to check for one.
3735  if (pos == _dof_constraints.end())
3736  {
3737  if (((unexpanded_dof < this->first_dof()) ||
3738  (unexpanded_dof >= this->end_dof())) &&
3739  !_dof_constraints.count(unexpanded_dof))
3740  dof_request_set.insert(unexpanded_dof);
3741  }
3742  // If we were asked for a DoF and we already have a
3743  // constraint for it, then we need to check if the
3744  // constraint is recursive.
3745  else
3746  {
3747  const DofConstraintRow & row = pos->second;
3748  for (DofConstraintRow::const_iterator j = row.begin();
3749  j != row.end(); ++j)
3750  {
3751  const dof_id_type constraining_dof = j->first;
3752 
3753  // If it's non-local and we haven't already got a
3754  // constraint for it, we might need to ask for one
3755  if (((constraining_dof < this->first_dof()) ||
3756  (constraining_dof >= this->end_dof())) &&
3757  !_dof_constraints.count(constraining_dof))
3758  dof_request_set.insert(constraining_dof);
3759  }
3760  }
3761  }
3762 
3763  // Clear the unexpanded constraint set; we're about to expand it
3764  unexpanded_dofs.clear();
3765 
3766  // Count requests by processor
3767  processor_id_type proc_id = 0;
3768  for (DoF_RCSet::iterator i = dof_request_set.begin();
3769  i != dof_request_set.end(); ++i)
3770  {
3771  while (*i >= _end_df[proc_id])
3772  proc_id++;
3773  dof_ids_on_proc[proc_id]++;
3774  }
3775 
3776  for (processor_id_type p = 0; p != this->n_processors(); ++p)
3777  {
3778  requested_dof_ids[p].reserve(dof_ids_on_proc[p]);
3779  }
3780 
3781