libMesh
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Protected Types | Protected Member Functions | Protected Attributes | Static Protected Attributes | Private Types | Private Member Functions | Static Private Member Functions | Private Attributes | Friends | List of all members
libMesh::DofMap Class Reference

This class handles the numbering of degrees of freedom on a mesh. More...

#include <dof_map.h>

Inheritance diagram for libMesh::DofMap:
[legend]

Classes

class  AugmentSendList
 Abstract base class to be used to add user-defined parallel degree of freedom couplings. More...
 
class  AugmentSparsityPattern
 Backwards compatibility for prior AugmentSparsityPattern users. More...
 

Public Types

typedef std::vector< GhostingFunctor * >::const_iterator GhostingFunctorIterator
 Iterator type for coupling and algebraic ghosting functor ranges.
 

Public Member Functions

 DofMap (const unsigned int sys_number, MeshBase &mesh)
 Constructor.
 
 ~DofMap ()
 Destructor.
 
void attach_matrix (SparseMatrix< Number > &matrix)
 Additional matrices may be attached to this DofMap.
 
void update_sparsity_pattern (SparseMatrix< Number > &matrix) const
 Additional matrices may be be temporarily initialized by this DofMap.
 
bool is_attached (SparseMatrix< Number > &matrix)
 Matrices should not be attached more than once.
 
std::size_t distribute_dofs (MeshBase &)
 Distribute dofs on the current mesh.
 
void compute_sparsity (const MeshBase &)
 Computes the sparsity pattern for the matrices corresponding to proc_id and sends that data to Linear Algebra packages for preallocation of sparse matrices.
 
bool computed_sparsity_already () const
 Returns true iff a sparsity pattern has already been computed.
 
void set_constrained_sparsity_construction (bool use_constraints)
 Sets the current policy for constructing sparsity patterns: if use_constraints is true (for robustness), we explicitly account for sparsity entries created by constraint matrix pre- and post- application.
 
void full_sparsity_pattern_needed ()
 Sets need_full_sparsity_pattern to true regardless of the requirements by matrices.
 
bool constrained_sparsity_construction ()
 Returns true iff the current policy when constructing sparsity patterns is to explicitly account for sparsity entries created by constraint matrix pre- and post- application.
 
void clear_sparsity ()
 Clears the sparsity pattern.
 
void remove_default_ghosting ()
 Remove any default ghosting functor(s).
 
void add_default_ghosting ()
 Add the default functor(s) for coupling and algebraic ghosting.
 
void add_coupling_functor (GhostingFunctor &coupling_functor, bool to_mesh=true)
 Adds a functor which can specify coupling requirements for creation of sparse matrices.
 
void add_coupling_functor (std::shared_ptr< GhostingFunctor > coupling_functor, bool to_mesh=true)
 Adds a functor which can specify coupling requirements for creation of sparse matrices.
 
void remove_coupling_functor (GhostingFunctor &coupling_functor)
 Removes a functor which was previously added to the set of coupling functors, from both this DofMap and from the underlying mesh.
 
GhostingFunctorIterator coupling_functors_begin () const
 Beginning of range of coupling functors.
 
GhostingFunctorIterator coupling_functors_end () const
 End of range of coupling functors.
 
DefaultCouplingdefault_coupling ()
 Default coupling functor.
 
void add_algebraic_ghosting_functor (GhostingFunctor &evaluable_functor, bool to_mesh=true)
 Adds a functor which can specify algebraic ghosting requirements for use with distributed vectors.
 
void add_algebraic_ghosting_functor (std::shared_ptr< GhostingFunctor > evaluable_functor, bool to_mesh=true)
 Adds a functor which can specify algebraic ghosting requirements for use with distributed vectors.
 
void remove_algebraic_ghosting_functor (GhostingFunctor &evaluable_functor)
 Removes a functor which was previously added to the set of algebraic ghosting functors, from both this DofMap and from the underlying mesh.
 
GhostingFunctorIterator algebraic_ghosting_functors_begin () const
 Beginning of range of algebraic ghosting functors.
 
GhostingFunctorIterator algebraic_ghosting_functors_end () const
 End of range of algebraic ghosting functors.
 
DefaultCouplingdefault_algebraic_ghosting ()
 Default algebraic ghosting functor.
 
void attach_extra_sparsity_object (SparsityPattern::AugmentSparsityPattern &asp)
 Attach an object to use to populate the sparsity pattern with extra entries.
 
void attach_extra_sparsity_function (void(*func)(SparsityPattern::Graph &sparsity, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *), void *context=nullptr)
 Attach a function pointer to use as a callback to populate the sparsity pattern with extra entries.
 
void attach_extra_send_list_object (DofMap::AugmentSendList &asl)
 Attach an object to populate the send_list with extra entries.
 
void attach_extra_send_list_function (void(*func)(std::vector< dof_id_type > &, void *), void *context=nullptr)
 Attach a function pointer to use as a callback to populate the send_list with extra entries.
 
void prepare_send_list ()
 Takes the _send_list vector (which may have duplicate entries) and sorts it.
 
void clear_send_list ()
 Clears the _send_list vector.
 
void reinit_send_list (MeshBase &mesh)
 Clears the _send_list vector and then rebuilds it.
 
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
 
const SparsityPattern::Buildget_sparsity_pattern () const
 
unsigned int n_vars () const
 
const std::string & variable_name (const unsigned int i) const
 
unsigned int n_components (const MeshBase &mesh) const
 
bool identify_variable_groups () const
 
void identify_variable_groups (const bool)
 Toggle automatic VariableGroup identification.
 
unsigned int variable_scalar_number (unsigned int var_num, unsigned int component) const
 
const FETypevariable_type (const unsigned int i) const
 
const FETypevariable_type (std::string_view var) const
 
unsigned int variable_number (std::string_view var) const
 
bool has_variable (std::string_view var) const
 
void get_all_variable_numbers (std::vector< unsigned int > &all_variable_numbers) const
 Fills all_variable_numbers with all the variable numbers for the variables that have been added to this system.
 
unsigned int add_variable (System &sys, std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
 Adds the variable var to the list of variables for this system.
 
unsigned int add_variables (System &sys, const std::vector< std::string > &vars, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
 Adds the variables vars to the list of variables for this system.
 
unsigned int add_variable_array (System &sys, const std::vector< std::string > &vars, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
 Adds variables vars to the list of variables for this system.
 
void set_error_on_cyclic_constraint (bool error_on_cyclic_constraint)
 Specify whether or not we perform an extra (opt-mode enabled) check for constraint loops.
 
void set_error_on_constraint_loop (bool error_on_constraint_loop)
 
const VariableGroupvariable_group (const unsigned int c) const
 
const Variablevariable (const unsigned int c) const override
 
Order variable_order (const unsigned int c) const
 
Order variable_group_order (const unsigned int vg) const
 
const FETypevariable_group_type (const unsigned int vg) const
 
unsigned int n_variable_groups () const
 
unsigned int n_variables () const override
 
unsigned int var_group_from_var_number (unsigned int var_num) const
 
bool has_blocked_representation () const
 
unsigned int block_size () const
 
dof_id_type n_dofs (const unsigned int vn) const
 
dof_id_type n_SCALAR_dofs () const
 
dof_id_type n_local_dofs (const unsigned int vn) const
 
std::vector< dof_id_typen_dofs_per_processor (const unsigned int vn) const
 
processor_id_type dof_owner (const dof_id_type 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 override
 Fills the vector di with the global degree of freedom indices for the element.
 
void array_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.
 
void array_dof_indices (const Node *const node, std::vector< dof_id_type > &di, const unsigned int vn) const
 
template<typename DofIndicesFunctor >
void array_dof_indices (const DofIndicesFunctor &functor, std::vector< dof_id_type > &di, const unsigned int vn) const
 
template<typename ScalarDofsFunctor , typename FieldDofsFunctor >
void dof_indices (const Elem *const elem, std::vector< dof_id_type > &di, const unsigned int vn, ScalarDofsFunctor scalar_dofs_functor, FieldDofsFunctor field_dofs_functor, int p_level=-12345) const
 Retrieves degree of freedom indices for a given elem and then performs actions for these indices defined by the user-provided functors scalar_dofs_functor and field_dofs_functor.
 
void 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.
 
void dof_indices (const Node *const node, std::vector< dof_id_type > &di, const unsigned int vn) const override
 Fills the vector di with the global degree of freedom indices for the node, for one variable vn.
 
void dof_indices (const Elem &elem, unsigned int n, std::vector< dof_id_type > &di, const unsigned int vn) const
 Appends to the vector di the global degree of freedom indices for elem.node_ref(n), for one variable vn.
 
void old_dof_indices (const Elem &elem, unsigned int n, std::vector< dof_id_type > &di, const unsigned int vn) const
 Appends to the vector di the old global degree of freedom indices for elem.node_ref(n), for one variable vn.
 
void SCALAR_dof_indices (std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
 Fills the vector di with the global degree of freedom indices corresponding to the SCALAR variable vn.
 
bool semilocal_index (dof_id_type dof_index) const
 
bool all_semilocal_indices (const std::vector< dof_id_type > &dof_indices) const
 
bool local_index (dof_id_type dof_index) const
 
template<typename DofObjectSubclass >
bool is_evaluable (const DofObjectSubclass &obj, unsigned int var_num=libMesh::invalid_uint) const
 
void set_implicit_neighbor_dofs (bool implicit_neighbor_dofs)
 Allow the implicit_neighbor_dofs flag to be set programmatically.
 
void set_verify_dirichlet_bc_consistency (bool val)
 Set the _verify_dirichlet_bc_consistency flag.
 
bool use_coupled_neighbor_dofs (const MeshBase &mesh) const
 Tells other library functions whether or not this problem includes coupling between dofs in neighboring cells, as can currently be specified on the command line or inferred from the use of all discontinuous variables.
 
void 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.
 
template<typename T , std::enable_if_t< std::is_same_v< T, dof_id_type >||std::is_same_v< T, std::vector< dof_id_type > >, int > = 0>
void local_variable_indices (T &idx, const MeshBase &mesh, unsigned int var_num) const
 If T == dof_id_type, counts, if T == std::vector<dof_id_type>, fills an array of, those dof indices which belong to the given variable number and live on the current processor.
 
template<typename T , std::enable_if_t< std::is_same_v< T, dof_id_type >||std::is_same_v< T, std::vector< dof_id_type > >, int > = 0>
void local_variable_indices (T &idx, unsigned int var_num) const
 If T == dof_id_type, counts, if T == std::vector<dof_id_type>, fills an array of, those dof indices which belong to the given variable number and live on the current processor.
 
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)
 Rebuilds the raw degree of freedom and DofObject constraints, based on attached DirichletBoundary objects and on non-conforming interface in adapted meshes.
 
void allgather_recursive_constraints (MeshBase &)
 Gathers constraint equation dependencies from other processors.
 
void scatter_constraints (MeshBase &)
 Sends constraint equations to constraining processors.
 
void 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.
 
void process_constraints (MeshBase &)
 Postprocesses any constrained degrees of freedom to be constrained only in terms of unconstrained dofs, then adds unconstrained dofs to the send_list and prepares that for use.
 
void check_for_cyclic_constraints ()
 Throw an error if we detect any constraint loops, i.e.
 
void check_for_constraint_loops ()
 
void 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.
 
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)
 Adds a copy of the user-defined row to the constraint matrix, using an inhomogeneous right-hand-side for the adjoint constraint equation.
 
void add_constraint_row (const dof_id_type dof_number, const DofConstraintRow &constraint_row, const bool forbid_constraint_overwrite=true)
 Adds a copy of the user-defined row to the constraint matrix, using a homogeneous right-hand-side for the constraint equation.
 
DofConstraints::const_iterator constraint_rows_begin () const
 
DofConstraints::const_iterator constraint_rows_end () const
 
const DofConstraintsget_dof_constraints () const
 Provide a const accessor to the DofConstraints map.
 
void stash_dof_constraints ()
 
void unstash_dof_constraints ()
 
void swap_dof_constraints ()
 Similar to the stash/unstash_dof_constraints() API, but swaps _dof_constraints and _stashed_dof_constraints without asserting that the source or destination is empty first.
 
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_heterogeneous_adjoint_constraints (const unsigned int qoi_num) const
 
bool has_heterogenous_adjoint_constraints (const unsigned int qoi_num) const
 Backwards compatibility with misspelling.
 
Number has_heterogeneous_adjoint_constraint (const unsigned int qoi_num, const dof_id_type dof) const
 
Number has_heterogenous_adjoint_constraint (const unsigned int qoi_num, const dof_id_type dof) const
 Backwards compatibility with misspelling.
 
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
 Prints (from processor 0) all DoF and Node constraints.
 
std::string get_local_constraints (bool print_nonlocal=false) const
 Gets a string reporting all DoF and Node constraints local to this processor.
 
std::pair< Real, Realmax_constraint_error (const System &system, NumericVector< Number > *v=nullptr) const
 Tests the constrained degrees of freedom on the numeric vector v, which represents a solution defined on the mesh, returning a pair whose first entry is the maximum absolute error on a constrained DoF and whose second entry is the maximum relative error.
 
void constrain_element_matrix (DenseMatrix< Number > &matrix, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
 Constrains the element matrix.
 
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
 Constrains the element matrix.
 
void constrain_element_vector (DenseVector< Number > &rhs, std::vector< dof_id_type > &dofs, bool asymmetric_constraint_rows=true) const
 Constrains the element vector.
 
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
 Constrains the element matrix and vector.
 
void heterogeneously_constrain_element_matrix_and_vector (DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true, int qoi_index=-1) const
 Constrains the element matrix and vector.
 
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 heterogeneously_constrain_element_vector (const DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true, int qoi_index=-1) const
 Constrains the element vector.
 
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 heterogeneously_constrain_element_jacobian_and_residual (DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, NumericVector< Number > &solution_local) const
 Constrains the element Jacobian and residual.
 
void heterogeneously_constrain_element_residual (DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, NumericVector< Number > &solution_local) const
 Constrains the element residual.
 
void constrain_element_residual (DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, NumericVector< Number > &solution_local) const
 Constrains the element residual.
 
void constrain_element_dyad_matrix (DenseVector< Number > &v, DenseVector< Number > &w, std::vector< dof_id_type > &row_dofs, bool asymmetric_constraint_rows=true) const
 Constrains a dyadic element matrix B = v w'.
 
void 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.
 
void enforce_constraints_exactly (const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const
 Constrains the numeric vector v, which represents a solution defined on the mesh.
 
void enforce_adjoint_constraints_exactly (NumericVector< Number > &v, unsigned int q) const
 Heterogeneously constrains the numeric vector v, which represents an adjoint solution defined on the mesh for quantity fo interest q.
 
void enforce_constraints_on_residual (const NonlinearImplicitSystem &system, NumericVector< Number > *rhs, NumericVector< Number > const *solution, bool homogeneous=true) const
 
void enforce_constraints_on_jacobian (const NonlinearImplicitSystem &system, SparseMatrix< Number > *jac) const
 
void add_periodic_boundary (const PeriodicBoundaryBase &periodic_boundary)
 Adds a copy of the specified periodic boundary to the system.
 
void add_periodic_boundary (const PeriodicBoundaryBase &boundary, const PeriodicBoundaryBase &inverse_boundary)
 Add a periodic boundary pair.
 
bool is_periodic_boundary (const boundary_id_type boundaryid) const
 
PeriodicBoundariesget_periodic_boundaries ()
 
const PeriodicBoundariesget_periodic_boundaries () const
 
void add_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary)
 Adds a copy of the specified Dirichlet boundary to the system.
 
void 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.
 
void remove_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary)
 Removes the specified Dirichlet boundary from the system.
 
void remove_adjoint_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary, unsigned int q)
 Removes from the system the specified Dirichlet boundary for the adjoint equation defined by Quantity of interest index q.
 
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 check_dirichlet_bcid_consistency (const MeshBase &mesh, const DirichletBoundary &boundary) const
 Check that all the ids in dirichlet_bcids are actually present in the mesh.
 
void old_dof_indices (const Elem *const elem, std::vector< dof_id_type > &di, const unsigned int vn=libMesh::invalid_uint) const
 After a mesh is refined and repartitioned it is possible that the _send_list will need to be augmented.
 
void 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.
 
void reinit (MeshBase &mesh, const std::map< const Node *, std::set< subdomain_id_type > > &constraining_subdomains)
 Reinitialize the underlying data structures conformal to the current mesh.
 
virtual void clear () override
 Free all new memory associated with the object, but restore its original state, with the mesh pointer and any default ghosting.
 
void print_info (std::ostream &os=libMesh::out) const
 Prints summary info about the sparsity bandwidth and constraints.
 
std::string get_info () const
 Gets summary info about the sparsity bandwidth and constraints.
 
unsigned int sys_number () const
 
std::unique_ptr< SparsityPattern::Buildbuild_sparsity (const MeshBase &mesh, bool calculate_constrained=false, bool use_condensed_system=false) const
 Builds a sparsity pattern for matrices using the current degree-of-freedom numbering and coupling.
 
void should_p_refine (unsigned int g, bool p_refine)
 Set whether the given variable group should be p-refined on a p-refined Elem.
 
bool should_p_refine (unsigned int g) const
 Whether the given variable group should be p-refined.
 
bool should_p_refine_var (unsigned int var) const
 Whether the given variable should be p-refined.
 
void should_p_refine (FEFamily, bool)=delete
 
void should_p_refine (Order, bool)=delete
 
bool should_p_refine (FEFamily) const =delete
 
bool should_p_refine (Order) const =delete
 
void create_static_condensation (MeshBase &mesh, System &system)
 Add a static condensation class.
 
bool has_static_condensation () const
 Checks whether we have static condensation.
 
StaticCondensationDofMapget_static_condensation ()
 
const StaticCondensationDofMapget_static_condensation () const
 
void reinit_static_condensation ()
 Calls reinit on the static condensation map if it exists.
 
dof_id_type n_dofs () const
 
dof_id_type n_local_dofs () const
 
dof_id_type first_dof (const processor_id_type proc) const
 
dof_id_type first_dof () const
 
dof_id_type end_dof (const processor_id_type proc) const
 
dof_id_type end_dof () const
 
dof_id_type n_dofs_on_processor (const processor_id_type proc) const
 
dof_id_type n_old_dofs () const
 
dof_id_type first_old_dof (const processor_id_type proc) const
 
dof_id_type first_old_dof () const
 
dof_id_type end_old_dof (const processor_id_type proc) const
 
dof_id_type end_old_dof () 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 ()
 Gets a string containing the reference information.
 
static void print_info (std::ostream &out_stream=libMesh::out)
 Prints the reference information, by default to libMesh::out.
 
static unsigned int n_objects ()
 Prints the number of outstanding (created, but not yet destroyed) objects.
 
static void enable_print_counter_info ()
 Methods to enable/disable the reference counter output from print_info().
 
static void disable_print_counter_info ()
 

Public Attributes

CouplingMatrix_dof_coupling
 Degree of freedom coupling.
 

Protected Types

typedef std::map< std::string, std::pair< unsigned int, unsigned int > > Counts
 Data structure to log the information.
 

Protected Member Functions

std::size_t compute_dof_info (dof_id_type n_local_dofs)
 compute the key degree of freedom information given the local number of degrees of freedom on this process
 
void increment_constructor_count (const std::string &name) noexcept
 Increments the construction counter.
 
void increment_destructor_count (const std::string &name) noexcept
 Increments the destruction counter.
 

Protected Attributes

std::vector< dof_id_type_first_df
 First DOF index on processor p.
 
std::vector< dof_id_type_end_df
 Last DOF index (plus 1) on processor p.
 
dof_id_type _n_dfs
 Total number of degrees of freedom.
 
dof_id_type _n_old_dfs
 Total number of degrees of freedom on old dof objects.
 
std::vector< dof_id_type_first_old_df
 First old DOF index on processor p.
 
std::vector< dof_id_type_end_old_df
 Last old DOF index (plus 1) on processor p.
 
const Parallel::Communicator_communicator
 

Static Protected Attributes

static Counts _counts
 Actually holds the data.
 
static Threads::atomic< unsigned int_n_objects
 The number of objects.
 
static Threads::spin_mutex _mutex
 Mutual exclusion object to enable thread-safe reference counting.
 
static bool _enable_print_counter = true
 Flag to control whether reference count information is printed when print_info is called.
 

Private Types

typedef DofObject *(DofMap::* dofobject_accessor) (MeshBase &mesh, dof_id_type i) const
 A member function type like node_ptr() or elem_ptr().
 
typedef std::set< std::unique_ptr< CouplingMatrix >, Utility::CompareUnderlyingCouplingMatricesSet
 

Private Member Functions

const std::pair< unsigned int, unsigned int > & get_variable_array (unsigned int vi) const
 Retrieve the array variable bounds for a given variable vi.
 
void _dof_indices (const Elem &elem, int p_level, std::vector< dof_id_type > &di, const unsigned int vg, const unsigned int vig, const Node *const *nodes, unsigned int n_nodes, const unsigned int v #ifdef DEBUG, std::size_t &tot_size #endif) const
 Helper function that gets the dof indices on the current element for a non-SCALAR type variable, where the variable is identified by its variable group number vg and its offset vig from the first variable in that group.
 
template<typename FieldDofsFunctor >
void _dof_indices (const Elem &elem, int p_level, std::vector< dof_id_type > &di, const unsigned int vg, const unsigned int vig, const Node *const *nodes, unsigned int n_nodes, const unsigned int v, #ifdef DEBUG std::size_t &tot_size, #endif FieldDofsFunctor field_dofs_functor) const
 As above except a field_dofs_functor must be provided.
 
void _node_dof_indices (const Elem &elem, unsigned int n, const DofObject &obj, std::vector< dof_id_type > &di, const unsigned int vn) const
 Helper function that implements the element-nodal versions of dof_indices and old_dof_indices.
 
void invalidate_dofs (MeshBase &mesh) const
 Invalidates all active DofObject dofs for this system.
 
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)
 Helper function for distributing dofs in parallel.
 
std::map< const Node *, std::set< subdomain_id_type > > calculate_constraining_subdomains ()
 We may have mesh constraint rows with dependent nodes in one subdomain but dependency nodes in another subdomain, and we may have variables whose subdomain restriction includes the dependent subdomain but not the dependency.
 
void distribute_local_dofs_var_major (dof_id_type &next_free_dof, MeshBase &mesh, const std::map< const Node *, std::set< subdomain_id_type > > &constraining_subdomains)
 Distributes the global degrees of freedom, for dofs on this processor.
 
void distribute_local_dofs_node_major (dof_id_type &next_free_dof, MeshBase &mesh, const std::map< const Node *, std::set< subdomain_id_type > > &constraining_subdomains)
 Distributes the global degrees of freedom for dofs on this processor.
 
void distribute_scalar_dofs (dof_id_type &next_free_dof)
 
void assert_no_nodes_missed (MeshBase &mesh)
 
void add_neighbors_to_send_list (MeshBase &mesh)
 Adds entries to the _send_list vector corresponding to DoFs on elements neighboring the current processor.
 
void build_constraint_matrix (DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
 Build the constraint matrix C associated with the element degree of freedom indices elem_dofs.
 
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
 Build the constraint matrix C and the forcing vector H associated with the element degree of freedom indices elem_dofs.
 
void find_connected_dofs (std::vector< dof_id_type > &elem_dofs) const
 Finds all the DOFS associated with the element DOFs elem_dofs.
 
void find_connected_dof_objects (std::vector< const DofObject * > &objs) const
 Finds all the DofObjects associated with the set in objs.
 
void add_constraints_to_send_list ()
 Adds entries to the _send_list vector corresponding to DoFs which are dependencies for constraint equations on the current processor.
 
void process_mesh_constraint_rows (const MeshBase &mesh)
 Adds any spline constraints from the Mesh to our DoF constraints.
 

Static Private Member Functions

static void merge_ghost_functor_outputs (GhostingFunctor::map_type &elements_to_ghost, CouplingMatricesSet &temporary_coupling_matrices, const GhostingFunctorIterator &gf_begin, const GhostingFunctorIterator &gf_end, const MeshBase::const_element_iterator &elems_begin, const MeshBase::const_element_iterator &elems_end, processor_id_type p)
 

Private Attributes

bool _error_on_constraint_loop
 This flag indicates whether or not we do an opt-mode check for the presence of constraint loops, i.e.
 
bool _constrained_sparsity_construction
 This flag indicates whether or not we explicitly take constraint equations into account when computing a sparsity pattern.
 
std::vector< Variable_variables
 The variables in this system/degree of freedom map.
 
std::vector< VariableGroup_variable_groups
 The variable groups in this system/degree of freedom map.
 
std::vector< unsigned int_variable_group_numbers
 The variable group number for each variable.
 
std::unordered_map< unsigned int, unsigned int_var_to_vg
 A map from variable number to variable group number.
 
std::map< std::string, unsigned int, std::less<> > _variable_numbers
 The variable numbers corresponding to user-specified names, useful for name-based lookups.
 
std::vector< std::pair< unsigned int, unsigned int > > _array_variables
 Array variable information storage.
 
bool _identify_variable_groups = true
 true when VariableGroup structures should be automatically identified, false otherwise.
 
const unsigned int _sys_number
 The number of the system we manage DOFs for.
 
MeshBase_mesh
 The mesh that system uses.
 
std::vector< SparseMatrix< Number > * > _matrices
 Additional matrices handled by this object.
 
std::vector< dof_id_type_first_scalar_df
 First DOF index for SCALAR variable v, or garbage for non-SCALAR variable v.
 
std::vector< dof_id_type_send_list
 A list containing all the global DOF indices that affect the solution on my processor.
 
SparsityPattern::AugmentSparsityPattern_augment_sparsity_pattern
 Function object to call to add extra entries to the sparsity pattern.
 
void(* _extra_sparsity_function )(SparsityPattern::Graph &, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *)
 A function pointer to a function to call to add extra entries to the sparsity pattern.
 
void * _extra_sparsity_context
 A pointer associated with the extra sparsity that can optionally be passed in.
 
AugmentSendList_augment_send_list
 Function object to call to add extra entries to the send list.
 
void(* _extra_send_list_function )(std::vector< dof_id_type > &, void *)
 A function pointer to a function to call to add extra entries to the send list.
 
void * _extra_send_list_context
 A pointer associated with the extra send list that can optionally be passed in.
 
std::unique_ptr< DefaultCoupling_default_coupling
 The default coupling GhostingFunctor, used to implement standard libMesh sparsity pattern construction.
 
std::unique_ptr< DefaultCoupling_default_evaluating
 The default algebraic GhostingFunctor, used to implement standard libMesh send_list construction.
 
std::vector< GhostingFunctor * > _algebraic_ghosting_functors
 The list of all GhostingFunctor objects to be used when distributing ghosted vectors.
 
std::vector< GhostingFunctor * > _coupling_functors
 The list of all GhostingFunctor objects to be used when coupling degrees of freedom in matrix sparsity patterns.
 
std::map< GhostingFunctor *, std::shared_ptr< GhostingFunctor > > _shared_functors
 Hang on to references to any GhostingFunctor objects we were passed in shared_ptr form.
 
bool need_full_sparsity_pattern
 Default false; set to true if any attached matrix requires a full sparsity pattern.
 
std::unique_ptr< SparsityPattern::Build_sp
 The sparsity pattern of the global matrix.
 
dof_id_type _n_SCALAR_dofs
 The total number of SCALAR dofs associated to all SCALAR variables.
 
std::vector< dof_id_type_first_old_scalar_df
 First old DOF index for SCALAR variable v, or garbage for non-SCALAR variable v.
 
DofConstraints _dof_constraints
 Data structure containing DOF constraints.
 
DofConstraints _stashed_dof_constraints
 
DofConstraintValueMap _primal_constraint_values
 
AdjointDofConstraintValues _adjoint_constraint_values
 
NodeConstraints _node_constraints
 Data structure containing DofObject constraints.
 
std::unique_ptr< PeriodicBoundaries_periodic_boundaries
 Data structure containing periodic boundaries.
 
std::unique_ptr< DirichletBoundaries_dirichlet_boundaries
 Data structure containing Dirichlet functions.
 
std::vector< std::unique_ptr< DirichletBoundaries > > _adjoint_dirichlet_boundaries
 Data structure containing Dirichlet functions.
 
bool _implicit_neighbor_dofs_initialized
 Bools to indicate if we override the –implicit_neighbor_dofs commandline options.
 
bool _implicit_neighbor_dofs
 
bool _verify_dirichlet_bc_consistency
 Flag which determines whether we should do some additional checking of the consistency of the DirichletBoundary objects added by the user.
 
std::unique_ptr< StaticCondensationDofMap_sc
 Static condensation class.
 

Friends

class SparsityPattern::Build
 

Detailed Description

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

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

Definition at line 179 of file dof_map.h.

Member Typedef Documentation

◆ Counts

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

Data structure to log the information.

The log is identified by the class name.

Definition at line 119 of file reference_counter.h.

◆ CouplingMatricesSet

Definition at line 1999 of file dof_map.h.

◆ dofobject_accessor

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

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

Definition at line 1915 of file dof_map.h.

◆ GhostingFunctorIterator

typedef std::vector<GhostingFunctor*>::const_iterator libMesh::DofMap::GhostingFunctorIterator

Iterator type for coupling and algebraic ghosting functor ranges.

This has changed in the past and may change again; code should use auto or the type here.

Definition at line 315 of file dof_map.h.

Constructor & Destructor Documentation

◆ DofMap()

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

Constructor.

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

Definition at line 138 of file dof_map.C.

139 :
140 DofMapBase (mesh.comm()),
141 _dof_coupling(nullptr),
144 _variables(),
147 _sys_number(number),
148 _mesh(mesh),
149 _matrices(),
151 _send_list(),
155 _augment_send_list(nullptr),
158 _default_coupling(std::make_unique<DefaultCoupling>()),
159 _default_evaluating(std::make_unique<DefaultCoupling>()),
162#ifdef LIBMESH_ENABLE_AMR
164#endif
165#ifdef LIBMESH_ENABLE_CONSTRAINTS
170#endif
171#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
173#endif
174#ifdef LIBMESH_ENABLE_PERIODIC
175 , _periodic_boundaries(std::make_unique<PeriodicBoundaries>())
176#endif
177#ifdef LIBMESH_ENABLE_DIRICHLET
178 , _dirichlet_boundaries(std::make_unique<DirichletBoundaries>())
180#endif
184 _sc(nullptr)
185{
186 _matrices.clear();
187
188 _default_coupling->set_mesh(&_mesh);
189 _default_evaluating->set_mesh(&_mesh);
190 _default_evaluating->set_n_levels(1);
191
192#ifdef LIBMESH_ENABLE_PERIODIC
193 _default_coupling->set_periodic_boundaries(_periodic_boundaries.get());
194 _default_evaluating->set_periodic_boundaries(_periodic_boundaries.get());
195#endif
196
199}
DofMapBase(const Parallel::Communicator &comm)
std::vector< unsigned int > _variable_group_numbers
The variable group number for each variable.
Definition dof_map.h:2106
bool _implicit_neighbor_dofs
Definition dof_map.h:2318
bool _verify_dirichlet_bc_consistency
Flag which determines whether we should do some additional checking of the consistency of the Dirichl...
Definition dof_map.h:2330
DofConstraintValueMap _primal_constraint_values
Definition dof_map.h:2276
void * _extra_sparsity_context
A pointer associated with the extra sparsity that can optionally be passed in.
Definition dof_map.h:2176
std::vector< dof_id_type > _send_list
A list containing all the global DOF indices that affect the solution on my processor.
Definition dof_map.h:2159
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition dof_map.h:2302
const unsigned int _sys_number
The number of the system we manage DOFs for.
Definition dof_map.h:2135
std::vector< std::unique_ptr< DirichletBoundaries > > _adjoint_dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition dof_map.h:2308
AugmentSendList * _augment_send_list
Function object to call to add extra entries to the send list.
Definition dof_map.h:2181
std::unique_ptr< DefaultCoupling > _default_evaluating
The default algebraic GhostingFunctor, used to implement standard libMesh send_list construction.
Definition dof_map.h:2207
std::vector< Variable > _variables
The variables in this system/degree of freedom map.
Definition dof_map.h:2096
void * _extra_send_list_context
A pointer associated with the extra send list that can optionally be passed in.
Definition dof_map.h:2191
void(* _extra_sparsity_function)(SparsityPattern::Graph &, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *)
A function pointer to a function to call to add extra entries to the sparsity pattern.
Definition dof_map.h:2169
bool _constrained_sparsity_construction
This flag indicates whether or not we explicitly take constraint equations into account when computin...
Definition dof_map.h:2091
NodeConstraints _node_constraints
Data structure containing DofObject constraints.
Definition dof_map.h:2285
AdjointDofConstraintValues _adjoint_constraint_values
Definition dof_map.h:2278
SparsityPattern::AugmentSparsityPattern * _augment_sparsity_pattern
Function object to call to add extra entries to the sparsity pattern.
Definition dof_map.h:2164
dof_id_type _n_SCALAR_dofs
The total number of SCALAR dofs associated to all SCALAR variables.
Definition dof_map.h:2258
std::vector< dof_id_type > _first_old_scalar_df
First old DOF index for SCALAR variable v, or garbage for non-SCALAR variable v.
Definition dof_map.h:2266
void add_algebraic_ghosting_functor(GhostingFunctor &evaluable_functor, bool to_mesh=true)
Adds a functor which can specify algebraic ghosting requirements for use with distributed vectors.
Definition dof_map.C:2062
bool _implicit_neighbor_dofs_initialized
Bools to indicate if we override the –implicit_neighbor_dofs commandline options.
Definition dof_map.h:2317
bool need_full_sparsity_pattern
Default false; set to true if any attached matrix requires a full sparsity pattern.
Definition dof_map.h:2245
std::vector< SparseMatrix< Number > * > _matrices
Additional matrices handled by this object.
Definition dof_map.h:2147
CouplingMatrix * _dof_coupling
Degree of freedom coupling.
Definition dof_map.h:1741
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Data structure containing periodic boundaries.
Definition dof_map.h:2294
std::unique_ptr< DefaultCoupling > _default_coupling
The default coupling GhostingFunctor, used to implement standard libMesh sparsity pattern constructio...
Definition dof_map.h:2199
MeshBase & _mesh
The mesh that system uses.
Definition dof_map.h:2140
void(* _extra_send_list_function)(std::vector< dof_id_type > &, void *)
A function pointer to a function to call to add extra entries to the send list.
Definition dof_map.h:2186
std::vector< VariableGroup > _variable_groups
The variable groups in this system/degree of freedom map.
Definition dof_map.h:2101
void add_coupling_functor(GhostingFunctor &coupling_functor, bool to_mesh=true)
Adds a functor which can specify coupling requirements for creation of sparse matrices.
Definition dof_map.C:2005
bool _error_on_constraint_loop
This flag indicates whether or not we do an opt-mode check for the presence of constraint loops,...
Definition dof_map.h:2085
std::vector< dof_id_type > _first_scalar_df
First DOF index for SCALAR variable v, or garbage for non-SCALAR variable v.
Definition dof_map.h:2153
DofConstraints _stashed_dof_constraints
Definition dof_map.h:2274
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition dof_map.h:2274
std::unique_ptr< StaticCondensationDofMap > _sc
Static condensation class.
Definition dof_map.h:2333
MeshBase & mesh

References _default_coupling, _default_evaluating, _matrices, _mesh, _periodic_boundaries, add_algebraic_ghosting_functor(), add_coupling_functor(), and libMesh::DofMapBase::clear().

◆ ~DofMap()

libMesh::DofMap::~DofMap ( )

Destructor.

Definition at line 204 of file dof_map.C.

205{
206 this->clear();
207
208 // clear() resets all but the default DofMap-based functors. We
209 // need to remove those from the mesh too before we die.
212}
virtual void clear() override
Free all new memory associated with the object, but restore its original state, with the mesh pointer...
Definition dof_map.C:871
void remove_ghosting_functor(GhostingFunctor &ghosting_functor)
Removes a functor which was previously added to the set of ghosting functors.
Definition mesh_base.C:1100

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

Member Function Documentation

◆ _dof_indices() [1/2]

void libMesh::DofMap::_dof_indices ( const Elem elem,
int  p_level,
std::vector< dof_id_type > &  di,
const unsigned int  vg,
const unsigned int  vig,
const Node *const *  nodes,
unsigned int  n_nodes,
const unsigned int v #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, where the variable is identified by its variable group number vg and its offset vig from the first variable in that group.

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

Definition at line 2573 of file dof_map.C.

2586{
2587 _dof_indices(elem,
2588 p_level,
2589 di,
2590 vg,
2591 vig,
2592 nodes,
2593 n_nodes,
2594 v,
2595#ifdef DEBUG
2596 tot_size,
2597#endif
2598 [](const Elem &,
2599 unsigned int,
2600 unsigned int,
2601 std::vector<dof_id_type> & functor_di,
2602 const dof_id_type dof) { functor_di.push_back(dof); });
2603}
void _dof_indices(const Elem &elem, int p_level, std::vector< dof_id_type > &di, const unsigned int vg, const unsigned int vig, const Node *const *nodes, unsigned int n_nodes, const unsigned int v #ifdef DEBUG, std::size_t &tot_size #endif) const
Helper function that gets the dof indices on the current element for a non-SCALAR type variable,...
Definition dof_map.C:2573
uint8_t dof_id_type
Definition id_types.h:67
const dof_id_type n_nodes
Definition tecplot_io.C:67

References n_nodes.

Referenced by dof_indices().

◆ _dof_indices() [2/2]

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

As above except a field_dofs_functor must be provided.

This method is useful when the caller wants to do more than simply fill a degree of freedom container

Parameters
field_dofs_functorThis functor has the interface: void field_dofs_functor(const Elem & elem, const unsigned int node_num, const unsigned int var_num, std::vector<dof_id_type> & di, const dof_id_type field_dof) where field_dof represents a field degree of freedom to act on and is associated with node_num and var_num. If the degree of freedom is elemental than node_num will be invalid_uint. di is the degree of freedom container provided to the _dof_indices method

Definition at line 2619 of file dof_map.h.

2631{
2632 const VariableGroup & var = this->variable_group(vg);
2633
2634 if (var.active_on_subdomain(elem.subdomain_id()))
2635 {
2636 const ElemType type = elem.type();
2637 const unsigned int sys_num = this->sys_number();
2638#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2639 const bool is_inf = elem.infinite();
2640#endif
2641
2642 const bool extra_hanging_dofs =
2644
2645 FEType fe_type = var.type();
2646
2647 const bool add_p_level = fe_type.p_refinement;
2648
2649#ifdef DEBUG
2650 // The number of dofs per element is non-static for subdivision FE
2651 if (var.type().family == SUBDIVISION)
2652 tot_size += n_nodes;
2653 else
2654 // FIXME: Is the passed-in p_level just elem.p_level()? If so,
2655 // this seems redundant.
2656 tot_size += FEInterface::n_dofs(fe_type, add_p_level*p_level, &elem);
2657#endif
2658
2659 // The total Order is not required when getting the function
2660 // pointer, it is only needed when the function is called (see
2661 // below).
2664
2665 // Get the node-based DOF numbers
2666 for (unsigned int n=0; n != n_nodes; n++)
2667 {
2668 const Node & node = *nodes[n];
2669
2670 // Cache the intermediate lookups that are common to every
2671 // component
2672#ifdef DEBUG
2673 const std::pair<unsigned int, unsigned int>
2674 vg_and_offset = node.var_to_vg_and_offset(sys_num,v);
2675 libmesh_assert_equal_to (vg, vg_and_offset.first);
2676 libmesh_assert_equal_to (vig, vg_and_offset.second);
2677#endif
2678 const unsigned int n_comp = node.n_comp_group(sys_num,vg);
2679
2680 // There is a potential problem with h refinement. Imagine a
2681 // quad9 that has a linear FE on it. Then, on the hanging side,
2682 // it can falsely identify a DOF at the mid-edge node. This is why
2683 // we go through FEInterface instead of node.n_comp() directly.
2684 const unsigned int nc =
2685#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2686 is_inf ?
2687 FEInterface::n_dofs_at_node(fe_type, add_p_level*p_level, &elem, n) :
2688#endif
2689 ndan (type, fe_type.order + add_p_level*p_level, n);
2690
2691 // If this is a non-vertex on a hanging node with extra
2692 // degrees of freedom, we use the non-vertex dofs (which
2693 // come in reverse order starting from the end, to
2694 // simplify p refinement)
2695 if (extra_hanging_dofs && !elem.is_vertex(n))
2696 {
2697 const int dof_offset = n_comp - nc;
2698
2699 // We should never have fewer dofs than necessary on a
2700 // node unless we're getting indices on a parent element,
2701 // and we should never need the indices on such a node
2702 if (dof_offset < 0)
2703 {
2704 libmesh_assert(!elem.active());
2705 di.resize(di.size() + nc, DofObject::invalid_id);
2706 }
2707 else
2708 for (int i=int(n_comp)-1; i>=dof_offset; i--)
2709 {
2710 const dof_id_type d =
2711 node.dof_number(sys_num, vg, vig, i, n_comp);
2712 libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2713 field_dofs_functor(elem, n, v, di, d);
2714 }
2715 }
2716 // If this is a vertex or an element without extra hanging
2717 // dofs, our dofs come in forward order coming from the
2718 // beginning
2719 else
2720 {
2721 // We have a good component index only if it's being
2722 // used on this FE type (nc) *and* it's available on
2723 // this DofObject (n_comp).
2724 const unsigned int good_nc = std::min(n_comp, nc);
2725 for (unsigned int i=0; i!=good_nc; ++i)
2726 {
2727 const dof_id_type d =
2728 node.dof_number(sys_num, vg, vig, i, n_comp);
2729 libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2730 libmesh_assert_less (d, this->n_dofs());
2731 field_dofs_functor(elem, n, v, di, d);
2732 }
2733
2734 // With fewer good component indices than we need, e.g.
2735 // due to subdomain expansion, the remaining expected
2736 // indices are marked invalid.
2737 if (n_comp < nc)
2738 for (unsigned int i=n_comp; i!=nc; ++i)
2739 di.push_back(DofObject::invalid_id);
2740 }
2741 }
2742
2743 // If there are any element-based DOF numbers, get them
2744 const unsigned int nc = FEInterface::n_dofs_per_elem(fe_type, add_p_level*p_level, &elem);
2745
2746 // We should never have fewer dofs than necessary on an
2747 // element unless we're getting indices on a parent element
2748 // (and we should never need those indices) or off-domain for a
2749 // subdomain-restricted variable (where invalid_id is the
2750 // correct thing to return)
2751 if (nc != 0)
2752 {
2753 const unsigned int n_comp = elem.n_comp_group(sys_num,vg);
2754 if (elem.n_systems() > sys_num && nc <= n_comp)
2755 {
2756 for (unsigned int i=0; i<nc; i++)
2757 {
2758 const dof_id_type d =
2759 elem.dof_number(sys_num, vg, vig, i, n_comp);
2760 libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2761
2762 field_dofs_functor(elem, invalid_uint, v, di, d);
2763 }
2764 }
2765 else
2766 {
2767 libmesh_assert(!elem.active() || fe_type.family == LAGRANGE || fe_type.family == SUBDIVISION);
2768 di.resize(di.size() + nc, DofObject::invalid_id);
2769 }
2770 }
2771 }
2772}
dof_id_type n_dofs() const
unsigned int sys_number() const
Definition dof_map.h:2340
const VariableGroup & variable_group(const unsigned int c) const
Definition dof_map.h:2348
static constexpr dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition dof_object.h:473
static n_dofs_at_node_ptr n_dofs_at_node_function(const unsigned int dim, const FEType &fe_t)
unsigned int(* n_dofs_at_node_ptr)(const ElemType, const Order, const unsigned int)
static unsigned int n_dofs(const unsigned int dim, const FEType &fe_t, const ElemType t)
static unsigned int n_dofs_at_node(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int n)
static unsigned int n_dofs_per_elem(const unsigned int dim, const FEType &fe_t, const ElemType t)
static bool extra_hanging_dofs(const FEType &fe_t)
ElemType
Defines an enum for geometric element types.
libmesh_assert(ctx)
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition libmesh.h:303

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

◆ _node_dof_indices()

void libMesh::DofMap::_node_dof_indices ( const Elem elem,
unsigned int  n,
const DofObject obj,
std::vector< dof_id_type > &  di,
const unsigned int  vn 
) const
private

Helper function that implements the element-nodal versions of dof_indices and old_dof_indices.

Definition at line 2491 of file dof_map.C.

2496{
2497 // Half of this is a cut and paste of _dof_indices code below, but
2498 // duplication actually seems cleaner than creating a helper
2499 // function with a million arguments and hoping the compiler inlines
2500 // it properly into one of our most highly trafficked functions.
2501
2502 // dof_indices() is a relatively light-weight function; the cost of
2503 // the logging code itself is roughly on par with the time required
2504 // to call dof_indices().
2505 // LOG_SCOPE("_node_dof_indices()", "DofMap");
2506
2507 const unsigned int sys_num = this->sys_number();
2508 const auto [vg, vig] =
2509 obj.var_to_vg_and_offset(sys_num,vn);
2510 const unsigned int n_comp = obj.n_comp_group(sys_num,vg);
2511
2512 const VariableGroup & var = this->variable_group(vg);
2513 FEType fe_type = var.type();
2514 const bool extra_hanging_dofs =
2516
2517 const bool add_p_level = fe_type.p_refinement;
2518
2519 // There is a potential problem with h refinement. Imagine a
2520 // quad9 that has a linear FE on it. Then, on the hanging side,
2521 // it can falsely identify a DOF at the mid-edge node. This is why
2522 // we go through FEInterface instead of obj->n_comp() directly.
2523 const unsigned int nc =
2524 FEInterface::n_dofs_at_node(fe_type, &elem, n, add_p_level);
2525
2526 // If this is a non-vertex on a hanging node with extra
2527 // degrees of freedom, we use the non-vertex dofs (which
2528 // come in reverse order starting from the end, to
2529 // simplify p refinement)
2530 if (extra_hanging_dofs && nc && !elem.is_vertex(n))
2531 {
2532 const int dof_offset = n_comp - nc;
2533
2534 // We should never have fewer dofs than necessary on a
2535 // node unless we're getting indices on a parent element,
2536 // and we should never need the indices on such a node
2537 if (dof_offset < 0)
2538 {
2539 libmesh_assert(!elem.active());
2540 di.resize(di.size() + nc, DofObject::invalid_id);
2541 }
2542 else
2543 for (unsigned int i = dof_offset; i != n_comp; ++i)
2544 {
2545 const dof_id_type d =
2546 obj.dof_number(sys_num, vg, vig, i, n_comp);
2547 libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2548 di.push_back(d);
2549 }
2550 }
2551 // If this is a vertex or an element without extra hanging
2552 // dofs, our dofs come in forward order coming from the
2553 // beginning. But we still might not have all those dofs, in cases
2554 // where a subdomain-restricted variable just had its subdomain
2555 // expanded.
2556 else
2557 {
2558 const unsigned int good_nc =
2559 std::min(static_cast<unsigned int>(n_comp), nc);
2560 for (unsigned int i=0; i != good_nc; ++i)
2561 {
2562 const dof_id_type d =
2563 obj.dof_number(sys_num, vg, vig, i, n_comp);
2564 libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2565 di.push_back(d);
2566 }
2567 for (unsigned int i=good_nc; i != nc; ++i)
2568 di.push_back(DofObject::invalid_id);
2569 }
2570}

References libMesh::Elem::active(), libMesh::DofObject::dof_number(), libMesh::Elem::is_vertex(), libMesh::libmesh_assert(), libMesh::DofObject::n_comp_group(), libMesh::FEType::p_refinement, libMesh::Variable::type(), and libMesh::DofObject::var_to_vg_and_offset().

◆ add_adjoint_constraint_row()

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

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

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

Definition at line 2212 of file dof_map_constraints.C.

2217{
2218 // Optionally allow the user to overwrite constraints. Defaults to false.
2219 if (forbid_constraint_overwrite)
2220 {
2221 libmesh_error_msg_if(!this->is_constrained_dof(dof_number),
2222 "ERROR: DOF " << dof_number << " has no corresponding primal constraint!");
2223#ifndef NDEBUG
2224 // No way to do this without a non-normalized tolerance?
2225
2226 // // If the user passed in more than just the rhs, let's check the
2227 // // coefficients for consistency
2228 // if (!constraint_row.empty())
2229 // {
2230 // DofConstraintRow row = _dof_constraints[dof_number];
2231 // for (const auto & [dof, val] : row)
2232 // libmesh_assert(constraint_row.find(dof)->second == val);
2233 // }
2234 //
2235 // if (_adjoint_constraint_values[qoi_index].find(dof_number) !=
2236 // _adjoint_constraint_values[qoi_index].end())
2237 // libmesh_assert_equal_to(_adjoint_constraint_values[qoi_index][dof_number],
2238 // constraint_rhs);
2239
2240#endif
2241 }
2242
2243 // Creates the map of rhs values if it doesn't already exist; then
2244 // adds the current value to that map
2245
2246 // Store the rhs value in the map
2247 _adjoint_constraint_values[qoi_index].insert_or_assign(dof_number, constraint_rhs);
2248}
bool is_constrained_dof(const dof_id_type dof) const
Definition dof_map.h:2426

References _adjoint_constraint_values, and is_constrained_dof().

◆ add_adjoint_dirichlet_boundary()

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

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

Definition at line 5442 of file dof_map_constraints.C.

5444{
5445 unsigned int old_size = cast_int<unsigned int>
5447 for (unsigned int i = old_size; i <= qoi_index; ++i)
5448 _adjoint_dirichlet_boundaries.push_back(std::make_unique<DirichletBoundaries>());
5449
5450 // Make copy of DirichletBoundary, owned by _adjoint_dirichlet_boundaries
5451 _adjoint_dirichlet_boundaries[qoi_index]->push_back
5452 (std::make_unique<DirichletBoundary>(dirichlet_boundary));
5453}

References _adjoint_dirichlet_boundaries.

Referenced by PoissonSystem::init_data(), and SigmaPhysics::init_data().

◆ add_algebraic_ghosting_functor() [1/2]

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

Adds a functor which can specify algebraic ghosting requirements for use with distributed vectors.

Degrees of freedom on other processors which match the elements and variables returned by these functors will be added to the send_list, and the elements on other processors will be ghosted on a distributed mesh, so that the elements can always be found and the solutions on them will always be evaluable.

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

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

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

Definition at line 2062 of file dof_map.C.

2064{
2065 // We used to implicitly support duplicate inserts to std::set
2066#ifdef LIBMESH_ENABLE_DEPRECATED
2068 (std::remove(_algebraic_ghosting_functors.begin(),
2070 &evaluable_functor),
2072#endif
2073
2074 // We shouldn't have two copies of the same functor
2077 &evaluable_functor) ==
2079
2080 _algebraic_ghosting_functors.push_back(&evaluable_functor);
2081 evaluable_functor.set_mesh(&_mesh);
2082 if (to_mesh)
2083 _mesh.add_ghosting_functor(evaluable_functor);
2084}
std::vector< GhostingFunctor * > _algebraic_ghosting_functors
The list of all GhostingFunctor objects to be used when distributing ghosted vectors.
Definition dof_map.h:2220
void add_ghosting_functor(GhostingFunctor &ghosting_functor)
Adds a functor which can specify ghosting requirements for use on distributed meshes.
Definition mesh_base.C:1078

References libMesh::libmesh_assert(), and libMesh::GhostingFunctor::set_mesh().

Referenced by add_algebraic_ghosting_functor(), DofMap(), main(), OverlappingAlgebraicGhostingTest::run_ghosting_test(), SlitMeshRefinedSystemTest::setUp(), PointNeighborCouplingTest::testCoupling(), and EquationSystemsTest::testDisableDefaultGhosting().

◆ add_algebraic_ghosting_functor() [2/2]

void libMesh::DofMap::add_algebraic_ghosting_functor ( std::shared_ptr< GhostingFunctor evaluable_functor,
bool  to_mesh = true 
)
inline

Adds a functor which can specify algebraic ghosting requirements for use with distributed vectors.

GhostingFunctor memory when using this method is managed by the shared_ptr mechanism.

Definition at line 413 of file dof_map.h.

415 { _shared_functors[evaluable_functor.get()] = evaluable_functor;
416 this->add_algebraic_ghosting_functor(*evaluable_functor, to_mesh); }
std::map< GhostingFunctor *, std::shared_ptr< GhostingFunctor > > _shared_functors
Hang on to references to any GhostingFunctor objects we were passed in shared_ptr form.
Definition dof_map.h:2239

References _shared_functors, and add_algebraic_ghosting_functor().

◆ add_constraint_row() [1/2]

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

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

By default, produces an error if the DOF was already constrained.

Definition at line 1156 of file dof_map.h.

1159 { 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)
Adds a copy of the user-defined row to the constraint matrix, using an inhomogeneous right-hand-side ...

References add_constraint_row().

◆ add_constraint_row() [2/2]

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

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

Definition at line 2180 of file dof_map_constraints.C.

2184{
2185 // Optionally allow the user to overwrite constraints. Defaults to false.
2186 libmesh_error_msg_if(forbid_constraint_overwrite && this->is_constrained_dof(dof_number),
2187 "ERROR: DOF " << dof_number << " was already constrained!");
2188
2189 libmesh_assert_less(dof_number, this->n_dofs());
2190
2191 // There is an implied "1" on the diagonal of the constraint row, and the user
2192 // should not try to manually set _any_ value on the diagonal.
2193 libmesh_assert_msg(!constraint_row.count(dof_number),
2194 "Error: constraint_row for dof " << dof_number <<
2195 " should not contain an entry for dof " << dof_number);
2196
2197#ifndef NDEBUG
2198 for (const auto & pr : constraint_row)
2199 libmesh_assert_less(pr.first, this->n_dofs());
2200#endif
2201
2202 // Store the constraint_row in the map
2203 _dof_constraints.insert_or_assign(dof_number, constraint_row);
2204
2205 std::pair<DofConstraintValueMap::iterator, bool> rhs_it =
2206 _primal_constraint_values.emplace(dof_number, constraint_rhs);
2207 if (!rhs_it.second)
2208 rhs_it.first->second = constraint_rhs;
2209}

References _dof_constraints, _primal_constraint_values, is_constrained_dof(), and n_dofs().

Referenced by add_constraint_row(), MyConstraint::constrain(), libMesh::VariationalSmootherConstraint::constrain_node_to_line(), libMesh::VariationalSmootherConstraint::constrain_node_to_plane(), libMesh::VariationalSmootherConstraint::fix_node(), and process_mesh_constraint_rows().

◆ add_constraints_to_send_list()

void libMesh::DofMap::add_constraints_to_send_list ( )
private

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

Definition at line 5311 of file dof_map_constraints.C.

5312{
5313 // This function must be run on all processors at once
5314 parallel_object_only();
5315
5316 // Return immediately if there's nothing to gather
5317 if (this->n_processors() == 1)
5318 return;
5319
5320 // We might get to return immediately if none of the processors
5321 // found any constraints
5322 unsigned int has_constraints = !_dof_constraints.empty();
5323 this->comm().max(has_constraints);
5324 if (!has_constraints)
5325 return;
5326
5327 auto add_row = [this](const DofConstraintRow & constraint_row) {
5328 for (const auto & j : constraint_row)
5329 {
5330 dof_id_type constraint_dependency = j.first;
5331
5332 // No point in adding one of our own dofs to the send_list
5333 if (this->local_index(constraint_dependency))
5334 continue;
5335
5336 _send_list.push_back(constraint_dependency);
5337 }
5338 };
5339
5340 // We usually only need dependencies of our own constrained dofs
5341 for (const auto & [constrained_dof, constraint_row] : _dof_constraints)
5342 if (this->local_index(constrained_dof))
5343 add_row(constraint_row);
5344
5345 // If we only need constraint DoFs constraining DoFs which are
5346 // algebraically local, we're done.
5347 if (!this->has_static_condensation())
5348 return;
5349
5350 // If we use StaticCondensation, though, we may need constraint DoFs
5351 // constraining DoFs which are not local (they're on someone else's
5352 // node) but which are supported on local elements. Let's get those
5353 // too if we have to.
5354 //
5355 // We'll potentially be hitting the same constrained DoFs from
5356 // multiple directions.
5357 std::unordered_set<dof_id_type> extra_dependencies;
5358 for (auto & elem : this->get_static_condensation().mesh().active_local_element_ptr_range())
5359 {
5360 std::vector<dof_id_type> di;
5361 this->dof_indices (elem, di);
5362 for (const auto & dof_id : di)
5363 if (!this->local_index(dof_id))
5364 if (auto pos = _dof_constraints.find(dof_id);
5365 pos != _dof_constraints.end())
5366 add_row(pos->second);
5367 }
5368}
void max(const T &r, T &o, Request &req) const
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition dof_map.C:2201
StaticCondensationDofMap & get_static_condensation()
Definition dof_map.h:2859
bool local_index(dof_id_type dof_index) const
Definition dof_map.h:967
bool has_static_condensation() const
Checks whether we have static condensation.
Definition dof_map.h:1797
const Parallel::Communicator & comm() const
processor_id_type n_processors() const
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
A row of the Dof constraint matrix.
Definition dof_map.h:100

References _dof_constraints, _send_list, libMesh::ParallelObject::comm(), dof_indices(), get_static_condensation(), has_static_condensation(), local_index(), libMesh::Parallel::Communicator::max(), libMesh::StaticCondensationDofMap::mesh(), and libMesh::ParallelObject::n_processors().

Referenced by process_constraints().

◆ add_coupling_functor() [1/2]

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

Adds a functor which can specify coupling requirements for creation of sparse matrices.

Degree of freedom pairs which match the elements and variables returned by these functors will be added to the sparsity pattern, and the degrees of freedom which live on other processors will be added to the send_list for use on ghosted vectors, and the elements which live on other processors will be ghosted on a distributed mesh.

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

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

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

Definition at line 2005 of file dof_map.C.

2007{
2008 // We used to implicitly support duplicate inserts to std::set
2009#ifdef LIBMESH_ENABLE_DEPRECATED
2010 _coupling_functors.erase
2011 (std::remove(_coupling_functors.begin(),
2012 _coupling_functors.end(),
2013 &coupling_functor),
2014 _coupling_functors.end());
2015#endif
2016
2017 // We shouldn't have two copies of the same functor
2018 libmesh_assert(std::find(_coupling_functors.begin(),
2019 _coupling_functors.end(),
2020 &coupling_functor) ==
2021 _coupling_functors.end());
2022
2023 _coupling_functors.push_back(&coupling_functor);
2024 coupling_functor.set_mesh(&_mesh);
2025 if (to_mesh)
2026 _mesh.add_ghosting_functor(coupling_functor);
2027}
std::vector< GhostingFunctor * > _coupling_functors
The list of all GhostingFunctor objects to be used when coupling degrees of freedom in matrix sparsit...
Definition dof_map.h:2233

References libMesh::libmesh_assert(), and libMesh::GhostingFunctor::set_mesh().

Referenced by add_coupling_functor(), DofMap(), NonManifoldCouplingTestBase::init_es(), main(), OverlappingCouplingGhostingTest::run_sparsity_pattern_test(), EquationSystemsTest::testDisableDefaultGhosting(), and SystemsTest::testDofCouplingWithVarGroups().

◆ add_coupling_functor() [2/2]

void libMesh::DofMap::add_coupling_functor ( std::shared_ptr< GhostingFunctor coupling_functor,
bool  to_mesh = true 
)
inline

Adds a functor which can specify coupling requirements for creation of sparse matrices.

GhostingFunctor memory when using this method is managed by the shared_ptr mechanism.

Definition at line 351 of file dof_map.h.

353 { _shared_functors[coupling_functor.get()] = coupling_functor;
354 this->add_coupling_functor(*coupling_functor, to_mesh); }

References _shared_functors, and add_coupling_functor().

◆ add_default_ghosting()

void libMesh::DofMap::add_default_ghosting ( )

Add the default functor(s) for coupling and algebraic ghosting.

User-added ghosting functors will be unaffected.

Definition at line 1996 of file dof_map.C.

1997{
2000}
DefaultCoupling & default_coupling()
Default coupling functor.
Definition dof_map.h:378
DefaultCoupling & default_algebraic_ghosting()
Default algebraic ghosting functor.
Definition dof_map.h:440

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

◆ add_dirichlet_boundary()

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

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

The constraints implied by DirichletBoundary objects are imposed in the same order in which DirichletBoundary objects are added to the DofMap. When multiple DirichletBoundary objects would impose competing constraints on a given DOF, the first DirichletBoundary to constrain the DOF "wins". This distinction is important when e.g. two surfaces (sidesets) intersect. The nodes on the intersection will be constrained according to whichever sideset's DirichletBoundary object was added to the DofMap first.

Definition at line 5436 of file dof_map_constraints.C.

5437{
5438 _dirichlet_boundaries->push_back(std::make_unique<DirichletBoundary>(dirichlet_boundary));
5439}

References _dirichlet_boundaries.

Referenced by libMesh::DifferentiableSystem::add_dot_var_dirichlet_bcs(), assemble_and_solve(), CoupledSystem::init_data(), HeatSystem::init_data(), PoissonSystem::init_data(), NavierSystem::init_data(), ElasticitySystem::init_data(), SimpleRBConstruction::init_data(), ElasticityRBConstruction::init_data(), SigmaPhysics::init_data(), LaplaceSystem::init_dirichlet_bcs(), main(), set_lid_driven_bcs(), set_poiseuille_bcs(), set_stagnation_bcs(), set_system_parameters(), MeshAssignTest::testMeshMoveAssign(), PeriodicBCTest::testPeriodicBC(), BoundaryInfoTest::testShellFaceConstraints(), DisjointNeighborTest::testTempJump(), and DisjointNeighborTest::testTempJumpRefine().

◆ add_neighbors_to_send_list()

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

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

Definition at line 1687 of file dof_map.C.

1688{
1689 LOG_SCOPE("add_neighbors_to_send_list()", "DofMap");
1690
1691 // Return immediately if there's no ghost data
1692 if (this->n_processors() == 1)
1693 return;
1694
1695 const unsigned int n_var = this->n_variables();
1696
1697 MeshBase::const_element_iterator local_elem_it
1698 = mesh.active_local_elements_begin();
1699 const MeshBase::const_element_iterator local_elem_end
1700 = mesh.active_local_elements_end();
1701
1702 GhostingFunctor::map_type elements_to_send;
1703 DofMap::CouplingMatricesSet temporary_coupling_matrices;
1704
1705 // We need to add dofs to the send list if they've been directly
1706 // requested by an algebraic ghosting functor or they've been
1707 // indirectly requested by a coupling functor.
1708 this->merge_ghost_functor_outputs(elements_to_send,
1709 temporary_coupling_matrices,
1712 local_elem_it, local_elem_end, mesh.processor_id());
1713
1714 this->merge_ghost_functor_outputs(elements_to_send,
1715 temporary_coupling_matrices,
1717 this->coupling_functors_end(),
1718 local_elem_it, local_elem_end, mesh.processor_id());
1719
1720 // Making a list of non-zero coupling matrix columns is an
1721 // O(N_var^2) operation. We cache it so we only have to do it once
1722 // per CouplingMatrix and not once per element.
1723 std::map<const CouplingMatrix *, std::vector<unsigned int>>
1724 column_variable_lists;
1725
1726 for (const auto & [partner, ghost_coupling] : elements_to_send)
1727 {
1728 // We asked ghosting functors not to give us local elements
1729 libmesh_assert_not_equal_to
1730 (partner->processor_id(), this->processor_id());
1731
1732 // Loop over any present coupling matrix column variables if we
1733 // have a coupling matrix, or just add all variables to
1734 // send_list if not.
1735 if (ghost_coupling)
1736 {
1737 libmesh_assert_equal_to (ghost_coupling->size(), n_var);
1738
1739 // Try to find a cached list of column variables.
1740 std::map<const CouplingMatrix *, std::vector<unsigned int>>::const_iterator
1741 column_variable_list = column_variable_lists.find(ghost_coupling);
1742
1743 // If we didn't find it, then we need to create it.
1744 if (column_variable_list == column_variable_lists.end())
1745 {
1746 auto inserted_variable_list_pair =
1747 column_variable_lists.emplace(ghost_coupling, std::vector<unsigned int>());
1748 column_variable_list = inserted_variable_list_pair.first;
1749
1750 std::vector<unsigned int> & new_variable_list =
1751 inserted_variable_list_pair.first->second;
1752
1753 std::vector<unsigned char> has_variable(n_var, false);
1754
1755 for (unsigned int vi = 0; vi != n_var; ++vi)
1756 {
1757 ConstCouplingRow ccr(vi, *ghost_coupling);
1758
1759 for (const auto & vj : ccr)
1760 has_variable[vj] = true;
1761 }
1762 for (unsigned int vj = 0; vj != n_var; ++vj)
1763 {
1764 if (has_variable[vj])
1765 new_variable_list.push_back(vj);
1766 }
1767 }
1768
1769 const std::vector<unsigned int> & variable_list =
1770 column_variable_list->second;
1771
1772 for (const auto & vj : variable_list)
1773 {
1774 std::vector<dof_id_type> di;
1775 this->dof_indices (partner, di, vj);
1776
1777 // Insert the remote DOF indices into the send list
1778 for (auto d : di)
1779 if (d != DofObject::invalid_id &&
1780 !this->local_index(d))
1781 {
1782 libmesh_assert_less(d, this->n_dofs());
1783 _send_list.push_back(d);
1784 }
1785 }
1786 }
1787 else
1788 {
1789 std::vector<dof_id_type> di;
1790 this->dof_indices (partner, di);
1791
1792 // Insert the remote DOF indices into the send list
1793 for (const auto & dof : di)
1794 if (dof != DofObject::invalid_id &&
1795 !this->local_index(dof))
1796 {
1797 libmesh_assert_less(dof, this->n_dofs());
1798 _send_list.push_back(dof);
1799 }
1800 }
1801
1802 }
1803
1804 // We're now done with any merged coupling matrices we had to create.
1805 temporary_coupling_matrices.clear();
1806
1807 //-------------------------------------------------------------------------
1808 // Our coupling functors added dofs from neighboring elements to the
1809 // send list, but we may still need to add non-local dofs from local
1810 // elements.
1811 //-------------------------------------------------------------------------
1812
1813 // Loop over the active local elements, adding all active elements
1814 // that neighbor an active local element to the send list.
1815 for ( ; local_elem_it != local_elem_end; ++local_elem_it)
1816 {
1817 const Elem * elem = *local_elem_it;
1818
1819 std::vector<dof_id_type> di;
1820 this->dof_indices (elem, di);
1821
1822 // Insert the remote DOF indices into the send list
1823 for (const auto & dof : di)
1824 if (dof != DofObject::invalid_id &&
1825 !this->local_index(dof))
1826 {
1827 libmesh_assert_less(dof, this->n_dofs());
1828 _send_list.push_back(dof);
1829 }
1830 }
1831}
unsigned int n_variables() const override
Definition dof_map.h:736
GhostingFunctorIterator coupling_functors_begin() const
Beginning of range of coupling functors.
Definition dof_map.h:366
GhostingFunctorIterator coupling_functors_end() const
End of range of coupling functors.
Definition dof_map.h:372
static void merge_ghost_functor_outputs(GhostingFunctor::map_type &elements_to_ghost, CouplingMatricesSet &temporary_coupling_matrices, const GhostingFunctorIterator &gf_begin, const GhostingFunctorIterator &gf_end, const MeshBase::const_element_iterator &elems_begin, const MeshBase::const_element_iterator &elems_end, processor_id_type p)
Definition dof_map.C:1585
std::set< std::unique_ptr< CouplingMatrix >, Utility::CompareUnderlying > CouplingMatricesSet
Definition dof_map.h:1999
GhostingFunctorIterator algebraic_ghosting_functors_end() const
End of range of algebraic ghosting functors.
Definition dof_map.h:434
GhostingFunctorIterator algebraic_ghosting_functors_begin() const
Beginning of range of algebraic ghosting functors.
Definition dof_map.h:428
bool has_variable(std::string_view var) const
Definition dof_map.h:2986
std::map< const Elem *, const CouplingMatrix *, CompareDofObjectsByPIDAndThenID > map_type
What elements do we care about and what variables do we care about on each element?

References mesh.

◆ add_periodic_boundary() [1/2]

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

Add a periodic boundary pair.

Parameters
boundary- primary boundary
inverse_boundary- inverse boundary

Definition at line 5564 of file dof_map_constraints.C.

5566{
5567 libmesh_assert_equal_to (boundary.myboundary, inverse_boundary.pairedboundary);
5568 libmesh_assert_equal_to (boundary.pairedboundary, inverse_boundary.myboundary);
5569 libmesh_assert(boundary.get_variables() == inverse_boundary.get_variables());
5570
5571 // See if we already have a periodic boundary associated myboundary...
5572 PeriodicBoundaryBase * existing_boundary =
5573 _periodic_boundaries->boundary(boundary.myboundary);
5574
5575 if (!existing_boundary)
5576 {
5577 // ...if not, clone the inputs and add them to the
5578 // PeriodicBoundaries object.
5579 // These will be cleaned up automatically in the
5580 // _periodic_boundaries destructor.
5581 _periodic_boundaries->emplace(boundary.myboundary, boundary.clone());
5582 _periodic_boundaries->emplace(inverse_boundary.myboundary, inverse_boundary.clone());
5583 }
5584 else
5585 {
5586 // ...otherwise, merge this object's variable IDs with the
5587 // existing boundary object's.
5588 existing_boundary->merge(boundary);
5589
5590 // Do the same merging process for the inverse boundary. The
5591 // inverse had better already exist!
5592 PeriodicBoundaryBase * existing_inverse_boundary =
5593 _periodic_boundaries->boundary(boundary.pairedboundary);
5594 libmesh_assert(existing_inverse_boundary);
5595 existing_inverse_boundary->merge(inverse_boundary);
5596
5597 // If we had to merge different *types* of boundaries then
5598 // something likely has gone wrong.
5599#ifdef LIBMESH_HAVE_RTTI
5600 // typeid needs to be given references, not just pointers, to
5601 // return a derived class name.
5602 libmesh_assert(typeid(boundary) == typeid(*existing_boundary));
5603 libmesh_assert(typeid(inverse_boundary) == typeid(*existing_inverse_boundary));
5604#endif
5605 }
5606}
The base class for defining periodic boundaries.
const std::set< unsigned int > & get_variables() const
Get the set of variables for this periodic boundary condition.
boundary_id_type myboundary
The boundary ID of this boundary and its counterpart.
void merge(const PeriodicBoundaryBase &pb)
virtual std::unique_ptr< PeriodicBoundaryBase > clone(TransformationType t=FORWARD) const =0
If we want the DofMap to be able to make copies of references and store them in the underlying map,...

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

◆ add_periodic_boundary() [2/2]

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

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

Definition at line 5556 of file dof_map_constraints.C.

5557{
5558 auto inverse_boundary = periodic_boundary.clone(PeriodicBoundaryBase::INVERSE);
5559 this->add_periodic_boundary(periodic_boundary, *inverse_boundary);
5560}
void add_periodic_boundary(const PeriodicBoundaryBase &periodic_boundary)
Adds a copy of the specified periodic boundary to the system.

References add_periodic_boundary(), libMesh::PeriodicBoundaryBase::clone(), and libMesh::PeriodicBoundaryBase::INVERSE.

Referenced by add_periodic_boundary(), Biharmonic::JR::JR(), main(), and PeriodicBCTest::testPeriodicBC().

◆ add_variable()

unsigned int libMesh::DofMap::add_variable ( System sys,
std::string_view  var,
const FEType type,
const std::set< subdomain_id_type > *const  active_subdomains = nullptr 
)

Adds the variable var to the list of variables for this system.

If active_subdomains is either nullptr (the default) or points to an empty set, then it will be assumed that var has no subdomain restrictions

Returns
The index number for the new variable.

Definition at line 3146 of file dof_map.C.

3150{
3151 parallel_object_only(); // Not strictly needed, but the only safe way to keep in sync
3152
3153 libmesh_assert(this->comm().verify(std::string(var)));
3154 libmesh_assert(this->comm().verify(type));
3155 libmesh_assert(this->comm().verify((active_subdomains == nullptr)));
3156
3157 if (active_subdomains)
3158 libmesh_assert(this->comm().verify(active_subdomains->size()));
3159
3160 // Make sure the variable isn't there already
3161 // or if it is, that it's the type we want
3162 for (auto v : make_range(this->n_vars()))
3163 if (this->variable_name(v) == var)
3164 {
3165 if (this->variable_type(v) == type)
3166 {
3167 // Check whether the existing variable's active subdomains also matches
3168 // the incoming variable's active subdomains. If they don't match, then
3169 // either it is an error by the user or the user is trying to change the
3170 // subdomain restriction after the variable has already been added, which
3171 // is not supported.
3172 const Variable & existing_var = this->variable(v);
3173
3174 // Check whether active_subdomains is not provided/empty and the existing_var is
3175 // implicitly_active()
3176 bool check1 = (!active_subdomains || active_subdomains->empty()) &&
3177 existing_var.implicitly_active();
3178
3179 // Check if the provided active_subdomains is equal to the existing_var's
3180 // active_subdomains
3181 bool check2 =
3182 (active_subdomains && (*active_subdomains == existing_var.active_subdomains()));
3183
3184 // If either of these checks passed, then we already have this variable
3185 if (check1 || check2)
3186 return _variables[v].number();
3187 }
3188
3189 libmesh_error_msg("ERROR: incompatible variable "
3190 << var << " has already been added for this system!");
3191 }
3192
3193 libmesh_assert(!sys.is_initialized());
3194
3195 if (this->n_variable_groups())
3196 {
3197 // Optimize for VariableGroups here - if the user is adding multiple
3198 // variables of the same FEType and subdomain restriction, catch
3199 // that here and add them as members of the same VariableGroup.
3200 //
3201 // start by setting this flag to whatever the user has requested
3202 // and then consider the conditions which should negate it.
3203 bool should_be_in_vg = this->identify_variable_groups();
3204
3205 VariableGroup & vg = _variable_groups.back();
3206
3207 // get a pointer to their subdomain restriction, if any.
3208 const std::set<subdomain_id_type> * const their_active_subdomains(
3209 vg.implicitly_active() ? nullptr : &vg.active_subdomains());
3210
3211 // Different types?
3212 if (vg.type() != type)
3213 should_be_in_vg = false;
3214
3215 // they are restricted, we aren't?
3216 if (their_active_subdomains &&
3217 (!active_subdomains || (active_subdomains && active_subdomains->empty())))
3218 should_be_in_vg = false;
3219
3220 // they aren't restricted, we are?
3221 if (!their_active_subdomains && (active_subdomains && !active_subdomains->empty()))
3222 should_be_in_vg = false;
3223
3224 if (their_active_subdomains && active_subdomains)
3225 // restricted to different sets?
3226 if (*their_active_subdomains != *active_subdomains)
3227 should_be_in_vg = false;
3228
3229 // OK, after all that, append the variable to the vg if none of the conditions
3230 // were violated
3231 if (should_be_in_vg)
3232 {
3233 const unsigned int vn = this->n_vars();
3234
3235 std::string varstr(var);
3236
3237 _variable_numbers[varstr] = vn;
3238 vg.append(std::move(varstr));
3239 _variables.push_back(vg(vg.n_variables() - 1));
3240 const unsigned int vgn = _variable_groups.size() - 1;
3241 _variable_group_numbers.push_back(vgn);
3242 _var_to_vg.emplace(vn, vgn);
3243
3244 return vn;
3245 }
3246 }
3247
3248 // otherwise, fall back to adding a single variable group
3249 return this->add_variables(
3250 sys, std::vector<std::string>(1, std::string(var)), type, active_subdomains);
3251}
unsigned int n_variable_groups() const
Definition dof_map.h:733
std::unordered_map< unsigned int, unsigned int > _var_to_vg
A map from variable number to variable group number.
Definition dof_map.h:2111
std::map< std::string, unsigned int, std::less<> > _variable_numbers
The variable numbers corresponding to user-specified names, useful for name-based lookups.
Definition dof_map.h:2117
bool identify_variable_groups() const
Definition dof_map.h:2951
unsigned int add_variables(System &sys, const std::vector< std::string > &vars, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variables vars to the list of variables for this system.
Definition dof_map.C:3253
unsigned int n_vars() const
Definition dof_map.h:2937
const FEType & variable_type(const unsigned int i) const
Definition dof_map.h:2388
const Variable & variable(const unsigned int c) const override
Definition dof_map.h:2358
const std::string & variable_name(const unsigned int i) const
Definition dof_map.h:2943
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176

References libMesh::Variable::active_subdomains(), libMesh::VariableGroup::append(), libMesh::Variable::implicitly_active(), libMesh::System::is_initialized(), libMesh::libmesh_assert(), libMesh::make_range(), libMesh::VariableGroup::n_variables(), n_vars, and libMesh::Variable::type().

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

◆ add_variable_array()

unsigned int libMesh::DofMap::add_variable_array ( System sys,
const std::vector< std::string > &  vars,
const FEType type,
const std::set< subdomain_id_type > *const  active_subdomains = nullptr 
)

Adds variables vars to the list of variables for this system.

If active_subdomains is either nullptr (the default) or points to an empty set, then it will be assumed that the vars have no subdomain restrictions. This API will end up calling this->add_variables(). However, we will additionally store data that can be leveraged by the DofMap to build degrees of freedom containers corresponding to all the variables in this variable array

An 'array variable' is simply a sequence of contiguous variable numbers defined by pair where the first member of the pair is the first number in the variable sequence and the second member of the pair is the number of the last variable in the sequence plus one. Array variables may be used in tandem with variable grouping by downstream code to build optimized physics kernels since each variable in the array will have the same shape functions.

Returns
The index number for the last of the new variables.

Definition at line 3377 of file dof_map.C.

3381{
3382 const unsigned int count = cast_int<unsigned int>(vars.size());
3383 const unsigned int last_var = this->add_variables(sys, vars, type, active_subdomains);
3384 const unsigned int first_var = last_var + 1 - count;
3385 _array_variables.push_back({first_var, first_var + count});
3386 return last_var;
3387}
std::vector< std::pair< unsigned int, unsigned int > > _array_variables
Array variable information storage.
Definition dof_map.h:2124

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

◆ add_variables()

unsigned int libMesh::DofMap::add_variables ( System sys,
const std::vector< std::string > &  vars,
const FEType type,
const std::set< subdomain_id_type > *const  active_subdomains = nullptr 
)

Adds the variables vars to the list of variables for this system.

If active_subdomains is either nullptr (the default) or points to an empty set, then it will be assumed that the vars have no subdomain restrictions

Returns
The index number for the last of the new variables.

Definition at line 3253 of file dof_map.C.

3257{
3258 parallel_object_only(); // Not strictly needed, but the only safe way to keep in sync
3259
3260 libmesh_assert(!sys.is_initialized());
3261
3262 libmesh_assert(this->comm().verify(vars.size()));
3263 libmesh_assert(this->comm().verify(type));
3264 libmesh_assert(this->comm().verify((active_subdomains == nullptr)));
3265
3266 if (active_subdomains)
3267 libmesh_assert(this->comm().verify(active_subdomains->size()));
3268
3269 // Make sure the variable isn't there already
3270 // or if it is, that it's the type we want
3271 for (auto ovar : vars)
3272 {
3273 libmesh_assert(this->comm().verify(ovar));
3274
3275 for (auto v : make_range(this->n_vars()))
3276 if (this->variable_name(v) == ovar)
3277 {
3278 if (this->variable_type(v) == type)
3279 return _variables[v].number();
3280
3281 libmesh_error_msg("ERROR: incompatible variable "
3282 << ovar << " has already been added for this system!");
3283 }
3284 }
3285
3286 if (this->n_variable_groups())
3287 {
3288 // Optimize for VariableGroups here - if the user is adding multiple
3289 // variables of the same FEType and subdomain restriction, catch
3290 // that here and add them as members of the same VariableGroup.
3291 //
3292 // start by setting this flag to whatever the user has requested
3293 // and then consider the conditions which should negate it.
3294 bool should_be_in_vg = this->identify_variable_groups();
3295
3296 VariableGroup & vg = _variable_groups.back();
3297
3298 // get a pointer to their subdomain restriction, if any.
3299 const std::set<subdomain_id_type> * const their_active_subdomains(
3300 vg.implicitly_active() ? nullptr : &vg.active_subdomains());
3301
3302 // Different types?
3303 if (vg.type() != type)
3304 should_be_in_vg = false;
3305
3306 // they are restricted, we aren't?
3307 if (their_active_subdomains &&
3308 (!active_subdomains || (active_subdomains && active_subdomains->empty())))
3309 should_be_in_vg = false;
3310
3311 // they aren't restricted, we are?
3312 if (!their_active_subdomains && (active_subdomains && !active_subdomains->empty()))
3313 should_be_in_vg = false;
3314
3315 if (their_active_subdomains && active_subdomains)
3316 // restricted to different sets?
3317 if (*their_active_subdomains != *active_subdomains)
3318 should_be_in_vg = false;
3319
3320 // If after all that none of the conditions were violated,
3321 // append the variables to the vg and we're done
3322 if (should_be_in_vg)
3323 {
3324 unsigned int vn = this->n_vars();
3325 const unsigned int vgn = _variable_groups.size() - 1;
3326
3327 for (auto ovar : vars)
3328 {
3329 vn = this->n_vars();
3330
3331 vg.append(ovar);
3332
3333 _variables.push_back(vg(vg.n_variables() - 1));
3334 _variable_numbers[ovar] = vn;
3335 _variable_group_numbers.push_back(vgn);
3336 _var_to_vg.emplace(vn, vgn);
3337 }
3338 return vn;
3339 }
3340 }
3341
3342 const unsigned int curr_n_vars = this->n_vars();
3343
3344 const unsigned int next_first_component = this->n_components(sys.get_mesh());
3345
3346 // We weren't able to add to an existing variable group, so
3347 // add a new variable group to the list
3348 _variable_groups.push_back(
3349 (active_subdomains == nullptr)
3350 ? VariableGroup(&sys, vars, curr_n_vars, next_first_component, type)
3351 : VariableGroup(&sys, vars, curr_n_vars, next_first_component, type, *active_subdomains));
3352
3353 const VariableGroup & vg(_variable_groups.back());
3354 const unsigned int vgn = _variable_groups.size() - 1;
3355
3356 // Add each component of the group individually
3357 for (auto v : make_range(vars.size()))
3358 {
3359 const unsigned int vn = curr_n_vars + v;
3360 _variables.push_back(vg(v));
3361 _variable_numbers[vars[v]] = vn;
3362 _variable_group_numbers.push_back(vgn);
3363 _var_to_vg.emplace(vn, vgn);
3364 }
3365
3366 libmesh_assert_equal_to((curr_n_vars + vars.size()), this->n_vars());
3367
3368 // BSK - Defer this now to System::init_data() so we can detect
3369 // VariableGroups 12/28/2012
3370 // // Add the variable group to the _dof_map
3371 // _dof_map->add_variable_group (vg);
3372
3373 // Return the number of the new variable
3374 return cast_int<unsigned int>(curr_n_vars + vars.size() - 1);
3375}
unsigned int n_components(const MeshBase &mesh) const
Definition dof_map.h:2963

References libMesh::Variable::active_subdomains(), libMesh::VariableGroup::append(), libMesh::System::get_mesh(), libMesh::Variable::implicitly_active(), libMesh::System::is_initialized(), libMesh::libmesh_assert(), libMesh::make_range(), libMesh::VariableGroup::n_variables(), n_vars, and libMesh::Variable::type().

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

◆ algebraic_ghosting_functors_begin()

GhostingFunctorIterator libMesh::DofMap::algebraic_ghosting_functors_begin ( ) const
inline

Beginning of range of algebraic ghosting functors.

Definition at line 428 of file dof_map.h.

429 { return _algebraic_ghosting_functors.begin(); }

References _algebraic_ghosting_functors.

◆ algebraic_ghosting_functors_end()

GhostingFunctorIterator libMesh::DofMap::algebraic_ghosting_functors_end ( ) const
inline

End of range of algebraic ghosting functors.

Definition at line 434 of file dof_map.h.

435 { return _algebraic_ghosting_functors.end(); }

References _algebraic_ghosting_functors.

◆ all_semilocal_indices()

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

Definition at line 2660 of file dof_map.C.

2661{
2662 // We're all semilocal unless we find a counterexample
2663 for (const auto & di : dof_indices_in)
2664 if (!this->semilocal_index(di))
2665 return false;
2666
2667 return true;
2668}
bool semilocal_index(dof_id_type dof_index) const
Definition dof_map.C:2644

◆ allgather_recursive_constraints()

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

Gathers constraint equation dependencies from other processors.

Definition at line 3677 of file dof_map_constraints.C.

3678{
3679 // This function must be run on all processors at once
3680 parallel_object_only();
3681
3682 // Return immediately if there's nothing to gather
3683 if (this->n_processors() == 1)
3684 return;
3685
3686 // We might get to return immediately if none of the processors
3687 // found any constraints
3688 unsigned int has_constraints = !_dof_constraints.empty()
3689#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3690 || !_node_constraints.empty()
3691#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
3692 ;
3693 this->comm().max(has_constraints);
3694 if (!has_constraints)
3695 return;
3696
3697 // If we have heterogeneous adjoint constraints we need to
3698 // communicate those too.
3699 const unsigned int max_qoi_num =
3701 0 : _adjoint_constraint_values.rbegin()->first+1;
3702
3703#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3704 // We may need to send nodes ahead of data about them
3705 std::vector<Parallel::Request> packed_range_sends;
3706
3707 // We may be receiving packed_range sends out of order with
3708 // parallel_sync tags, so make sure they're received correctly.
3709 Parallel::MessageTag range_tag = this->comm().get_unique_tag();
3710
3711 // We only need to do these sends on a distributed mesh
3712 const bool dist_mesh = !mesh.is_serial();
3713#endif
3714
3715 // We might have calculated constraints for constrained dofs
3716 // which have support on other processors.
3717 // Push these out first.
3718 {
3719 std::map<processor_id_type, std::set<dof_id_type>> pushed_ids;
3720
3721#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3722 std::map<processor_id_type, std::set<dof_id_type>> pushed_node_ids;
3723#endif
3724
3725 const unsigned int sys_num = this->sys_number();
3726
3727 // Collect the constraints to push to each processor
3728 for (auto & elem : as_range(mesh.active_not_local_elements_begin(),
3729 mesh.active_not_local_elements_end()))
3730 {
3731 const unsigned short n_nodes = elem->n_nodes();
3732
3733 // Just checking dof_indices on the foreign element isn't
3734 // enough. Consider a central hanging node between a coarse
3735 // Q2/Q1 element and its finer neighbors on a higher-ranked
3736 // processor. The coarse element's processor will own the node,
3737 // and will thereby own the pressure dof on that node, despite
3738 // the fact that that pressure dof doesn't directly exist on the
3739 // coarse element!
3740 //
3741 // So, we loop through dofs manually.
3742
3743 {
3744 const unsigned int n_vars = elem->n_vars(sys_num);
3745 for (unsigned int v=0; v != n_vars; ++v)
3746 {
3747 const unsigned int n_comp = elem->n_comp(sys_num,v);
3748 for (unsigned int c=0; c != n_comp; ++c)
3749 {
3750 const unsigned int id =
3751 elem->dof_number(sys_num,v,c);
3752 if (this->is_constrained_dof(id))
3753 pushed_ids[elem->processor_id()].insert(id);
3754 }
3755 }
3756 }
3757
3758 for (unsigned short n = 0; n != n_nodes; ++n)
3759 {
3760 const Node & node = elem->node_ref(n);
3761 const unsigned int n_vars = node.n_vars(sys_num);
3762 for (unsigned int v=0; v != n_vars; ++v)
3763 {
3764 const unsigned int n_comp = node.n_comp(sys_num,v);
3765 for (unsigned int c=0; c != n_comp; ++c)
3766 {
3767 const unsigned int id =
3768 node.dof_number(sys_num,v,c);
3769 if (this->is_constrained_dof(id))
3770 pushed_ids[elem->processor_id()].insert(id);
3771 }
3772 }
3773 }
3774
3775#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3776 for (unsigned short n = 0; n != n_nodes; ++n)
3777 if (this->is_constrained_node(elem->node_ptr(n)))
3778 pushed_node_ids[elem->processor_id()].insert(elem->node_id(n));
3779#endif
3780 }
3781
3782 // Rewrite those id sets as vectors for sending and receiving,
3783 // then find the corresponding data for each id, then push it all.
3784 std::map<processor_id_type, std::vector<dof_id_type>>
3785 pushed_id_vecs, received_id_vecs;
3786 for (auto & p : pushed_ids)
3787 pushed_id_vecs[p.first].assign(p.second.begin(), p.second.end());
3788
3789 std::map<processor_id_type, std::vector<std::vector<std::pair<dof_id_type,Real>>>>
3790 pushed_keys_vals, received_keys_vals;
3791 std::map<processor_id_type, std::vector<std::vector<Number>>> pushed_rhss, received_rhss;
3792 for (auto & p : pushed_id_vecs)
3793 {
3794 auto & keys_vals = pushed_keys_vals[p.first];
3795 keys_vals.reserve(p.second.size());
3796
3797 auto & rhss = pushed_rhss[p.first];
3798 rhss.reserve(p.second.size());
3799 for (auto & pushed_id : p.second)
3800 {
3801 const DofConstraintRow & row = _dof_constraints[pushed_id];
3802 keys_vals.emplace_back(row.begin(), row.end());
3803
3804 rhss.push_back(std::vector<Number>(max_qoi_num+1));
3805 std::vector<Number> & rhs = rhss.back();
3806 DofConstraintValueMap::const_iterator rhsit =
3807 _primal_constraint_values.find(pushed_id);
3808 rhs[max_qoi_num] =
3809 (rhsit == _primal_constraint_values.end()) ?
3810 0 : rhsit->second;
3811 for (unsigned int q = 0; q != max_qoi_num; ++q)
3812 {
3813 AdjointDofConstraintValues::const_iterator adjoint_map_it =
3815
3816 if (adjoint_map_it == _adjoint_constraint_values.end())
3817 continue;
3818
3819 const DofConstraintValueMap & constraint_map =
3820 adjoint_map_it->second;
3821
3822 DofConstraintValueMap::const_iterator adj_rhsit =
3823 constraint_map.find(pushed_id);
3824
3825 rhs[q] =
3826 (adj_rhsit == constraint_map.end()) ?
3827 0 : adj_rhsit->second;
3828 }
3829 }
3830 }
3831
3832 auto ids_action_functor =
3833 [& received_id_vecs]
3834 (processor_id_type pid,
3835 const std::vector<dof_id_type> & data)
3836 {
3837 received_id_vecs[pid] = data;
3838 };
3839
3841 (this->comm(), pushed_id_vecs, ids_action_functor);
3842
3843 auto keys_vals_action_functor =
3844 [& received_keys_vals]
3845 (processor_id_type pid,
3846 const std::vector<std::vector<std::pair<dof_id_type,Real>>> & data)
3847 {
3848 received_keys_vals[pid] = data;
3849 };
3850
3852 (this->comm(), pushed_keys_vals, keys_vals_action_functor);
3853
3854 auto rhss_action_functor =
3855 [& received_rhss]
3856 (processor_id_type pid,
3857 const std::vector<std::vector<Number>> & data)
3858 {
3859 received_rhss[pid] = data;
3860 };
3861
3863 (this->comm(), pushed_rhss, rhss_action_functor);
3864
3865 // Now we have all the DofConstraint rows and rhs values received
3866 // from others, so add the DoF constraints that we've been sent
3867
3868#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3869 std::map<processor_id_type, std::vector<dof_id_type>>
3870 pushed_node_id_vecs, received_node_id_vecs;
3871 for (auto & p : pushed_node_ids)
3872 pushed_node_id_vecs[p.first].assign(p.second.begin(), p.second.end());
3873
3874 std::map<processor_id_type, std::vector<std::vector<std::pair<dof_id_type,Real>>>>
3875 pushed_node_keys_vals, received_node_keys_vals;
3876 std::map<processor_id_type, std::vector<Point>> pushed_offsets, received_offsets;
3877
3878 for (auto & p : pushed_node_id_vecs)
3879 {
3880 const processor_id_type pid = p.first;
3881
3882 // FIXME - this could be an unordered set, given a
3883 // hash<pointers> specialization
3884 std::set<const Node *> nodes_requested;
3885
3886 auto & node_keys_vals = pushed_node_keys_vals[pid];
3887 node_keys_vals.reserve(p.second.size());
3888
3889 auto & offsets = pushed_offsets[pid];
3890 offsets.reserve(p.second.size());
3891
3892 for (auto & pushed_node_id : p.second)
3893 {
3894 const Node * node = mesh.node_ptr(pushed_node_id);
3895 NodeConstraintRow & row = _node_constraints[node].first;
3896 const std::size_t row_size = row.size();
3897 node_keys_vals.push_back
3898 (std::vector<std::pair<dof_id_type,Real>>());
3899 std::vector<std::pair<dof_id_type,Real>> & this_node_kv =
3900 node_keys_vals.back();
3901 this_node_kv.reserve(row_size);
3902 for (const auto & j : row)
3903 {
3904 this_node_kv.emplace_back(j.first->id(), j.second);
3905
3906 // If we're not sure whether our send
3907 // destination already has this node, let's give
3908 // it a copy.
3909 if (j.first->processor_id() != pid && dist_mesh)
3910 nodes_requested.insert(j.first);
3911 }
3912
3913 offsets.push_back(_node_constraints[node].second);
3914
3915 }
3916
3917 // Constraining nodes might not even exist on our
3918 // correspondant's subset of a distributed mesh, so let's
3919 // make them exist.
3920 if (dist_mesh)
3921 {
3922 packed_range_sends.push_back(Parallel::Request());
3923 this->comm().send_packed_range
3924 (pid, &mesh, nodes_requested.begin(), nodes_requested.end(),
3925 packed_range_sends.back(), range_tag);
3926 }
3927 }
3928
3929 auto node_ids_action_functor =
3930 [& received_node_id_vecs]
3931 (processor_id_type pid,
3932 const std::vector<dof_id_type> & data)
3933 {
3934 received_node_id_vecs[pid] = data;
3935 };
3936
3938 (this->comm(), pushed_node_id_vecs, node_ids_action_functor);
3939
3940 auto node_keys_vals_action_functor =
3941 [& received_node_keys_vals]
3942 (processor_id_type pid,
3943 const std::vector<std::vector<std::pair<dof_id_type,Real>>> & data)
3944 {
3945 received_node_keys_vals[pid] = data;
3946 };
3947
3949 (this->comm(), pushed_node_keys_vals,
3950 node_keys_vals_action_functor);
3951
3952 auto node_offsets_action_functor =
3953 [& received_offsets]
3954 (processor_id_type pid,
3955 const std::vector<Point> & data)
3956 {
3957 received_offsets[pid] = data;
3958 };
3959
3961 (this->comm(), pushed_offsets, node_offsets_action_functor);
3962
3963#endif
3964
3965 // Add all the dof constraints that I've been sent
3966 for (auto & [pid, pushed_ids_to_me] : received_id_vecs)
3967 {
3968 libmesh_assert(received_keys_vals.count(pid));
3969 libmesh_assert(received_rhss.count(pid));
3970 const auto & pushed_keys_vals_to_me = received_keys_vals.at(pid);
3971 const auto & pushed_rhss_to_me = received_rhss.at(pid);
3972
3973 libmesh_assert_equal_to (pushed_ids_to_me.size(),
3974 pushed_keys_vals_to_me.size());
3975 libmesh_assert_equal_to (pushed_ids_to_me.size(),
3976 pushed_rhss_to_me.size());
3977
3978 for (auto i : index_range(pushed_ids_to_me))
3979 {
3980 dof_id_type constrained = pushed_ids_to_me[i];
3981
3982 // If we don't already have a constraint for this dof,
3983 // add the one we were sent
3984 if (!this->is_constrained_dof(constrained))
3985 {
3986 DofConstraintRow & row = _dof_constraints[constrained];
3987 for (auto & kv : pushed_keys_vals_to_me[i])
3988 {
3989 libmesh_assert_less(kv.first, this->n_dofs());
3990 row[kv.first] = kv.second;
3991 }
3992
3993 const Number primal_rhs = pushed_rhss_to_me[i][max_qoi_num];
3994
3995 if (libmesh_isnan(primal_rhs))
3996 libmesh_assert(pushed_keys_vals_to_me[i].empty());
3997
3998 if (primal_rhs != Number(0))
3999 _primal_constraint_values[constrained] = primal_rhs;
4000 else
4001 _primal_constraint_values.erase(constrained);
4002
4003 for (unsigned int q = 0; q != max_qoi_num; ++q)
4004 {
4005 AdjointDofConstraintValues::iterator adjoint_map_it =
4007
4008 const Number adj_rhs = pushed_rhss_to_me[i][q];
4009
4010 if ((adjoint_map_it == _adjoint_constraint_values.end()) &&
4011 adj_rhs == Number(0))
4012 continue;
4013
4014 if (adjoint_map_it == _adjoint_constraint_values.end())
4015 adjoint_map_it = _adjoint_constraint_values.emplace
4016 (q, DofConstraintValueMap()).first;
4017
4018 DofConstraintValueMap & constraint_map =
4019 adjoint_map_it->second;
4020
4021 if (adj_rhs != Number(0))
4022 constraint_map[constrained] = adj_rhs;
4023 else
4024 constraint_map.erase(constrained);
4025 }
4026 }
4027 }
4028 }
4029
4030#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
4031 // Add all the node constraints that I've been sent
4032 for (auto & [pid, pushed_node_ids_to_me] : received_node_id_vecs)
4033 {
4034 // Before we act on any new constraint rows, we may need to
4035 // make sure we have all the nodes involved!
4036 if (dist_mesh)
4039 (Node**)nullptr, range_tag);
4040
4041 libmesh_assert(received_node_keys_vals.count(pid));
4042 libmesh_assert(received_offsets.count(pid));
4043 const auto & pushed_node_keys_vals_to_me = received_node_keys_vals.at(pid);
4044 const auto & pushed_offsets_to_me = received_offsets.at(pid);
4045
4046 libmesh_assert_equal_to (pushed_node_ids_to_me.size(),
4047 pushed_node_keys_vals_to_me.size());
4048 libmesh_assert_equal_to (pushed_node_ids_to_me.size(),
4049 pushed_offsets_to_me.size());
4050
4051 for (auto i : index_range(pushed_node_ids_to_me))
4052 {
4053 dof_id_type constrained_id = pushed_node_ids_to_me[i];
4054
4055 // If we don't already have a constraint for this node,
4056 // add the one we were sent
4057 const Node * constrained = mesh.node_ptr(constrained_id);
4058 if (!this->is_constrained_node(constrained))
4059 {
4060 NodeConstraintRow & row = _node_constraints[constrained].first;
4061 for (auto & kv : pushed_node_keys_vals_to_me[i])
4062 {
4063 const Node * key_node = mesh.node_ptr(kv.first);
4064 libmesh_assert(key_node);
4065 row[key_node] = kv.second;
4066 }
4067 _node_constraints[constrained].second = pushed_offsets_to_me[i];
4068 }
4069 }
4070 }
4071#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
4072 }
4073
4074 // Now start checking for any other constraints we need
4075 // to know about, requesting them recursively.
4076
4077 // Create sets containing the DOFs and nodes we already depend on
4078 typedef std::set<dof_id_type> DoF_RCSet;
4079 DoF_RCSet unexpanded_dofs;
4080
4081 for (const auto & i : _dof_constraints)
4082 unexpanded_dofs.insert(i.first);
4083
4084 // Gather all the dof constraints we need
4085 this->gather_constraints(mesh, unexpanded_dofs, false);
4086
4087 // Gather all the node constraints we need
4088#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
4089 typedef std::set<const Node *> Node_RCSet;
4090 Node_RCSet unexpanded_nodes;
4091
4092 for (const auto & i : _node_constraints)
4093 unexpanded_nodes.insert(i.first);
4094
4095 // We have to keep recursing while the unexpanded set is
4096 // nonempty on *any* processor
4097 bool unexpanded_set_nonempty = !unexpanded_nodes.empty();
4098 this->comm().max(unexpanded_set_nonempty);
4099
4100 while (unexpanded_set_nonempty)
4101 {
4102 // Let's make sure we don't lose sync in this loop.
4103 parallel_object_only();
4104
4105 // Request sets
4106 Node_RCSet node_request_set;
4107
4108 // Request sets to send to each processor
4109 std::map<processor_id_type, std::vector<dof_id_type>>
4110 requested_node_ids;
4111
4112 // And the sizes of each
4113 std::map<processor_id_type, dof_id_type> node_ids_on_proc;
4114
4115 // Fill (and thereby sort and uniq!) the main request sets
4116 for (const auto & i : unexpanded_nodes)
4117 {
4118 NodeConstraintRow & row = _node_constraints[i].first;
4119 for (const auto & j : row)
4120 {
4121 const Node * const node = j.first;
4122 libmesh_assert(node);
4123
4124 // If it's non-local and we haven't already got a
4125 // constraint for it, we might need to ask for one
4126 if ((node->processor_id() != this->processor_id()) &&
4127 !_node_constraints.count(node))
4128 node_request_set.insert(node);
4129 }
4130 }
4131
4132 // Clear the unexpanded constraint sets; we're about to expand
4133 // them
4134 unexpanded_nodes.clear();
4135
4136 // Count requests by processor
4137 for (const auto & node : node_request_set)
4138 {
4139 libmesh_assert(node);
4140 libmesh_assert_less (node->processor_id(), this->n_processors());
4141 node_ids_on_proc[node->processor_id()]++;
4142 }
4143
4144 for (auto pair : node_ids_on_proc)
4145 requested_node_ids[pair.first].reserve(pair.second);
4146
4147 // Prepare each processor's request set
4148 for (const auto & node : node_request_set)
4149 requested_node_ids[node->processor_id()].push_back(node->id());
4150
4151 typedef std::vector<std::pair<dof_id_type, Real>> row_datum;
4152
4153 auto node_row_gather_functor =
4154 [this,
4155 & mesh,
4156 dist_mesh,
4157 & packed_range_sends,
4158 & range_tag]
4159 (processor_id_type pid,
4160 const std::vector<dof_id_type> & ids,
4161 std::vector<row_datum> & data)
4162 {
4163 // FIXME - this could be an unordered set, given a
4164 // hash<pointers> specialization
4165 std::set<const Node *> nodes_requested;
4166
4167 // Fill those requests
4168 const std::size_t query_size = ids.size();
4169
4170 data.resize(query_size);
4171 for (std::size_t i=0; i != query_size; ++i)
4172 {
4173 dof_id_type constrained_id = ids[i];
4174 const Node * constrained_node = mesh.node_ptr(constrained_id);
4175 if (_node_constraints.count(constrained_node))
4176 {
4177 const NodeConstraintRow & row = _node_constraints[constrained_node].first;
4178 std::size_t row_size = row.size();
4179 data[i].reserve(row_size);
4180 for (const auto & j : row)
4181 {
4182 const Node * node = j.first;
4183 data[i].emplace_back(node->id(), j.second);
4184
4185 // If we're not sure whether our send
4186 // destination already has this node, let's give
4187 // it a copy.
4188 if (node->processor_id() != pid && dist_mesh)
4189 nodes_requested.insert(node);
4190
4191 // We can have 0 nodal constraint
4192 // coefficients, where no Lagrange constraint
4193 // exists but non-Lagrange basis constraints
4194 // might.
4195 // libmesh_assert(j.second);
4196 }
4197 }
4198 else
4199 {
4200 // We have to distinguish "constraint with no
4201 // constraining nodes" (e.g. due to user node
4202 // constraint equations) from "no constraint".
4203 // We'll use invalid_id for the latter.
4204 data[i].emplace_back(DofObject::invalid_id, Real(0));
4205 }
4206 }
4207
4208 // Constraining nodes might not even exist on our
4209 // correspondant's subset of a distributed mesh, so let's
4210 // make them exist.
4211 if (dist_mesh)
4212 {
4213 packed_range_sends.push_back(Parallel::Request());
4214 this->comm().send_packed_range
4215 (pid, &mesh, nodes_requested.begin(), nodes_requested.end(),
4216 packed_range_sends.back(), range_tag);
4217 }
4218 };
4219
4220 typedef Point node_rhs_datum;
4221
4222 auto node_rhs_gather_functor =
4223 [this,
4224 & mesh]
4226 const std::vector<dof_id_type> & ids,
4227 std::vector<node_rhs_datum> & data)
4228 {
4229 // Fill those requests
4230 const std::size_t query_size = ids.size();
4231
4232 data.resize(query_size);
4233 for (std::size_t i=0; i != query_size; ++i)
4234 {
4235 dof_id_type constrained_id = ids[i];
4236 const Node * constrained_node = mesh.node_ptr(constrained_id);
4237 if (_node_constraints.count(constrained_node))
4238 data[i] = _node_constraints[constrained_node].second;
4239 else
4240 data[i](0) = std::numeric_limits<Real>::quiet_NaN();
4241 }
4242 };
4243
4244 auto node_row_action_functor =
4245 [this,
4246 & mesh,
4247 dist_mesh,
4248 & range_tag,
4249 & unexpanded_nodes]
4250 (processor_id_type pid,
4251 const std::vector<dof_id_type> & ids,
4252 const std::vector<row_datum> & data)
4253 {
4254 // Before we act on any new constraint rows, we may need to
4255 // make sure we have all the nodes involved!
4256 if (dist_mesh)
4259 (Node**)nullptr, range_tag);
4260
4261 // Add any new constraint rows we've found
4262 const std::size_t query_size = ids.size();
4263
4264 for (std::size_t i=0; i != query_size; ++i)
4265 {
4266 const dof_id_type constrained_id = ids[i];
4267
4268 // An empty row is an constraint with an empty row; for
4269 // no constraint we use a "no row" placeholder
4270 if (data[i].empty())
4271 {
4272 const Node * constrained_node = mesh.node_ptr(constrained_id);
4273 NodeConstraintRow & row = _node_constraints[constrained_node].first;
4274 row.clear();
4275 }
4276 else if (data[i][0].first != DofObject::invalid_id)
4277 {
4278 const Node * constrained_node = mesh.node_ptr(constrained_id);
4279 NodeConstraintRow & row = _node_constraints[constrained_node].first;
4280 row.clear();
4281 for (auto & pair : data[i])
4282 {
4283 const Node * key_node =
4284 mesh.node_ptr(pair.first);
4285 libmesh_assert(key_node);
4286 row[key_node] = pair.second;
4287 }
4288
4289 // And prepare to check for more recursive constraints
4290 unexpanded_nodes.insert(constrained_node);
4291 }
4292 }
4293 };
4294
4295 auto node_rhs_action_functor =
4296 [this,
4297 & mesh]
4299 const std::vector<dof_id_type> & ids,
4300 const std::vector<node_rhs_datum> & data)
4301 {
4302 // Add rhs data for any new node constraint rows we've found
4303 const std::size_t query_size = ids.size();
4304
4305 for (std::size_t i=0; i != query_size; ++i)
4306 {
4307 dof_id_type constrained_id = ids[i];
4308 const Node * constrained_node = mesh.node_ptr(constrained_id);
4309
4310 if (!libmesh_isnan(data[i](0)))
4311 _node_constraints[constrained_node].second = data[i];
4312 else
4313 _node_constraints.erase(constrained_node);
4314 }
4315 };
4316
4317 // Now request node constraint rows from other processors
4318 row_datum * node_row_ex = nullptr;
4320 (this->comm(), requested_node_ids, node_row_gather_functor,
4321 node_row_action_functor, node_row_ex);
4322
4323 // And request node constraint right hand sides from other procesors
4324 node_rhs_datum * node_rhs_ex = nullptr;
4326 (this->comm(), requested_node_ids, node_rhs_gather_functor,
4327 node_rhs_action_functor, node_rhs_ex);
4328
4329
4330 // We have to keep recursing while the unexpanded set is
4331 // nonempty on *any* processor
4332 unexpanded_set_nonempty = !unexpanded_nodes.empty();
4333 this->comm().max(unexpanded_set_nonempty);
4334 }
4335 Parallel::wait(packed_range_sends);
4336#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
4337}
MessageTag get_unique_tag(int tagvalue=MessageTag::invalid_tag) const
void receive_packed_range(const unsigned int dest_processor_id, Context *context, OutputIter out, const T *output_type, const MessageTag &tag=any_tag) const
void send_packed_range(const unsigned int dest_processor_id, const Context *context, Iter range_begin, const Iter range_end, const MessageTag &tag=no_tag, std::size_t approx_buffer_size=1000000) const
Storage for DofConstraint right hand sides for a particular problem.
Definition dof_map.h:124
void 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.
bool is_constrained_node(const Node *node) const
Definition dof_map.h:2410
unsigned int n_comp(const unsigned int s, const unsigned int var) const
Definition dof_object.h:978
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
processor_id_type processor_id() const
Definition dof_object.h:881
dof_id_type id() const
Definition dof_object.h:819
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
Definition dof_object.h:943
virtual bool is_serial() const
Definition mesh_base.h:357
virtual const Node * node_ptr(const dof_id_type i) const =0
A Node is like a Point, but with more information.
Definition node.h:55
processor_id_type processor_id() const
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
void pull_parallel_vector_data(const Communicator &comm, const MapToVectors &queries, GatherFunctor &gather_data, const ActionFunctor &act_on_data, const datum *example)
Status wait(Request &r)
void push_parallel_vector_data(const Communicator &comm, MapToVectors &&data, const ActionFunctor &act_on_data)
std::map< const Node *, Real, std::less< const Node * >, Threads::scalable_allocator< std::pair< const Node *const, Real > > > NodeConstraintRow
A row of the Node constraint mapping.
Definition dof_map.h:148
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition int_range.h:153
bool libmesh_isnan(T x)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t processor_id_type
Definition id_types.h:104

References _adjoint_constraint_values, _dof_constraints, _node_constraints, _primal_constraint_values, libMesh::as_range(), libMesh::ParallelObject::comm(), libMesh::DofObject::dof_number(), gather_constraints(), libMesh::Parallel::Communicator::get_unique_tag(), libMesh::DofObject::id(), libMesh::index_range(), libMesh::DofObject::invalid_id, is_constrained_dof(), is_constrained_node(), libMesh::MeshBase::is_serial(), libMesh::libmesh_assert(), libMesh::libmesh_isnan(), libMesh::Parallel::Communicator::max(), mesh, libMesh::DofObject::n_comp(), libMesh::Elem::n_nodes(), n_nodes, libMesh::ParallelObject::n_processors(), n_vars(), libMesh::DofObject::n_vars(), libMesh::Elem::node_id(), libMesh::MeshBase::node_ptr(), libMesh::Elem::node_ptr(), libMesh::Elem::node_ref(), libMesh::DofObject::processor_id(), TIMPI::pull_parallel_vector_data(), TIMPI::push_parallel_vector_data(), libMesh::Real, libMesh::Parallel::Communicator::receive_packed_range(), libMesh::Parallel::Communicator::send_packed_range(), sys_number(), and TIMPI::wait().

Referenced by process_constraints().

◆ array_dof_indices() [1/3]

template<typename DofIndicesFunctor >
void libMesh::DofMap::array_dof_indices ( const DofIndicesFunctor &  functor,
std::vector< dof_id_type > &  di,
const unsigned int  vn 
) const

Definition at line 2890 of file dof_map.h.

2893{
2894 const auto [begin, end] = this->get_variable_array(vn);
2895 functor(di, begin);
2896
2897 const unsigned int count = end - begin;
2898 // We make count, which could be >> ntest, the inner index in hopes of vectorization
2899 if (count > 1)
2900 {
2901 const dof_id_type component_size = di.size();
2902 di.resize(count * component_size);
2903
2904 const auto pack_container = [&di,
2905 component_size](const unsigned int j,
2906 const std::vector<dof_id_type> & j_dof_indices,
2907 const unsigned int stride) {
2908 if (&j_dof_indices != &di)
2909 libmesh_assert(j_dof_indices.size() == component_size);
2910 for (const auto i : make_range(component_size))
2911 di[j * component_size + i] = j_dof_indices[i] + stride * j;
2912 };
2913 pack_container(0, di, 0);
2914
2915 const auto & fe_type = _variable_groups[libmesh_map_find(_var_to_vg, vn)].type();
2916 if (const bool lagrange = fe_type.family == LAGRANGE;
2917 lagrange || (FEInterface::get_continuity(fe_type) == DISCONTINUOUS))
2918 {
2919 const auto stride = lagrange ? 1 : component_size;
2920 for (const auto j : make_range((unsigned int)1, count))
2921 pack_container(j, di, stride);
2922 }
2923 else
2924 {
2925 static thread_local std::vector<dof_id_type> work_dof_indices;
2926 unsigned int j = 1;
2927 for (const auto i : make_range(begin + 1, end))
2928 {
2929 functor(work_dof_indices, i);
2930 pack_container(j++, work_dof_indices, 0);
2931 }
2932 }
2933 }
2934}
void ErrorVector unsigned int
const std::pair< unsigned int, unsigned int > & get_variable_array(unsigned int vi) const
Retrieve the array variable bounds for a given variable vi.
Definition dof_map.h:2873
static FEContinuity get_continuity(const FEType &fe_type)
Returns the input FEType's FEContinuity based on the underlying FEFamily and potentially the Order,...

References _var_to_vg, _variable_groups, libMesh::DISCONTINUOUS, libMesh::FEInterface::get_continuity(), get_variable_array(), libMesh::LAGRANGE, libMesh::libmesh_assert(), and libMesh::make_range().

◆ array_dof_indices() [2/3]

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

This will aggregate all the degrees of the freedom from the variable array that vn is a member of, and potentially for a non-default element p refinement level

Definition at line 2339 of file dof_map.C.

2343{
2344 auto dof_indices_functor = [elem, p_level, this](std::vector<dof_id_type> & functor_di,
2345 const unsigned int functor_vn) {
2346 this->dof_indices(elem, functor_di, functor_vn, p_level);
2347 };
2348 this->array_dof_indices(dof_indices_functor, di, vn);
2349}
void array_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.
Definition dof_map.C:2339

◆ array_dof_indices() [3/3]

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

Definition at line 2351 of file dof_map.C.

2354{
2355 auto dof_indices_functor = [node, this](std::vector<dof_id_type> & functor_di,
2356 const unsigned int functor_vn) {
2357 this->dof_indices(node, functor_di, functor_vn);
2358 };
2359 this->array_dof_indices(dof_indices_functor, di, vn);
2360}

◆ assert_no_nodes_missed()

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

Definition at line 1563 of file dof_map.C.

1564{
1565 MeshTools::libmesh_assert_valid_procids<Node>(mesh);
1566
1567 for (auto & node : mesh.local_node_ptr_range())
1568 {
1569 unsigned int n_var_g = node->n_var_groups(this->sys_number());
1570 for (unsigned int vg=0; vg != n_var_g; ++vg)
1571 {
1572 unsigned int n_comp_g =
1573 node->n_comp_group(this->sys_number(), vg);
1574 dof_id_type my_first_dof = n_comp_g ?
1575 node->vg_dof_base(this->sys_number(), vg) : 0;
1576 libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
1577 }
1578 }
1579}

References mesh.

◆ attach_extra_send_list_function()

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

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

Definition at line 490 of file dof_map.h.

References _extra_send_list_context, and _extra_send_list_function.

◆ attach_extra_send_list_object()

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

Attach an object to populate the send_list with extra entries.

This should only add to the send list, but no checking is done to enforce this behavior.

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

Definition at line 481 of file dof_map.h.

482 {
483 _augment_send_list = &asl;
484 }

References _augment_send_list.

◆ attach_extra_sparsity_function()

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

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

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

Further, you must modify n_nz and n_oz properly!

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

Definition at line 467 of file dof_map.h.

References _extra_sparsity_context, and _extra_sparsity_function.

◆ attach_extra_sparsity_object()

void libMesh::DofMap::attach_extra_sparsity_object ( SparsityPattern::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 452 of file dof_map.h.

453 {
455 }

References _augment_sparsity_pattern.

◆ attach_matrix()

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

Additional matrices may be attached to this DofMap.

They are initialized to the same sparsity structure as the major matrix.

Definition at line 240 of file dof_map.C.

241{
242 parallel_object_only();
243
244 // We shouldn't be trying to re-attach the same matrices repeatedly
245 libmesh_assert (std::find(_matrices.begin(), _matrices.end(),
246 &matrix) == _matrices.end());
247
248 _matrices.push_back(&matrix);
249
250 this->update_sparsity_pattern(matrix);
251
252 if (matrix.need_full_sparsity_pattern())
254}
void update_sparsity_pattern(SparseMatrix< Number > &matrix) const
Additional matrices may be be temporarily initialized by this DofMap.
Definition dof_map.C:269
virtual bool need_full_sparsity_pattern() const

References _matrices, libMesh::libmesh_assert(), need_full_sparsity_pattern, libMesh::SparseMatrix< T >::need_full_sparsity_pattern(), and update_sparsity_pattern().

Referenced by libMesh::RBConstruction::allocate_data_structures(), libMesh::TransientRBConstruction::allocate_data_structures(), libMesh::ClawSystem::init_data(), libMesh::System::init_matrices(), and libMesh::System::late_matrix_init().

◆ block_size()

unsigned int libMesh::DofMap::block_size ( ) const
inline
Returns
The block size, if the variables are amenable to block storage. Otherwise 1. This routine was originally designed to enable a blocked storage, but it turns out this information is still super useful for solvers even when we do not use the blocked storage (e.g., MATMPIBAIJ in PETSc). For example (in PCHMG), for a system of PDEs, to construct an efficient multilevel preconditioner, we coarsen the matrix of one single PDE instead of the entire huge matrix. In order to accomplish this, we need to know many PDEs we have. Another use case, the fieldsplit preconditioner can be constructed in place with this info without involving any user efforts.

Definition at line 766 of file dof_map.h.

767 {
768 return (this->has_blocked_representation() ? this->n_variables() : 1);
769 }
bool has_blocked_representation() const
Definition dof_map.h:749

References has_blocked_representation(), and n_variables().

◆ build_constraint_matrix()

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

Build the constraint matrix C associated with the element degree of freedom indices elem_dofs.

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

Definition at line 3433 of file dof_map_constraints.C.

3436{
3437 LOG_SCOPE_IF("build_constraint_matrix()", "DofMap", !called_recursively);
3438
3439 // Create a set containing the DOFs we already depend on
3440 typedef std::set<dof_id_type> RCSet;
3441 RCSet dof_set;
3442
3443 bool we_have_constraints = false;
3444
3445 // Next insert any other dofs the current dofs might be constrained
3446 // in terms of. Note that in this case we may not be done: Those
3447 // may in turn depend on others. So, we need to repeat this process
3448 // in that case until the system depends only on unconstrained
3449 // degrees of freedom.
3450 for (const auto & dof : elem_dofs)
3451 if (this->is_constrained_dof(dof))
3452 {
3453 we_have_constraints = true;
3454
3455 // If the DOF is constrained
3456 DofConstraints::const_iterator
3457 pos = _dof_constraints.find(dof);
3458
3459 libmesh_assert (pos != _dof_constraints.end());
3460
3461 const DofConstraintRow & constraint_row = pos->second;
3462
3463 // Constraint rows in p refinement may be empty
3464 //libmesh_assert (!constraint_row.empty());
3465
3466 for (const auto & item : constraint_row)
3467 dof_set.insert (item.first);
3468 }
3469
3470 // May be safe to return at this point
3471 // (but remember to stop the perflog)
3472 if (!we_have_constraints)
3473 return;
3474
3475 for (const auto & dof : elem_dofs)
3476 dof_set.erase (dof);
3477
3478 // If we added any DOFS then we need to do this recursively.
3479 // It is possible that we just added a DOF that is also
3480 // constrained!
3481 //
3482 // Also, we need to handle the special case of an element having DOFs
3483 // constrained in terms of other, local DOFs
3484 if (!dof_set.empty() || // case 1: constrained in terms of other DOFs
3485 !called_recursively) // case 2: constrained in terms of our own DOFs
3486 {
3487 const unsigned int old_size =
3488 cast_int<unsigned int>(elem_dofs.size());
3489
3490 // Add new dependency dofs to the end of the current dof set
3491 elem_dofs.insert(elem_dofs.end(),
3492 dof_set.begin(), dof_set.end());
3493
3494 // Now we can build the constraint matrix.
3495 // Note that resize also zeros for a DenseMatrix<Number>.
3496 C.resize (old_size,
3497 cast_int<unsigned int>(elem_dofs.size()));
3498
3499 // Create the C constraint matrix.
3500 for (unsigned int i=0; i != old_size; i++)
3501 if (this->is_constrained_dof(elem_dofs[i]))
3502 {
3503 // If the DOF is constrained
3504 DofConstraints::const_iterator
3505 pos = _dof_constraints.find(elem_dofs[i]);
3506
3507 libmesh_assert (pos != _dof_constraints.end());
3508
3509 const DofConstraintRow & constraint_row = pos->second;
3510
3511 // p refinement creates empty constraint rows
3512 // libmesh_assert (!constraint_row.empty());
3513
3514 for (const auto & item : constraint_row)
3515 for (unsigned int j=0,
3516 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
3517 j != n_elem_dofs; j++)
3518 if (elem_dofs[j] == item.first)
3519 C(i,j) = item.second;
3520 }
3521 else
3522 {
3523 C(i,i) = 1.;
3524 }
3525
3526 // May need to do this recursively. It is possible
3527 // that we just replaced a constrained DOF with another
3528 // constrained DOF.
3530
3531 this->build_constraint_matrix (Cnew, elem_dofs, true);
3532
3533 if ((C.n() == Cnew.m()) &&
3534 (Cnew.n() == elem_dofs.size())) // If the constraint matrix
3535 C.right_multiply(Cnew); // is constrained...
3536
3537 libmesh_assert_equal_to (C.n(), elem_dofs.size());
3538 }
3539}
Defines a dense matrix for use in Finite Element-type computations.
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
virtual void right_multiply(const DenseMatrixBase< T > &M2) override final
Performs the operation: (*this) <- (*this) * M3.
void build_constraint_matrix(DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
Build the constraint matrix C associated with the element degree of freedom indices elem_dofs.
Tnew cast_int(Told oldvar)

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

Referenced by build_constraint_matrix(), constrain_element_residual(), and max_constraint_error().

◆ build_constraint_matrix_and_vector()

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

Build the constraint matrix C and the forcing vector H associated with the element degree of freedom indices elem_dofs.

The optional parameter called_recursively should be left at the default value false. This is used to handle the special case of an element's degrees of freedom being constrained in terms of other, local degrees of freedom. The usual case is for an elements DOFs to be constrained by some other, external DOFs and/or Dirichlet conditions.

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

Definition at line 3543 of file dof_map_constraints.C.

3548{
3549 LOG_SCOPE_IF("build_constraint_matrix_and_vector()", "DofMap", !called_recursively);
3550
3551 // Create a set containing the DOFs we already depend on
3552 typedef std::set<dof_id_type> RCSet;
3553 RCSet dof_set;
3554
3555 bool we_have_constraints = false;
3556
3557 // Next insert any other dofs the current dofs might be constrained
3558 // in terms of. Note that in this case we may not be done: Those
3559 // may in turn depend on others. So, we need to repeat this process
3560 // in that case until the system depends only on unconstrained
3561 // degrees of freedom.
3562 for (const auto & dof : elem_dofs)
3563 if (this->is_constrained_dof(dof))
3564 {
3565 we_have_constraints = true;
3566
3567 // If the DOF is constrained
3568 DofConstraints::const_iterator
3569 pos = _dof_constraints.find(dof);
3570
3571 libmesh_assert (pos != _dof_constraints.end());
3572
3573 const DofConstraintRow & constraint_row = pos->second;
3574
3575 // Constraint rows in p refinement may be empty
3576 //libmesh_assert (!constraint_row.empty());
3577
3578 for (const auto & item : constraint_row)
3579 dof_set.insert (item.first);
3580 }
3581
3582 // May be safe to return at this point
3583 // (but remember to stop the perflog)
3584 if (!we_have_constraints)
3585 return;
3586
3587 for (const auto & dof : elem_dofs)
3588 dof_set.erase (dof);
3589
3590 // If we added any DOFS then we need to do this recursively.
3591 // It is possible that we just added a DOF that is also
3592 // constrained!
3593 //
3594 // Also, we need to handle the special case of an element having DOFs
3595 // constrained in terms of other, local DOFs
3596 if (!dof_set.empty() || // case 1: constrained in terms of other DOFs
3597 !called_recursively) // case 2: constrained in terms of our own DOFs
3598 {
3599 const DofConstraintValueMap * rhs_values = nullptr;
3600 if (qoi_index < 0)
3601 rhs_values = &_primal_constraint_values;
3602 else if (auto it = _adjoint_constraint_values.find(qoi_index);
3603 it != _adjoint_constraint_values.end())
3604 rhs_values = &it->second;
3605
3606 const unsigned int old_size =
3607 cast_int<unsigned int>(elem_dofs.size());
3608
3609 // Add new dependency dofs to the end of the current dof set
3610 elem_dofs.insert(elem_dofs.end(),
3611 dof_set.begin(), dof_set.end());
3612
3613 // Now we can build the constraint matrix and vector.
3614 // Note that resize also zeros for a DenseMatrix and DenseVector
3615 C.resize (old_size,
3616 cast_int<unsigned int>(elem_dofs.size()));
3617 H.resize (old_size);
3618
3619 // Create the C constraint matrix.
3620 for (unsigned int i=0; i != old_size; i++)
3621 if (this->is_constrained_dof(elem_dofs[i]))
3622 {
3623 // If the DOF is constrained
3624 DofConstraints::const_iterator
3625 pos = _dof_constraints.find(elem_dofs[i]);
3626
3627 libmesh_assert (pos != _dof_constraints.end());
3628
3629 const DofConstraintRow & constraint_row = pos->second;
3630
3631 // p refinement creates empty constraint rows
3632 // libmesh_assert (!constraint_row.empty());
3633
3634 for (const auto & item : constraint_row)
3635 for (unsigned int j=0,
3636 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
3637 j != n_elem_dofs; j++)
3638 if (elem_dofs[j] == item.first)
3639 C(i,j) = item.second;
3640
3641 if (rhs_values)
3642 {
3643 if (const auto rhsit = rhs_values->find(elem_dofs[i]);
3644 rhsit != rhs_values->end())
3645 H(i) = rhsit->second;
3646 }
3647 }
3648 else
3649 {
3650 C(i,i) = 1.;
3651 }
3652
3653 // May need to do this recursively. It is possible
3654 // that we just replaced a constrained DOF with another
3655 // constrained DOF.
3658
3659 this->build_constraint_matrix_and_vector (Cnew, Hnew, elem_dofs,
3660 qoi_index, true);
3661
3662 if ((C.n() == Cnew.m()) && // If the constraint matrix
3663 (Cnew.n() == elem_dofs.size())) // is constrained...
3664 {
3665 // If x = Cy + h and y = Dz + g
3666 // Then x = (CD)z + (Cg + h)
3667 C.vector_mult_add(H, 1, Hnew);
3668
3669 C.right_multiply(Cnew);
3670 }
3671
3672 libmesh_assert_equal_to (C.n(), elem_dofs.size());
3673 }
3674}
void vector_mult_add(DenseVector< T > &dest, const T factor, const DenseVector< T > &arg) const
Performs the scaled matrix-vector multiplication, dest += factor * (*this) * arg.
Defines a dense vector for use in Finite Element-type computations.
void resize(const unsigned int n)
Resize the vector.
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
Build the constraint matrix C and the forcing vector H associated with the element degree of freedom ...

References _adjoint_constraint_values, _dof_constraints, _primal_constraint_values, build_constraint_matrix_and_vector(), is_constrained_dof(), libMesh::libmesh_assert(), 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 build_constraint_matrix_and_vector(), heterogeneously_constrain_element_jacobian_and_residual(), and heterogeneously_constrain_element_residual().

◆ build_sparsity()

std::unique_ptr< SparsityPattern::Build > libMesh::DofMap::build_sparsity ( const MeshBase mesh,
bool  calculate_constrained = false,
bool  use_condensed_system = false 
) const

Builds a sparsity pattern for matrices using the current degree-of-freedom numbering and coupling.

By default, ignores constraint equations, for build speed; this is valid for the combination of !need_full_sparsity_pattern and constraints which only come from periodic boundary conditions and adaptive mesh refinement, where matrix constraint adds some matrix entries but removes equally many (or more) other entries.

Can be told to calculate sparsity for the constrained matrix, which may be necessary in the case of spline control node constraints or sufficiently many user constraints.

Definition at line 63 of file dof_map.C.

66{
67 libmesh_assert (mesh.is_prepared());
68
69 LOG_SCOPE("build_sparsity()", "DofMap");
70
71 // Compute the sparsity structure of the global matrix. This can be
72 // fed into a PetscMatrixBase to allocate exactly the number of nonzeros
73 // necessary to store the matrix. This algorithm should be linear
74 // in the (# of elements)*(# nodes per element)
75
76 // We can be more efficient in the threaded sparsity pattern assembly
77 // if we don't need the exact pattern. For some sparse matrix formats
78 // a good upper bound will suffice.
79
80 // See if we need to include sparsity pattern entries for coupling
81 // between neighbor dofs
82 bool implicit_neighbor_dofs = this->use_coupled_neighbor_dofs(mesh);
83
84 const StaticCondensationDofMap * sc = nullptr;
85 if (use_condensed_system)
86 {
88 sc = _sc.get();
89 }
90
91 // We can compute the sparsity pattern in parallel on multiple
92 // threads. The goal is for each thread to compute the full sparsity
93 // pattern for a subset of elements. These sparsity patterns can
94 // be efficiently merged in the SparsityPattern::Build::join()
95 // method, especially if there is not too much overlap between them.
96 // Even better, if the full sparsity pattern is not needed then
97 // the number of nonzeros per row can be estimated from the
98 // sparsity patterns created on each thread.
99 auto sp = std::make_unique<SparsityPattern::Build>
100 (*this,
101 this->_dof_coupling,
102 this->_coupling_functors,
103 implicit_neighbor_dofs,
105 calculate_constrained,
106 sc);
107
108 Threads::parallel_reduce (ConstElemRange (mesh.active_local_elements_begin(),
109 mesh.active_local_elements_end()), *sp);
110
111 sp->parallel_sync();
112
113 libmesh_assert_equal_to (sp->get_sparsity_pattern().size(), this->n_local_dofs());
114
115 // Check to see if we have any extra stuff to add to the sparsity_pattern
117 {
119 {
120 libmesh_here();
121 libMesh::out << "WARNING: You have specified both an extra sparsity function and object.\n"
122 << " Are you sure this is what you meant to do??"
123 << std::endl;
124 }
125
126 sp->apply_extra_sparsity_function(_extra_sparsity_function,
128 }
129
131 sp->apply_extra_sparsity_object(*_augment_sparsity_pattern);
132
133 return sp;
134}
bool use_coupled_neighbor_dofs(const MeshBase &mesh) const
Tells other library functions whether or not this problem includes coupling between dofs in neighbori...
Definition dof_map.C:1903
void parallel_reduce(const Range &range, Body &body, unsigned int n_threads=libMesh::n_threads())
Execute the provided reduction operation in parallel on the specified range.
StoredRange< MeshBase::const_element_iterator, const Elem * > ConstElemRange
Definition elem_range.h:34
OStreamProxy out

References _augment_sparsity_pattern, _coupling_functors, _dof_coupling, _extra_sparsity_context, _extra_sparsity_function, _sc, has_static_condensation(), libMesh::libmesh_assert(), mesh, need_full_sparsity_pattern, libMesh::out, libMesh::Threads::parallel_reduce(), and use_coupled_neighbor_dofs().

Referenced by process_mesh_constraint_rows(), libMesh::StaticCondensationDofMap::reinit(), and libMesh::System::solve_for_unconstrained_dofs().

◆ calculate_constraining_subdomains()

std::map< const Node *, std::set< subdomain_id_type > > libMesh::DofMap::calculate_constraining_subdomains ( )
private

We may have mesh constraint rows with dependent nodes in one subdomain but dependency nodes in another subdomain, and we may have variables whose subdomain restriction includes the dependent subdomain but not the dependency.

In those cases we need to place degrees of freedom on dependency nodes anyway.

The set value for node n will include all subdomain ids of elements with nodes in subdomains constrained by n.

We use a map<set> rather than a multimap here because we expect to be inserting the same subdomain multiple times and we don't need duplicate values.

Definition at line 1256 of file dof_map.C.

1257{
1258 std::map<const Node *, std::set<subdomain_id_type>> constraining_subdomains;
1259 const auto & constraint_rows = _mesh.get_constraint_rows();
1260
1261 // We can't just loop over constraint rows here because we need
1262 // element subdomain ids for the constrained nodes, but we don't
1263 // want an extra loop if there are no constraint rows.
1264 if (!constraint_rows.empty())
1265 for (auto & elem : _mesh.active_element_ptr_range())
1266 {
1267 const subdomain_id_type sbdid = elem->subdomain_id();
1268
1269 for (const Node & node : elem->node_ref_range())
1270 {
1271 if (auto it = constraint_rows.find(&node);
1272 it != constraint_rows.end())
1273 {
1274 for (const auto & [pr, val] : it->second)
1275 {
1276 const Node * spline_node =
1277 pr.first->node_ptr(pr.second);
1278
1279 constraining_subdomains[spline_node].insert(sbdid);
1280 }
1281 }
1282 }
1283 }
1284
1285 return constraining_subdomains;
1286}
constraint_rows_type & get_constraint_rows()
Constraint rows accessors.
Definition mesh_base.h:1935
TestClass subdomain_id_type
Based on the 4-byte comment warning above, this probably doesn't work with exodusII at all....
Definition id_types.h:43

◆ check_dirichlet_bcid_consistency()

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

Check that all the ids in dirichlet_bcids are actually present in the mesh.

If not, this will throw an error.

Definition at line 5518 of file dof_map_constraints.C.

5520{
5521 const std::set<boundary_id_type>& mesh_side_bcids =
5523 const std::set<boundary_id_type>& mesh_edge_bcids =
5525 const std::set<boundary_id_type>& mesh_node_bcids =
5527 const std::set<boundary_id_type>& dbc_bcids = boundary.b;
5528
5529 // DirichletBoundary id sets should be consistent across all ranks
5530 libmesh_assert(mesh.comm().verify(dbc_bcids.size()));
5531
5532 for (const auto & bc_id : dbc_bcids)
5533 {
5534 // DirichletBoundary id sets should be consistent across all ranks
5535 libmesh_assert(mesh.comm().verify(bc_id));
5536
5537 bool found_bcid = (mesh_side_bcids.find(bc_id) != mesh_side_bcids.end() ||
5538 mesh_edge_bcids.find(bc_id) != mesh_edge_bcids.end() ||
5539 mesh_node_bcids.find(bc_id) != mesh_node_bcids.end());
5540
5541 // On a distributed mesh, boundary id sets may *not* be
5542 // consistent across all ranks, since not all ranks see all
5543 // boundaries
5544 mesh.comm().max(found_bcid);
5545
5546 libmesh_error_msg_if(!found_bcid,
5547 "Could not find Dirichlet boundary id " << bc_id << " in mesh!");
5548 }
5549}
timpi_pure bool verify(const T &r) const
const std::set< boundary_id_type > & get_edge_boundary_ids() const
const std::set< boundary_id_type > & get_boundary_ids() const
const std::set< boundary_id_type > & get_node_boundary_ids() const
std::set< boundary_id_type > b
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition mesh_base.h:170

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

Referenced by create_dof_constraints().

◆ check_for_constraint_loops()

void libMesh::DofMap::check_for_constraint_loops ( )

Definition at line 4509 of file dof_map_constraints.C.

4510{
4511 // Create a set containing the DOFs we already depend on
4512 typedef std::set<dof_id_type> RCSet;
4513 RCSet unexpanded_set;
4514
4515 // Use dof_constraints_copy in this method so that we don't
4516 // mess with _dof_constraints.
4517 DofConstraints dof_constraints_copy = _dof_constraints;
4518
4519 for (const auto & i : dof_constraints_copy)
4520 unexpanded_set.insert(i.first);
4521
4522 while (!unexpanded_set.empty())
4523 for (RCSet::iterator i = unexpanded_set.begin();
4524 i != unexpanded_set.end(); /* nothing */)
4525 {
4526 // If the DOF is constrained
4527 DofConstraints::iterator
4528 pos = dof_constraints_copy.find(*i);
4529
4530 libmesh_assert (pos != dof_constraints_copy.end());
4531
4532 DofConstraintRow & constraint_row = pos->second;
4533
4534 // Comment out "rhs" parts of this method copied from process_constraints
4535 // DofConstraintValueMap::iterator rhsit =
4536 // _primal_constraint_values.find(*i);
4537 // Number constraint_rhs = (rhsit == _primal_constraint_values.end()) ?
4538 // 0 : rhsit->second;
4539
4540 std::vector<dof_id_type> constraints_to_expand;
4541
4542 for (const auto & item : constraint_row)
4543 if (item.first != *i && this->is_constrained_dof(item.first))
4544 {
4545 unexpanded_set.insert(item.first);
4546 constraints_to_expand.push_back(item.first);
4547 }
4548
4549 for (const auto & expandable : constraints_to_expand)
4550 {
4551 const Real this_coef = constraint_row[expandable];
4552
4553 DofConstraints::const_iterator
4554 subpos = dof_constraints_copy.find(expandable);
4555
4556 libmesh_assert (subpos != dof_constraints_copy.end());
4557
4558 const DofConstraintRow & subconstraint_row = subpos->second;
4559
4560 for (const auto & item : subconstraint_row)
4561 {
4562 libmesh_error_msg_if(item.first == expandable, "Constraint loop detected");
4563
4564 constraint_row[item.first] += item.second * this_coef;
4565 }
4566
4567 // Comment out "rhs" parts of this method copied from process_constraints
4568 // DofConstraintValueMap::const_iterator subrhsit =
4569 // _primal_constraint_values.find(expandable);
4570 // if (subrhsit != _primal_constraint_values.end())
4571 // constraint_rhs += subrhsit->second * this_coef;
4572
4573 constraint_row.erase(expandable);
4574 }
4575
4576 // Comment out "rhs" parts of this method copied from process_constraints
4577 // if (rhsit == _primal_constraint_values.end())
4578 // {
4579 // if (constraint_rhs != Number(0))
4580 // _primal_constraint_values[*i] = constraint_rhs;
4581 // else
4582 // _primal_constraint_values.erase(*i);
4583 // }
4584 // else
4585 // {
4586 // if (constraint_rhs != Number(0))
4587 // rhsit->second = constraint_rhs;
4588 // else
4589 // _primal_constraint_values.erase(rhsit);
4590 // }
4591
4592 if (constraints_to_expand.empty())
4593 i = unexpanded_set.erase(i);
4594 else
4595 ++i;
4596 }
4597}
The constraint matrix storage format.
Definition dof_map.h:112

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

Referenced by check_for_cyclic_constraints(), and process_constraints().

◆ check_for_cyclic_constraints()

void libMesh::DofMap::check_for_cyclic_constraints ( )

Throw an error if we detect any constraint loops, i.e.

A -> B -> C -> A that is, "dof A is constrained in terms of dof B which is constrained in terms of dof C which is constrained in terms of dof A", since these are not supported by libMesh and give erroneous results if they are present.

Note
The original "cyclic constraint" terminology was unfortunate since the word cyclic is used by some software to indicate an actual type of rotational/angular constraint and not (as here) a cyclic graph. The former nomenclature will eventually be deprecated in favor of "constraint loop".

Definition at line 4503 of file dof_map_constraints.C.

4504{
4505 // Eventually make this officially libmesh_deprecated();
4507}

References check_for_constraint_loops().

◆ clear()

void libMesh::DofMap::clear ( )
overridevirtual

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

Reimplemented from libMesh::DofMapBase.

Definition at line 871 of file dof_map.C.

872{
874
875 // we don't want to clear
876 // the coupling matrix!
877 // It should not change...
878 //_dof_coupling->clear();
879 //
880 // But it would be inconsistent to leave our coupling settings
881 // through a clear()...
882 _dof_coupling = nullptr;
883
884 // Reset ghosting functor statuses
885 {
886 for (const auto & gf : _coupling_functors)
887 {
888 libmesh_assert(gf);
890 }
891 this->_coupling_functors.clear();
892
893 // Go back to default coupling
894
895 _default_coupling->set_dof_coupling(this->_dof_coupling);
896 _default_coupling->set_n_levels(this->use_coupled_neighbor_dofs(this->_mesh));
897
899 }
900
901
902 {
903 for (const auto & gf : _algebraic_ghosting_functors)
904 {
905 libmesh_assert(gf);
907 }
908 this->_algebraic_ghosting_functors.clear();
909
910 // Go back to default send_list generation
911
912 // _default_evaluating->set_dof_coupling(this->_dof_coupling);
913 _default_evaluating->set_n_levels(1);
915 }
916
917 this->_shared_functors.clear();
918
919 _variables.clear();
920 _variable_groups.clear();
921 _var_to_vg.clear();
923 _array_variables.clear();
924 _first_scalar_df.clear();
925 this->clear_send_list();
926 this->clear_sparsity();
928
929#ifdef LIBMESH_ENABLE_AMR
930
931 _dof_constraints.clear();
935 _n_old_dfs = 0;
936 _first_old_df.clear();
937 _end_old_df.clear();
938 _first_old_scalar_df.clear();
939
940#endif
941
942 _matrices.clear();
943 if (_sc)
944 _sc->clear();
945}
dof_id_type _n_old_dfs
Total number of degrees of freedom on old dof objects.
std::vector< dof_id_type > _first_old_df
First old DOF index on processor p.
virtual void clear()
std::vector< dof_id_type > _end_old_df
Last old DOF index (plus 1) on processor p.
void clear_sparsity()
Clears the sparsity pattern.
Definition dof_map.C:1981
void clear_send_list()
Clears the _send_list vector.
Definition dof_map.h:507

References libMesh::libmesh_assert().

Referenced by libMesh::DistributedMesh::clear(), libMesh::ReplicatedMesh::clear(), and ~DofMap().

◆ clear_send_list()

void libMesh::DofMap::clear_send_list ( )
inline

Clears the _send_list vector.

This should be done in order to completely rebuild the send_list from scratch rather than merely adding to the existing send_list.

Definition at line 507 of file dof_map.h.

508 {
509 _send_list.clear();
510 }

References _send_list.

◆ clear_sparsity()

void libMesh::DofMap::clear_sparsity ( )

Clears the sparsity pattern.

Definition at line 1981 of file dof_map.C.

1982{
1983 _sp.reset();
1984}
std::unique_ptr< SparsityPattern::Build > _sp
The sparsity pattern of the global matrix.
Definition dof_map.h:2252

Referenced by libMesh::System::reinit(), and OverlappingCouplingGhostingTest::run_sparsity_pattern_test().

◆ comm()

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

Definition at line 97 of file parallel_object.h.

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

References libMesh::ParallelObject::_communicator.

Referenced by libMesh::__libmesh_petsc_diff_solver_jacobian(), libMesh::__libmesh_petsc_diff_solver_monitor(), libMesh::__libmesh_petsc_diff_solver_residual(), libMesh::ExactSolution::_compute_error(), libMesh::UniformRefinementEstimator::_estimate_error(), libMesh::Partitioner::_find_global_index_by_pid_map(), 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(), add_constraints_to_send_list(), add_cube_convex_hull_to_mesh(), libMesh::PetscDMWrapper::add_dofs_helper(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::TransientRBConstruction::add_IC_to_RB_space(), libMesh::RBEIMEvaluation::add_interpolation_data(), libMesh::CondensedEigenSystem::add_matrices(), libMesh::EigenSystem::add_matrices(), libMesh::System::add_matrix(), libMesh::System::add_matrix(), libMesh::System::add_matrix(), libMesh::RBConstruction::add_scaled_matrix_and_vector(), libMesh::System::add_vector(), libMesh::MeshTools::Modification::all_tri(), libMesh::LaplaceMeshSmoother::allgather_graph(), allgather_recursive_constraints(), libMesh::RBConstruction::allocate_data_structures(), libMesh::TransientRBConstruction::allocate_data_structures(), libMesh::TransientRBConstruction::assemble_affine_expansion(), libMesh::AdvectionSystem::assemble_claw_rhs(), libMesh::FEMSystem::assemble_qoi(), libMesh::Nemesis_IO::assert_symmetric_cmaps(), libMesh::MeshCommunication::assign_global_indices(), libMesh::Partitioner::assign_partitioning(), libMesh::MeshTools::Generation::build_extrusion(), libMesh::Partitioner::build_graph(), libMesh::InfElemBuilder::build_inf_elem(), libMesh::BoundaryInfo::build_node_list_from_side_list(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::EquationSystems::build_parallel_solution_vector(), libMesh::PetscDMWrapper::build_section(), libMesh::PetscDMWrapper::build_sf(), libMesh::MeshBase::cache_elem_data(), check_dirichlet_bcid_consistency(), libMesh::MeshTetInterface::check_hull_integrity(), libMesh::MeshBase::complete_preparation(), libMesh::RBConstruction::compute_Fq_representor_innerprods(), libMesh::RBConstruction::compute_max_error_bound(), 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::RBConstruction::compute_output_dual_innerprods(), libMesh::RBConstruction::compute_residual_dual_norm_slow(), libMesh::RBSCMConstruction::compute_SCM_bounds_on_training_set(), computed_sparsity_already(), libMesh::Problem_Interface::computeJacobian(), libMesh::Problem_Interface::computePreconditioner(), PetscSolverConfiguration::configure_solver(), libMesh::ContinuationSystem::ContinuationSystem(), libMesh::MeshBase::copy_constraint_rows(), libMesh::ExodusII_IO::copy_elemental_solution(), libMesh::ExodusII_IO::copy_nodal_solution(), libMesh::ExodusII_IO::copy_scalar_solution(), libMesh::CondensedEigenSystem::copy_super_to_sub(), libMesh::MeshTools::correct_node_proc_ids(), libMesh::MeshTools::create_bounding_box(), create_dof_constraints(), libMesh::MeshTools::create_nodal_bounding_box(), libMesh::MeshRefinement::create_parent_error_vector(), libMesh::MeshTools::create_processor_bounding_box(), libMesh::MeshTools::create_subdomain_bounding_box(), libMesh::PetscMatrix< T >::create_submatrix_nosort(), create_wrapped_function(), libMesh::MeshCommunication::delete_remote_elements(), libMesh::MeshBase::detect_interior_parents(), libMesh::RBEIMEvaluation::distribute_bfs(), DMlibMeshFunction(), DMlibMeshJacobian(), DMlibMeshSetSystem_libMesh(), DMVariableBounds_libMesh(), libMesh::DTKSolutionTransfer::DTKSolutionTransfer(), libMesh::MeshRefinement::eliminate_unrefined_patches(), libMesh::RBEIMConstruction::enrich_eim_approximation_on_interiors(), libMesh::RBEIMConstruction::enrich_eim_approximation_on_nodes(), libMesh::RBEIMConstruction::enrich_eim_approximation_on_sides(), libMesh::TransientRBConstruction::enrich_RB_space(), libMesh::EpetraVector< T >::EpetraVector(), AssembleOptimization::equality_constraints(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::JumpErrorEstimator::estimate_error(), libMesh::PatchRecoveryErrorEstimator::estimate_error(), libMesh::WeightedPatchRecoveryErrorEstimator::estimate_error(), libMesh::SmoothnessEstimator::estimate_smoothness(), libMesh::MeshRefinement::flag_elements_by_elem_fraction(), libMesh::MeshRefinement::flag_elements_by_error_fraction(), libMesh::MeshRefinement::flag_elements_by_error_tolerance(), libMesh::MeshRefinement::flag_elements_by_mean_stddev(), libMesh::MeshRefinement::flag_elements_by_nelem_target(), libMesh::RBEIMEvaluation::gather_bfs(), gather_constraints(), libMesh::MeshfreeInterpolation::gather_remote_data(), libMesh::CondensedEigenSystem::get_eigenpair(), libMesh::RBEIMEvaluation::get_eim_basis_function_node_value(), libMesh::RBEIMEvaluation::get_eim_basis_function_side_value(), libMesh::RBEIMEvaluation::get_eim_basis_function_value(), libMesh::MeshBase::get_info(), libMesh::RBEIMEvaluation::get_interior_basis_functions_as_vecs(), libMesh::ImplicitSystem::get_linear_solver(), libMesh::RBEIMConstruction::get_max_abs_value(), libMesh::RBEIMConstruction::get_node_max_abs_value(), libMesh::RBEIMEvaluation::get_parametrized_function_node_value(), libMesh::RBEIMEvaluation::get_parametrized_function_side_value(), libMesh::RBEIMEvaluation::get_parametrized_function_value(), libMesh::RBEIMConstruction::get_random_point(), libMesh::RBEIMConstruction::get_random_point(), libMesh::RBEIMConstruction::get_random_point(), libMesh::MeshTetInterface::improve_hull_integrity(), AssembleOptimization::inequality_constraints(), AssembleOptimization::inequality_constraints_jacobian(), libMesh::StaticCondensation::init(), libMesh::TimeSolver::init(), libMesh::SystemSubsetBySubdomain::init(), libMesh::LocationMap< T >::init(), libMesh::PetscDMWrapper::init_and_attach_petscdm(), libMesh::PetscDMWrapper::init_and_attach_petscdm(), ElasticitySystem::init_data(), libMesh::AdvectionSystem::init_data(), libMesh::ClawSystem::init_data(), libMesh::PetscDMWrapper::init_petscdm(), libMesh::ExodusII_IO_Helper::initialize(), libMesh::OptimizationSystem::initialize_equality_constraints_storage(), libMesh::OptimizationSystem::initialize_inequality_constraints_storage(), libMesh::RBEIMConstruction::initialize_parametrized_functions_in_training_set(), libMesh::RBEIMConstruction::inner_product(), integrate_function(), libMesh::MeshTools::Modification::interpolate_surface(), libMesh::MeshTools::libmesh_assert_consistent_distributed(), libMesh::MeshTools::libmesh_assert_consistent_distributed_nodes(), libMesh::MeshTools::libmesh_assert_contiguous_dof_ids(), libMesh::MeshTools::libmesh_assert_equal_connectivity(), libMesh::MeshTools::libmesh_assert_equal_points(), libMesh::MeshTools::libmesh_assert_parallel_consistent_new_node_procids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Elem >(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_topology_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), libMesh::MeshTools::libmesh_assert_valid_constraint_rows(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_flags(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_object_ids(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_p_levels(), libMesh::MeshTools::libmesh_assert_valid_refinement_flags(), libMesh::MeshTools::libmesh_assert_valid_unique_ids(), libMesh::libmesh_petsc_linesearch_shellfunc(), libMesh::libmesh_petsc_preconditioner_apply(), libMesh::libmesh_petsc_snes_mffd_interface(), libMesh::libmesh_petsc_snes_postcheck(), 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::LinearImplicitSystem::LinearImplicitSystem(), main(), libMesh::MeshCommunication::make_elems_parallel_consistent(), libMesh::MeshCommunication::make_new_node_proc_ids_parallel_consistent(), libMesh::MeshCommunication::make_new_nodes_parallel_consistent(), libMesh::MeshCommunication::make_node_bcids_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::TransientRBConstruction::mass_matrix_scaled_matvec(), libMesh::FEMSystem::mesh_position_set(), libMesh::TriangulatorInterface::MeshedHole::MeshedHole(), LinearElasticityWithContact::move_mesh(), libMesh::DistributedMesh::n_active_elem(), libMesh::MeshTools::n_active_levels(), libMesh::BoundaryInfo::n_boundary_conds(), libMesh::MeshTools::n_connected_components(), n_constrained_dofs(), libMesh::MeshBase::n_constraint_rows(), n_dofs(), n_dofs_per_processor(), libMesh::BoundaryInfo::n_edge_conds(), libMesh::CondensedEigenSystem::n_global_non_condensed_dofs(), libMesh::MeshTools::n_levels(), MixedOrderTest::n_neighbor_links(), libMesh::BoundaryInfo::n_nodeset_conds(), libMesh::SparsityPattern::Build::n_nonzeros(), libMesh::MeshTools::n_p_levels(), libMesh::BoundaryInfo::n_shellface_conds(), libMesh::RBEIMEvaluation::node_distribute_bfs(), libMesh::RBEIMEvaluation::node_gather_bfs(), libMesh::RBEIMConstruction::node_inner_product(), libMesh::PetscVector< T >::operator=(), libMesh::MeshBase::operator==(), libMesh::DistributedMesh::parallel_max_elem_id(), libMesh::DistributedMesh::parallel_max_node_id(), libMesh::DistributedMesh::parallel_max_unique_id(), libMesh::ReplicatedMesh::parallel_max_unique_id(), libMesh::DistributedMesh::parallel_n_elem(), libMesh::DistributedMesh::parallel_n_nodes(), libMesh::SparsityPattern::Build::parallel_sync(), libMesh::BoundaryInfo::parallel_sync_node_ids(), libMesh::BoundaryInfo::parallel_sync_side_ids(), libMesh::MeshTools::paranoid_n_levels(), libMesh::Partitioner::partition(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::petsc_auto_fieldsplit(), LaplaceSystem::postprocess(), PoissonSystem::postprocess(), libMesh::MeshBase::print_constraint_rows(), print_dof_constraints(), process_mesh_constraint_rows(), libMesh::Partitioner::processor_pairs_to_interface_nodes(), libMesh::InterMeshProjection::project_system_vectors(), libMesh::XdrIO::read(), libMesh::Nemesis_IO::read(), FEMParameters::read(), libMesh::EquationSystems::read(), libMesh::CheckpointIO::read_header(), libMesh::ExodusII_IO::read_header(), libMesh::System::read_header(), libMesh::XdrIO::read_header(), libMesh::RBEIMEvaluation::read_in_interior_basis_functions(), libMesh::RBEIMEvaluation::read_in_node_basis_functions(), libMesh::RBEIMEvaluation::read_in_side_basis_functions(), libMesh::RBEvaluation::read_in_vectors_from_multiple_files(), libMesh::RBConstruction::read_riesz_representors_from_files(), libMesh::TransientRBConstruction::read_riesz_representors_from_files(), libMesh::System::read_SCALAR_dofs(), libMesh::XdrIO::read_serialized_bc_names(), libMesh::XdrIO::read_serialized_bcs_helper(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::System::read_serialized_vector(), libMesh::Nemesis_IO_Helper::read_var_names_impl(), MeshFunctionTest::read_variable_info_from_output_data(), libMesh::MeshBase::recalculate_n_partitions(), libMesh::SimplexRefiner::refine_via_edges(), libMesh::StaticCondensationDofMap::reinit(), libMesh::BoundaryInfo::remove_edge_id(), libMesh::BoundaryInfo::remove_node_id(), libMesh::BoundaryInfo::remove_shellface_id(), libMesh::BoundaryInfo::remove_side_id(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::DistributedMesh::renumber_nodes_and_elements(), LinearElasticityWithContact::residual_and_jacobian(), OverlappingAlgebraicGhostingTest::run_ghosting_test(), OverlappingCouplingGhostingTest::run_sparsity_pattern_test(), scale_mesh_and_plot(), scatter_constraints(), libMesh::CheckpointIO::select_split_config(), libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::send_and_insert_dof_values(), libMesh::TransientRBConstruction::set_error_temporal_data(), libMesh::Partitioner::set_interface_node_processor_ids_BFS(), libMesh::Partitioner::set_interface_node_processor_ids_linear(), libMesh::Partitioner::set_interface_node_processor_ids_petscpartitioner(), libMesh::Partitioner::set_node_processor_ids(), set_nonlocal_dof_objects(), libMesh::Partitioner::set_parent_processor_ids(), libMesh::PetscDMWrapper::set_point_range_in_section(), libMesh::PetscDiffSolver::setup_petsc_data(), libMesh::RBEIMEvaluation::side_distribute_bfs(), libMesh::RBEIMEvaluation::side_gather_bfs(), libMesh::RBEIMConstruction::side_inner_product(), libMesh::Partitioner::single_partition(), libMesh::LaplaceMeshSmoother::smooth(), libMesh::VariationalMeshSmoother::smooth(), libMesh::NoxNonlinearSolver< Number >::solve(), libMesh::ClawSystem::solve_conservation_law(), libMesh::split_mesh(), libMesh::RBEIMConstruction::store_eim_solutions_for_training_set(), libMesh::MeshBase::subdomain_ids(), libMesh::BoundaryInfo::sync(), libMesh::MeshBase::sync_subdomain_name_map(), ConstraintOperatorTest::test1DCoarseningNewNodes(), ConstraintOperatorTest::test1DCoarseningOperator(), MeshFunctionTest::test_bad_gradient_var_with_out_of_mesh_value(), MeshFunctionTest::test_bad_hessian_var_with_out_of_mesh_value(), MeshfunctionDFEM::test_mesh_function_dfem(), MeshfunctionDFEM::test_mesh_function_dfem_grad(), MeshFunctionTest::test_p_level(), ExodusC0PolyhedronTest::test_write_and_read_hexagonal_prism(), ExodusC0PolygonTest::test_write_and_read_pentagon(), DofMapTest::testBadElemFECombo(), SystemsTest::testBlockRestrictedVarNDofs(), BoundaryInfoTest::testBoundaryOnChildrenErrors(), CheckpointIOTest::testC0PolygonCheckpoint(), VolumeTest::testC0PolygonMethods(), CheckpointIOTest::testC0PolyhedronCheckpoint(), VolumeTest::testC0PolyhedronMethods(), ConstraintOperatorTest::testCoreform(), ConnectedComponentsTest::testEdge(), MeshInputTest::testExodusIGASidesets(), MeshTriangulationTest::testFoundCenters(), PointLocatorTest::testLocator(), BoundaryInfoTest::testMesh(), BoundaryMeshSubdomainTest::testPerBoundarySubdomain(), PointLocatorTest::testPlanar(), MeshTriangulationTest::testPoly2TriEdge3ToTri7CenterFixup(), MeshTriangulationTest::testPoly2TriRefinementBase(), SystemsTest::testProjectCubeWithMeshFunction(), SystemsTest::testProjectScalarCoarsening(), BoundaryInfoTest::testRenumber(), BoundaryInfoTest::testSelectiveRenumber(), BoundaryMeshSubdomainTest::testSingleSubdomain(), CheckpointIOTest::testSplitter(), MeshInputTest::testTetgenIO(), MeshTriangulationTest::testTriangulatorInterp(), MeshTriangulationTest::testTriangulatorMeshedHoles(), MeshTriangulationTest::testTriangulatorRoundHole(), MeshSmootherTest::testVariationalSmoother(), libMesh::MeshTools::total_weight(), libMesh::RBConstruction::train_reduced_basis_with_POD(), libMesh::MeshfreeSolutionTransfer::transfer(), libMesh::MeshFunctionSolutionTransfer::transfer(), libMesh::Poly2TriTriangulator::triangulate(), libMesh::RBConstruction::truth_assembly(), libMesh::TransientRBConstruction::truth_assembly(), update_current_local_solution(), libMesh::TransientRBConstruction::update_RB_initial_condition_all_N(), libMesh::RBConstruction::update_RB_system_matrices(), libMesh::TransientRBConstruction::update_RB_system_matrices(), libMesh::TransientRBConstruction::update_residual_terms(), libMesh::RBConstruction::update_residual_terms(), libMesh::MeshTools::volume(), libMesh::STLIO::write(), libMesh::XdrIO::write(), libMesh::NameBasedIO::write(), libMesh::VTKIO::write_nodal_data(), libMesh::RBEIMEvaluation::write_out_interior_basis_functions(), libMesh::RBEIMEvaluation::write_out_node_basis_functions(), libMesh::RBEIMEvaluation::write_out_side_basis_functions(), libMesh::RBEvaluation::write_out_vectors(), libMesh::RBConstruction::write_riesz_representors_to_files(), libMesh::TransientRBConstruction::write_riesz_representors_to_files(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), libMesh::XdrIO::write_serialized_nodesets(), libMesh::RBDataSerialization::RBEvaluationSerialization::write_to_file(), libMesh::RBDataSerialization::TransientRBEvaluationSerialization::write_to_file(), libMesh::RBDataSerialization::RBEIMEvaluationSerialization::write_to_file(), and libMesh::RBDataSerialization::RBSCMEvaluationSerialization::write_to_file().

◆ compute_dof_info()

std::size_t libMesh::DofMapBase::compute_dof_info ( dof_id_type  n_local_dofs)
protectedinherited

compute the key degree of freedom information given the local number of degrees of freedom on this process

Returns
The total number of DOFs for the System, summed across all procs.

Referenced by libMesh::StaticCondensationDofMap::reinit().

◆ compute_sparsity()

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

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

Definition at line 1960 of file dof_map.C.

1961{
1963
1964 // It is possible that some \p SparseMatrix implementations want to
1965 // see the sparsity pattern before we throw it away. If so, we
1966 // share a view of its arrays, and we pass it in to the matrices.
1967 for (const auto & mat : _matrices)
1968 {
1969 mat->attach_sparsity_pattern (*_sp);
1971 mat->update_sparsity_pattern (_sp->get_sparsity_pattern());
1972 }
1973 // If we don't need the full sparsity pattern anymore, free the
1974 // parts of it we don't need.
1976 _sp->clear_full_sparsity();
1977}
std::unique_ptr< SparsityPattern::Build > build_sparsity(const MeshBase &mesh, bool calculate_constrained=false, bool use_condensed_system=false) const
Builds a sparsity pattern for matrices using the current degree-of-freedom numbering and coupling.
Definition dof_map.C:63

References mesh.

Referenced by libMesh::System::init_matrices(), libMesh::System::reinit(), and OverlappingCouplingGhostingTest::run_sparsity_pattern_test().

◆ computed_sparsity_already()

bool libMesh::DofMap::computed_sparsity_already ( ) const

Returns true iff a sparsity pattern has already been computed.

Definition at line 258 of file dof_map.C.

259{
261 (!_sp->get_n_nz().empty() ||
262 !_sp->get_n_oz().empty());
263 this->comm().max(computed_sparsity_already);
265}
bool computed_sparsity_already() const
Returns true iff a sparsity pattern has already been computed.
Definition dof_map.C:258

References _sp, libMesh::ParallelObject::comm(), computed_sparsity_already(), and libMesh::Parallel::Communicator::max().

Referenced by computed_sparsity_already(), libMesh::System::solve_for_unconstrained_dofs(), and update_sparsity_pattern().

◆ constrain_element_dyad_matrix()

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

Constrains a dyadic element matrix B = v w'.

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

Definition at line 2511 of file dof_map.h.

2514 {}

Referenced by assemble().

◆ constrain_element_matrix() [1/2]

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

Constrains the element matrix.

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

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

Definition at line 2485 of file dof_map.h.

2487 {}

Referenced by libMesh::ClawSystem::assemble_advection_matrices(), assemble_mass(), libMesh::ClawSystem::assemble_mass_matrix(), assemble_matrices(), assemble_SchroedingerEquation(), LargeDeformationElasticity::jacobian(), and Biharmonic::JR::residual_and_jacobian().

◆ constrain_element_matrix() [2/2]

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

Constrains the element matrix.

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

Definition at line 2489 of file dof_map.h.

2492 {}

◆ constrain_element_matrix_and_vector()

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

Constrains the element matrix and vector.

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

Definition at line 2498 of file dof_map.h.

2501 {}

Referenced by libMesh::RBConstruction::add_scaled_matrix_and_vector(), LinearElasticity::assemble(), assemble(), assemble(), AssembleOptimization::assemble_A_and_F(), assemble_cd(), assemble_cd(), assemble_elasticity(), assemble_poisson(), assemble_shell(), assemble_stokes(), and LinearElasticityWithContact::residual_and_jacobian().

◆ constrain_element_residual()

void libMesh::DofMap::constrain_element_residual ( DenseVector< Number > &  rhs,
std::vector< dof_id_type > &  elem_dofs,
NumericVector< Number > &  solution_local 
) const

Constrains the element residual.

The element Jacobian is square, and the elem_dofs should correspond to the global DOF indices of both the rows and columns of the element matrix, and the dof constraint should not include any heterogeneous terms.

The residual-constraining version of this method creates linear systems in which heterogeneously constrained degrees of freedom create non-zero residual terms when not at their correct offset values, as would be appropriate for finding a solution to a nonlinear problem in a quasi-Newton solve.

The solution vector passed in should be a serialized or ghosted primal solution

Definition at line 2762 of file dof_map_constraints.C.

2766{
2767 libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
2768
2769 libmesh_assert (solution_local.type() == SERIAL ||
2770 solution_local.type() == GHOSTED);
2771
2772 // check for easy return
2773 if (this->_dof_constraints.empty())
2774 return;
2775
2776 // The constrained RHS is built up as C^T F
2778
2779 this->build_constraint_matrix (C, elem_dofs);
2780
2781 LOG_SCOPE("cnstrn_elem_residual()", "DofMap");
2782
2783 // It is possible that the matrix is not constrained at all.
2784 if (C.n() != elem_dofs.size())
2785 return;
2786
2787 // Compute the matrix-vector product C^T F
2788 DenseVector<Number> old_rhs(rhs);
2789 C.vector_mult_transpose(rhs, old_rhs);
2790
2791 for (unsigned int i=0,
2792 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2793 i != n_elem_dofs; i++)
2794 {
2795 const dof_id_type dof_id = elem_dofs[i];
2796
2797 if (auto pos = _dof_constraints.find(dof_id);
2798 pos != _dof_constraints.end())
2799 {
2800 // This will put a nonsymmetric entry in the constraint
2801 // row to ensure that the linear system produces the
2802 // correct value for the constrained DOF.
2803 const DofConstraintRow & constraint_row = pos->second;
2804
2805 Number & rhs_val = rhs(i);
2806 rhs_val = 0;
2807 for (const auto & [constraining_dof, coef] : constraint_row)
2808 rhs_val -= coef * solution_local(constraining_dof);
2809 rhs_val += solution_local(dof_id);
2810 }
2811 }
2812}
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
Performs the matrix-vector multiplication, dest := (*this)^T * arg.
virtual unsigned int size() const override final
ParallelType type() const

References _dof_constraints, build_constraint_matrix(), libMesh::GHOSTED, libMesh::libmesh_assert(), libMesh::DenseMatrixBase< T >::n(), libMesh::SERIAL, libMesh::DenseVector< T >::size(), libMesh::NumericVector< T >::type(), and libMesh::DenseMatrix< T >::vector_mult_transpose().

◆ constrain_element_vector()

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

Constrains the element vector.

Definition at line 2494 of file dof_map.h.

2496 {}

Referenced by LargeDeformationElasticity::residual(), Biharmonic::JR::residual_and_jacobian(), and InfFERadialTest::testRefinement().

◆ constrain_nothing()

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

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

2516{}

◆ constrain_p_dofs()

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

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

Definition at line 5377 of file dof_map_constraints.C.

5381{
5382 // We're constraining dofs on elem which correspond to p refinement
5383 // levels above p - this only makes sense if elem's p refinement
5384 // level is above p.
5385 libmesh_assert_greater (elem->p_level(), p);
5386 libmesh_assert_less (s, elem->n_sides());
5387
5388 const unsigned int sys_num = this->sys_number();
5389 FEType fe_type = this->variable_type(var);
5390
5391 const unsigned int n_nodes = elem->n_nodes();
5392 for (unsigned int n = 0; n != n_nodes; ++n)
5393 if (elem->is_node_on_side(n, s))
5394 {
5395 const Node & node = elem->node_ref(n);
5396 const unsigned int low_nc =
5397 FEInterface::n_dofs_at_node (fe_type, p, elem, n);
5398 const unsigned int high_nc =
5399 FEInterface::n_dofs_at_node (fe_type, elem, n);
5400
5401 // since we may be running this method concurrently
5402 // on multiple threads we need to acquire a lock
5403 // before modifying the _dof_constraints object.
5404 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
5405
5406 if (elem->is_vertex(n))
5407 {
5408 // Add "this is zero" constraint rows for high p vertex
5409 // dofs
5410 for (unsigned int i = low_nc; i != high_nc; ++i)
5411 {
5412 _dof_constraints[node.dof_number(sys_num,var,i)].clear();
5413 _primal_constraint_values.erase(node.dof_number(sys_num,var,i));
5414 }
5415 }
5416 else
5417 {
5418 const unsigned int total_dofs = node.n_comp(sys_num, var);
5419 libmesh_assert_greater_equal (total_dofs, high_nc);
5420 // Add "this is zero" constraint rows for high p
5421 // non-vertex dofs, which are numbered in reverse
5422 for (unsigned int j = low_nc; j != high_nc; ++j)
5423 {
5424 const unsigned int i = total_dofs - j - 1;
5425 _dof_constraints[node.dof_number(sys_num,var,i)].clear();
5426 _primal_constraint_values.erase(node.dof_number(sys_num,var,i));
5427 }
5428 }
5429 }
5430}
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
const Node & node_ref(const unsigned int i) const
Definition elem.h:2538
virtual unsigned int n_nodes() const =0
virtual bool is_vertex(const unsigned int i) const =0
virtual unsigned int n_sides() const =0
unsigned int p_level() const
Definition elem.h:3125
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition fe_type.h:197
spin_mutex spin_mtx
A convenient spin mutex object which can be used for obtaining locks.
Definition threads.C:30

References _dof_constraints, _primal_constraint_values, libMesh::DofObject::dof_number(), libMesh::Elem::is_node_on_side(), libMesh::Elem::is_vertex(), libMesh::DofObject::n_comp(), libMesh::FEInterface::n_dofs_at_node(), libMesh::Elem::n_nodes(), n_nodes, libMesh::Elem::n_sides(), libMesh::Elem::node_ref(), libMesh::Elem::p_level(), libMesh::Threads::spin_mtx, sys_number(), and variable_type().

Referenced by libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), and libMesh::FEGenericBase< OutputType >::compute_proj_constraints().

◆ constrained_sparsity_construction()

bool libMesh::DofMap::constrained_sparsity_construction ( )
inline

Returns true iff the current policy when constructing sparsity patterns is to explicitly account for sparsity entries created by constraint matrix pre- and post- application.

Definition at line 2560 of file dof_map.h.

2561{
2562#ifdef LIBMESH_ENABLE_CONSTRAINTS
2564#else
2565 return true;
2566#endif
2567}

References _constrained_sparsity_construction.

◆ constraint_rows_begin()

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

Definition at line 1164 of file dof_map.h.

1165 { return _dof_constraints.begin(); }

References _dof_constraints.

◆ constraint_rows_end()

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

Definition at line 1170 of file dof_map.h.

1171 { return _dof_constraints.end(); }

References _dof_constraints.

◆ coupling_functors_begin()

GhostingFunctorIterator libMesh::DofMap::coupling_functors_begin ( ) const
inline

Beginning of range of coupling functors.

Definition at line 366 of file dof_map.h.

367 { return _coupling_functors.begin(); }

References _coupling_functors.

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

◆ coupling_functors_end()

GhostingFunctorIterator libMesh::DofMap::coupling_functors_end ( ) const
inline

End of range of coupling functors.

Definition at line 372 of file dof_map.h.

373 { return _coupling_functors.end(); }

References _coupling_functors.

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

◆ create_dof_constraints()

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

Rebuilds the raw degree of freedom and DofObject constraints, based on attached DirichletBoundary objects and on non-conforming interface in adapted meshes.

A time is specified for use in building time-dependent Dirichlet constraints.

Definition at line 1736 of file dof_map_constraints.C.

1737{
1738 parallel_object_only();
1739
1740 LOG_SCOPE("create_dof_constraints()", "DofMap");
1741
1743
1744 // The user might have set boundary conditions after the mesh was
1745 // prepared; we should double-check that those boundary conditions
1746 // are still consistent.
1747#ifdef DEBUG
1749#endif
1750
1751 // In a distributed mesh we might have constraint rows on some
1752 // processors but not all; if we have constraint rows on *any*
1753 // processor then we need to process them.
1754 bool constraint_rows_empty = mesh.get_constraint_rows().empty();
1755 this->comm().min(constraint_rows_empty);
1756
1757 // We might get constraint equations from AMR hanging nodes in
1758 // 2D/3D, or from spline constraint rows or boundary conditions in
1759 // any dimension
1760 const bool possible_local_constraints = false
1761 || !mesh.n_elem()
1762 || !constraint_rows_empty
1763#ifdef LIBMESH_ENABLE_AMR
1764 || mesh.mesh_dimension() > 1
1765#endif
1766#ifdef LIBMESH_ENABLE_PERIODIC
1767 || !_periodic_boundaries->empty()
1768#endif
1769#ifdef LIBMESH_ENABLE_DIRICHLET
1770 || !_dirichlet_boundaries->empty()
1771#endif
1772 ;
1773
1774 // Even if we don't have constraints, another processor might.
1775 bool possible_global_constraints = possible_local_constraints;
1776#if defined(LIBMESH_ENABLE_PERIODIC) || defined(LIBMESH_ENABLE_DIRICHLET) || defined(LIBMESH_ENABLE_AMR)
1777 libmesh_assert(this->comm().verify(mesh.is_serial()));
1778
1779 this->comm().max(possible_global_constraints);
1780#endif
1781
1782 // Recalculate dof constraints from scratch. (Or just clear them,
1783 // if the user has just deleted their last dirichlet/periodic/user
1784 // constraint)
1785 // Note: any _stashed_dof_constraints are not cleared as it
1786 // may be the user's intention to restore them later.
1787#ifdef LIBMESH_ENABLE_CONSTRAINTS
1788 _dof_constraints.clear();
1791#endif
1792#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
1793 _node_constraints.clear();
1794#endif
1795
1796 if (!possible_global_constraints)
1797 return;
1798
1799 // Here we build the hanging node constraints. This is done
1800 // by enforcing the condition u_a = u_b along hanging sides.
1801 // u_a = u_b is collocated at the nodes of side a, which gives
1802 // one row of the constraint matrix.
1803
1804 // Processors only compute their local constraints
1805 ConstElemRange range (mesh.local_elements_begin(),
1806 mesh.local_elements_end());
1807
1808 // Global computation fails if we're using a FEMFunctionBase BC on a
1809 // ReplicatedMesh in parallel
1810 // ConstElemRange range (mesh.elements_begin(),
1811 // mesh.elements_end());
1812
1813 // compute_periodic_constraints requires a point_locator() from our
1814 // Mesh, but point_locator() construction is parallel and threaded.
1815 // Rather than nest threads within threads we'll make sure it's
1816 // preconstructed.
1817#ifdef LIBMESH_ENABLE_PERIODIC
1818 bool need_point_locator = !_periodic_boundaries->empty() && !range.empty();
1819
1820 this->comm().max(need_point_locator);
1821
1822 if (need_point_locator)
1824#endif
1825
1826#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
1827 Threads::parallel_for (range,
1828 ComputeNodeConstraints (_node_constraints,
1829#ifdef LIBMESH_ENABLE_PERIODIC
1831#endif
1832 mesh));
1833#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
1834
1835
1836 // Look at all the variables in the system. Reset the element
1837 // range at each iteration -- there is no need to reconstruct it.
1838 const auto n_vars = this->n_variables();
1839 for (unsigned int variable_number=0; variable_number<n_vars;
1840 ++variable_number, range.reset())
1841 Threads::parallel_for (range,
1842 ComputeConstraints (_dof_constraints,
1843 *this,
1844#ifdef LIBMESH_ENABLE_PERIODIC
1846#endif
1847 mesh,
1849
1850#ifdef LIBMESH_ENABLE_DIRICHLET
1851
1852 if (!_dirichlet_boundaries->empty())
1853 {
1854 // Sanity check that the boundary ids associated with the
1855 // DirichletBoundary objects are actually present in the
1856 // mesh. We do this check by default, but in cases where you
1857 // intentionally add "inconsistent but valid" DirichletBoundary
1858 // objects in parallel, this check can deadlock since it does a
1859 // collective communication internally. In that case it is
1860 // possible to disable this check by setting the flag to false.
1862 for (const auto & dirichlet : *_dirichlet_boundaries)
1863 this->check_dirichlet_bcid_consistency(mesh, *dirichlet);
1864
1865 // Threaded loop over local over elems applying all Dirichlet BCs
1867 (range,
1868 ConstrainDirichlet(*this, mesh, time, *_dirichlet_boundaries,
1869 AddPrimalConstraint(*this)));
1870
1871 // Threaded loop over local over elems per QOI applying all adjoint
1872 // Dirichlet BCs. Note that the ConstElemRange is reset before each
1873 // execution of Threads::parallel_for().
1874
1875 for (auto qoi_index : index_range(_adjoint_dirichlet_boundaries))
1876 {
1877 const DirichletBoundaries & adb_q =
1878 *(_adjoint_dirichlet_boundaries[qoi_index]);
1879
1880 if (!adb_q.empty())
1882 (range.reset(),
1883 ConstrainDirichlet(*this, mesh, time, adb_q,
1884 AddAdjointConstraint(*this, qoi_index)));
1885 }
1886 }
1887
1888#endif // LIBMESH_ENABLE_DIRICHLET
1889
1890 // Handle spline node constraints last, so we can try to move
1891 // existing constraints onto the spline basis if necessary.
1892 if (!constraint_rows_empty)
1893 this->process_mesh_constraint_rows(mesh);
1894}
void min(const T &r, T &o, Request &req) const
We're using a class instead of a typedef to allow forward declarations and future flexibility.
void check_dirichlet_bcid_consistency(const MeshBase &mesh, const DirichletBoundary &boundary) const
Check that all the ids in dirichlet_bcids are actually present in the mesh.
void process_mesh_constraint_rows(const MeshBase &mesh)
Adds any spline constraints from the Mesh to our DoF constraints.
unsigned int variable_number(std::string_view var) const
Definition dof_map.h:2991
bool is_prepared() const
Definition mesh_base.C:1064
unsigned int mesh_dimension() const
Definition mesh_base.C:430
virtual dof_id_type n_elem() const =0
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition mesh_base.C:1833
The StoredRange class defines a contiguous, divisible set of objects.
void libmesh_assert_valid_boundary_ids(const MeshBase &mesh)
A function for verifying that boundary condition ids match across processors.
void parallel_for(const Range &range, const Body &body, unsigned int n_threads=libMesh::n_threads())
Execute the provided function object in parallel on the specified range.

References _adjoint_constraint_values, _adjoint_dirichlet_boundaries, _dirichlet_boundaries, _dof_constraints, _node_constraints, _periodic_boundaries, _primal_constraint_values, _verify_dirichlet_bc_consistency, check_dirichlet_bcid_consistency(), libMesh::ParallelObject::comm(), libMesh::StoredRange< iterator_type, object_type >::empty(), libMesh::MeshBase::get_constraint_rows(), libMesh::index_range(), libMesh::MeshBase::is_prepared(), libMesh::MeshBase::is_serial(), libMesh::libmesh_assert(), libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), libMesh::Parallel::Communicator::max(), mesh, libMesh::MeshBase::mesh_dimension(), libMesh::Parallel::Communicator::min(), libMesh::MeshBase::n_elem(), n_variables(), n_vars(), libMesh::Threads::parallel_for(), process_mesh_constraint_rows(), libMesh::StoredRange< iterator_type, object_type >::reset(), libMesh::MeshBase::sub_point_locator(), and variable_number().

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

◆ create_static_condensation()

void libMesh::DofMap::create_static_condensation ( MeshBase mesh,
System system 
)

Add a static condensation class.

Definition at line 3135 of file dof_map.C.

3136{
3137 _sc = std::make_unique<StaticCondensationDofMap>(mesh, sys, *this);
3138}

References mesh.

◆ default_algebraic_ghosting()

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

Default algebraic ghosting functor.

Definition at line 440 of file dof_map.h.

440{ return *_default_evaluating; }

References _default_evaluating.

Referenced by DefaultCouplingTest::testCoupling(), and PointNeighborCouplingTest::testCoupling().

◆ default_coupling()

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

Default coupling functor.

Definition at line 378 of file dof_map.h.

378{ return *_default_coupling; }

References _default_coupling.

Referenced by PointNeighborCouplingTest::testCoupling().

◆ disable_print_counter_info()

void libMesh::ReferenceCounter::disable_print_counter_info ( )
staticinherited

Definition at line 100 of file reference_counter.C.

101{
102 _enable_print_counter = false;
103 return;
104}
static bool _enable_print_counter
Flag to control whether reference count information is printed when print_info is called.

References libMesh::ReferenceCounter::_enable_print_counter.

◆ distribute_dofs()

std::size_t libMesh::DofMap::distribute_dofs ( MeshBase mesh)

Distribute dofs on the current mesh.

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

Returns
The total number of DOFs for the System, summed across all procs.

Definition at line 949 of file dof_map.C.

950{
951 // This function must be run on all processors at once
952 parallel_object_only();
953
954 // Log how long it takes to distribute the degrees of freedom
955 LOG_SCOPE("distribute_dofs()", "DofMap");
956
957 libmesh_assert (mesh.is_prepared());
958
959 const processor_id_type proc_id = this->processor_id();
960#ifndef NDEBUG
961 const processor_id_type n_proc = this->n_processors();
962#endif
963
964 // libmesh_assert_greater (this->n_variables(), 0);
965 libmesh_assert_less (proc_id, n_proc);
966
967 // Data structure to ensure we can correctly combine
968 // subdomain-restricted variables with constraining nodes from
969 // different subdomains
970 const std::map<const Node *, std::set<subdomain_id_type>>
971 constraining_subdomains =
973
974 // re-init in case the mesh has changed
975 this->reinit(mesh,
976 constraining_subdomains);
977
978 // By default distribute variables in a
979 // var-major fashion, but allow run-time
980 // specification
981 bool node_major_dofs = libMesh::on_command_line ("--node-major-dofs");
982
983 // The DOF counter, will be incremented as we encounter
984 // new degrees of freedom
985 dof_id_type next_free_dof = 0;
986
987 // Clear the send list before we rebuild it
988 this->clear_send_list();
989
990 // Set temporary DOF indices on this processor
991 if (node_major_dofs)
993 (next_free_dof, mesh, constraining_subdomains);
994 else
996 (next_free_dof, mesh, constraining_subdomains);
997
998 // Get DOF counts on all processors
999 const auto n_dofs = this->compute_dof_info(next_free_dof);
1000
1001 // Clear all the current DOF indices
1002 // (distribute_dofs expects them cleared!)
1003 this->invalidate_dofs(mesh);
1004
1005 next_free_dof = _first_df[proc_id];
1006
1007 // Set permanent DOF indices on this processor
1008 if (node_major_dofs)
1010 (next_free_dof, mesh, constraining_subdomains);
1011 else
1013 (next_free_dof, mesh, constraining_subdomains);
1014
1015 libmesh_assert_equal_to (next_free_dof, _end_df[proc_id]);
1016
1017 //------------------------------------------------------------
1018 // At this point, all n_comp and dof_number values on local
1019 // DofObjects should be correct, but a DistributedMesh might have
1020 // incorrect values on non-local DofObjects. Let's request the
1021 // correct values from each other processor.
1022
1023 if (this->n_processors() > 1)
1024 {
1025 this->set_nonlocal_dof_objects(mesh.nodes_begin(),
1026 mesh.nodes_end(),
1028
1029 this->set_nonlocal_dof_objects(mesh.elements_begin(),
1030 mesh.elements_end(),
1032 }
1033
1034#ifdef DEBUG
1035 {
1036 const unsigned int
1037 sys_num = this->sys_number();
1038
1039 // Processors should all agree on DoF ids for the newly numbered
1040 // system.
1042
1043 // DoF processor ids should match DofObject processor ids
1044 for (auto & node : mesh.node_ptr_range())
1045 {
1046 DofObject const * const dofobj = node;
1047 const processor_id_type obj_proc_id = dofobj->processor_id();
1048
1049 for (auto v : make_range(dofobj->n_vars(sys_num)))
1050 for (auto c : make_range(dofobj->n_comp(sys_num,v)))
1051 {
1052 const dof_id_type dofid = dofobj->dof_number(sys_num,v,c);
1053 libmesh_assert_greater_equal (dofid, this->first_dof(obj_proc_id));
1054 libmesh_assert_less (dofid, this->end_dof(obj_proc_id));
1055 }
1056 }
1057
1058 for (auto & elem : mesh.element_ptr_range())
1059 {
1060 DofObject const * const dofobj = elem;
1061 const processor_id_type obj_proc_id = dofobj->processor_id();
1062
1063 for (auto v : make_range(dofobj->n_vars(sys_num)))
1064 for (auto c : make_range(dofobj->n_comp(sys_num,v)))
1065 {
1066 const dof_id_type dofid = dofobj->dof_number(sys_num,v,c);
1067 libmesh_assert_greater_equal (dofid, this->first_dof(obj_proc_id));
1068 libmesh_assert_less (dofid, this->end_dof(obj_proc_id));
1069 }
1070 }
1071 }
1072#endif
1073
1074 // start finding SCALAR degrees of freedom
1075#ifdef LIBMESH_ENABLE_AMR
1077#endif
1078 _first_scalar_df.clear();
1080 dof_id_type current_SCALAR_dof_index = n_dofs - n_SCALAR_dofs();
1081
1082 // Calculate and cache the initial DoF indices for SCALAR variables.
1083 // This is an O(N_vars) calculation so we want to do it once per
1084 // renumbering rather than once per SCALAR_dof_indices() call
1085
1086 for (auto v : make_range(this->n_variables()))
1087 if (this->variable(v).type().family == SCALAR)
1088 {
1089 _first_scalar_df[v] = current_SCALAR_dof_index;
1090 current_SCALAR_dof_index += this->variable(v).type().order.get_order();
1091 }
1092
1093 // Allow our GhostingFunctor objects to reinit if necessary
1094 for (const auto & gf : _algebraic_ghosting_functors)
1095 {
1096 libmesh_assert(gf);
1097 gf->dofmap_reinit();
1098 }
1099
1100 for (const auto & gf : _coupling_functors)
1101 {
1102 libmesh_assert(gf);
1103 gf->dofmap_reinit();
1104 }
1105
1106 // Note that in the add_neighbors_to_send_list nodes on processor
1107 // boundaries that are shared by multiple elements are added for
1108 // each element.
1110
1111 // Here we used to clean up that data structure; now System and
1112 // EquationSystems call that for us, after we've added constraint
1113 // dependencies to the send_list too.
1114 // this->sort_send_list ();
1115
1116 return n_dofs;
1117}
std::size_t compute_dof_info(dof_id_type n_local_dofs)
compute the key degree of freedom information given the local number of degrees of freedom on this pr...
std::vector< dof_id_type > _end_df
Last DOF index (plus 1) on processor p.
dof_id_type end_dof() const
std::vector< dof_id_type > _first_df
First DOF index on processor p.
dof_id_type first_dof() const
void reinit(MeshBase &mesh, const std::map< const Node *, std::set< subdomain_id_type > > &constraining_subdomains)
Reinitialize the underlying data structures conformal to the current mesh.
Definition dof_map.C:469
void set_nonlocal_dof_objects(iterator_type objects_begin, iterator_type objects_end, MeshBase &mesh, dofobject_accessor objects)
Helper function for distributing dofs in parallel.
Definition dof_map.C:318
void distribute_local_dofs_var_major(dof_id_type &next_free_dof, MeshBase &mesh, const std::map< const Node *, std::set< subdomain_id_type > > &constraining_subdomains)
Distributes the global degrees of freedom, for dofs on this processor.
Definition dof_map.C:1418
std::map< const Node *, std::set< subdomain_id_type > > calculate_constraining_subdomains()
We may have mesh constraint rows with dependent nodes in one subdomain but dependency nodes in anothe...
Definition dof_map.C:1256
void distribute_local_dofs_node_major(dof_id_type &next_free_dof, MeshBase &mesh, const std::map< const Node *, std::set< subdomain_id_type > > &constraining_subdomains)
Distributes the global degrees of freedom for dofs on this processor.
Definition dof_map.C:1290
DofObject * node_ptr(MeshBase &mesh, dof_id_type i) const
Definition dof_map.C:303
DofObject * elem_ptr(MeshBase &mesh, dof_id_type i) const
Definition dof_map.C:310
void add_neighbors_to_send_list(MeshBase &mesh)
Adds entries to the _send_list vector corresponding to DoFs on elements neighboring the current proce...
Definition dof_map.C:1687
dof_id_type n_SCALAR_dofs() const
Definition dof_map.h:786
void invalidate_dofs(MeshBase &mesh) const
Invalidates all active DofObject dofs for this system.
Definition dof_map.C:856
OrderWrapper order
The approximation order of the element (at 0 p-refinement level).
Definition fe_type.h:203
int get_order() const
Explicitly request the order as an int.
Definition fe_type.h:80
const FEType & type() const
Definition variable.h:144
void libmesh_assert_valid_dof_ids(const MeshBase &mesh, unsigned int sysnum=libMesh::invalid_uint)
A function for verifying that degree of freedom indexing matches across processors.
bool on_command_line(std::string arg)
Definition libmesh.C:934

References libMesh::DofObject::dof_number(), libMesh::libmesh_assert(), libMesh::make_range(), mesh, libMesh::DofObject::n_comp(), libMesh::DofObject::n_vars(), libMesh::on_command_line(), libMesh::DofObject::processor_id(), and libMesh::SCALAR.

Referenced by libMesh::EquationSystems::allgather(), libMesh::PetscDMWrapper::init_petscdm(), libMesh::EquationSystems::reinit_solutions(), SystemsTest::testProjectMatrix1D(), SystemsTest::testProjectMatrix2D(), and SystemsTest::testProjectMatrix3D().

◆ distribute_local_dofs_node_major()

void libMesh::DofMap::distribute_local_dofs_node_major ( dof_id_type next_free_dof,
MeshBase mesh,
const std::map< const Node *, std::set< subdomain_id_type > > &  constraining_subdomains 
)
private

Distributes the global degrees of freedom for dofs on this processor.

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

Uses the provided constraining_subdomains map from calculate_constraining_subdomains() to ensure allocation of all DoFs on constraining nodes.

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

Definition at line 1289 of file dof_map.C.

1294{
1295 const unsigned int sys_num = this->sys_number();
1296 const unsigned int n_var_groups = this->n_variable_groups();
1297
1298 // This is the common case and we want to optimize for it
1299 const bool constraining_subdomains_empty =
1300 constraining_subdomains.empty();
1301
1302 // Our numbering here must be kept consistent with the numbering
1303 // scheme assumed by DofMap::local_variable_indices!
1304
1305 //-------------------------------------------------------------------------
1306 // First count and assign temporary numbers to local dofs
1307 for (auto & elem : mesh.active_local_element_ptr_range())
1308 {
1309 // Only number dofs connected to active
1310 // elements on this processor.
1311 const unsigned int n_nodes = elem->n_nodes();
1312
1313 const subdomain_id_type sbdid = elem->subdomain_id();
1314
1315 // First number the nodal DOFS
1316 for (unsigned int n=0; n<n_nodes; n++)
1317 {
1318 Node & node = elem->node_ref(n);
1319
1320 for (unsigned vg=0; vg<n_var_groups; vg++)
1321 {
1322 const VariableGroup & vg_description(this->variable_group(vg));
1323
1324 if (vg_description.type().family == SCALAR)
1325 continue;
1326
1327 bool active_on_node =
1328 vg_description.active_on_subdomain(sbdid);
1329
1330 // Are we at least active indirectly here?
1331 if (!active_on_node && !constraining_subdomains_empty)
1332 if (auto it = constraining_subdomains.find(&node);
1333 it != constraining_subdomains.end())
1334 for (auto s : it->second)
1335 if (vg_description.active_on_subdomain(s))
1336 {
1337 active_on_node = true;
1338 break;
1339 }
1340
1341 if (active_on_node)
1342 {
1343 // assign dof numbers (all at once) if this is
1344 // our node and if they aren't already there
1345 if ((node.n_comp_group(sys_num,vg) > 0) &&
1346 (node.processor_id() == this->processor_id()) &&
1347 (node.vg_dof_base(sys_num,vg) ==
1349 {
1350 node.set_vg_dof_base(sys_num, vg,
1351 next_free_dof);
1352 next_free_dof += (vg_description.n_variables()*
1353 node.n_comp_group(sys_num,vg));
1354 //node.debug_buffer();
1355 }
1356 }
1357 }
1358 }
1359
1360 // Now number the element DOFS
1361 for (unsigned vg=0; vg<n_var_groups; vg++)
1362 {
1363 const VariableGroup & vg_description(this->variable_group(vg));
1364
1365 if ((vg_description.type().family != SCALAR) &&
1366 (vg_description.active_on_subdomain(elem->subdomain_id())))
1367 if (elem->n_comp_group(sys_num,vg) > 0)
1368 {
1369 libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg),
1371
1372 elem->set_vg_dof_base(sys_num,
1373 vg,
1374 next_free_dof);
1375
1376 next_free_dof += (vg_description.n_variables()*
1377 elem->n_comp_group(sys_num,vg));
1378 }
1379 }
1380 } // done looping over elements
1381
1382
1383 // we may have missed assigning DOFs to nodes that we own
1384 // but to which we have no connected elements matching our
1385 // variable restriction criterion. this will happen, for example,
1386 // if variable V is restricted to subdomain S. We may not own
1387 // any elements which live in S, but we may own nodes which are
1388 // *connected* to elements which do. in this scenario these nodes
1389 // will presently have unnumbered DOFs. we need to take care of
1390 // them here since we own them and no other processor will touch them.
1391 for (auto & node : mesh.local_node_ptr_range())
1392 for (unsigned vg=0; vg<n_var_groups; vg++)
1393 {
1394 const VariableGroup & vg_description(this->variable_group(vg));
1395
1396 if (node->n_comp_group(sys_num,vg))
1397 if (node->vg_dof_base(sys_num,vg) == DofObject::invalid_id)
1398 {
1399 node->set_vg_dof_base (sys_num,
1400 vg,
1401 next_free_dof);
1402
1403 next_free_dof += (vg_description.n_variables()*
1404 node->n_comp(sys_num,vg));
1405 }
1406 }
1407
1408 this->distribute_scalar_dofs(next_free_dof);
1409
1410#ifdef DEBUG
1412#endif // DEBUG
1413}
void distribute_scalar_dofs(dof_id_type &next_free_dof)
Definition dof_map.C:1539
void assert_no_nodes_missed(MeshBase &mesh)
Definition dof_map.C:1563

References libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, mesh, libMesh::DofObject::n_comp_group(), n_nodes, libMesh::VariableGroup::n_variables(), libMesh::DofObject::processor_id(), libMesh::SCALAR, libMesh::DofObject::set_vg_dof_base(), libMesh::Variable::type(), and libMesh::DofObject::vg_dof_base().

◆ distribute_local_dofs_var_major()

void libMesh::DofMap::distribute_local_dofs_var_major ( dof_id_type next_free_dof,
MeshBase mesh,
const std::map< const Node *, std::set< subdomain_id_type > > &  constraining_subdomains 
)
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.

Uses the provided constraining_subdomains map from calculate_constraining_subdomains() to ensure allocation of all DoFs on constraining nodes.

Definition at line 1417 of file dof_map.C.

1422{
1423 const unsigned int sys_num = this->sys_number();
1424 const unsigned int n_var_groups = this->n_variable_groups();
1425
1426 // This is the common case and we want to optimize for it
1427 const bool constraining_subdomains_empty =
1428 constraining_subdomains.empty();
1429
1430 // Our numbering here must be kept consistent with the numbering
1431 // scheme assumed by DofMap::local_variable_indices!
1432
1433 //-------------------------------------------------------------------------
1434 // First count and assign temporary numbers to local dofs
1435 for (unsigned vg=0; vg<n_var_groups; vg++)
1436 {
1437 const VariableGroup & vg_description(this->variable_group(vg));
1438
1439 const unsigned int n_vars_in_group = vg_description.n_variables();
1440
1441 // Skip the SCALAR dofs
1442 if (vg_description.type().family == SCALAR)
1443 continue;
1444
1445 for (auto & elem : mesh.active_local_element_ptr_range())
1446 {
1447 // Only number dofs connected to active elements on this
1448 // processor and only for variables which are active on on
1449 // this element's subdomain or which are active on the
1450 // subdomain of a node constrained by this node.
1451 const bool active_on_elem =
1452 vg_description.active_on_subdomain(elem->subdomain_id());
1453
1454 // If there's no way we're active on this element then we're
1455 // done
1456 if (!active_on_elem && constraining_subdomains_empty)
1457 continue;
1458
1459 const unsigned int n_nodes = elem->n_nodes();
1460
1461 // First number the nodal DOFS
1462 for (unsigned int n=0; n<n_nodes; n++)
1463 {
1464 Node & node = elem->node_ref(n);
1465
1466 bool active_on_node = active_on_elem;
1467 if (!active_on_node)
1468 if (auto it = constraining_subdomains.find(&node);
1469 it != constraining_subdomains.end())
1470 for (auto s : it->second)
1471 if (vg_description.active_on_subdomain(s))
1472 {
1473 active_on_node = true;
1474 break;
1475 }
1476
1477 if (!active_on_node)
1478 continue;
1479
1480 // assign dof numbers (all at once) if this is
1481 // our node and if they aren't already there
1482 if ((node.n_comp_group(sys_num,vg) > 0) &&
1483 (node.processor_id() == this->processor_id()) &&
1484 (node.vg_dof_base(sys_num,vg) ==
1486 {
1487 node.set_vg_dof_base(sys_num, vg, next_free_dof);
1488
1489 next_free_dof += (n_vars_in_group*
1490 node.n_comp_group(sys_num,vg));
1491 }
1492 }
1493
1494 // Now number the element DOFS
1495 if (elem->n_comp_group(sys_num,vg) > 0)
1496 {
1497 libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg),
1499
1500 elem->set_vg_dof_base(sys_num,
1501 vg,
1502 next_free_dof);
1503
1504 next_free_dof += (n_vars_in_group*
1505 elem->n_comp_group(sys_num,vg));
1506 }
1507 } // end loop on elements
1508
1509 // we may have missed assigning DOFs to nodes that we own
1510 // but to which we have no connected elements matching our
1511 // variable restriction criterion. this will happen, for example,
1512 // if variable V is restricted to subdomain S. We may not own
1513 // any elements which live in S, but we may own nodes which are
1514 // *connected* to elements which do. in this scenario these nodes
1515 // will presently have unnumbered DOFs. we need to take care of
1516 // them here since we own them and no other processor will touch them.
1517 for (auto & node : mesh.local_node_ptr_range())
1518 if (node->n_comp_group(sys_num,vg))
1519 if (node->vg_dof_base(sys_num,vg) == DofObject::invalid_id)
1520 {
1521 node->set_vg_dof_base (sys_num,
1522 vg,
1523 next_free_dof);
1524
1525 next_free_dof += (n_vars_in_group*
1526 node->n_comp_group(sys_num,vg));
1527 }
1528 } // end loop on variable groups
1529
1530 this->distribute_scalar_dofs(next_free_dof);
1531
1532#ifdef DEBUG
1534#endif
1535}

References libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, mesh, libMesh::DofObject::n_comp_group(), n_nodes, libMesh::VariableGroup::n_variables(), libMesh::DofObject::processor_id(), libMesh::SCALAR, libMesh::DofObject::set_vg_dof_base(), libMesh::Variable::type(), and libMesh::DofObject::vg_dof_base().

◆ distribute_scalar_dofs()

void libMesh::DofMap::distribute_scalar_dofs ( dof_id_type next_free_dof)
private

Definition at line 1539 of file dof_map.C.

1540{
1541 this->_n_SCALAR_dofs = 0;
1542 for (auto vg : make_range(this->n_variable_groups()))
1543 {
1544 const VariableGroup & vg_description(this->variable_group(vg));
1545
1546 if (vg_description.type().family == SCALAR)
1547 {
1548 this->_n_SCALAR_dofs += (vg_description.n_variables()*
1549 vg_description.type().order.get_order());
1550 continue;
1551 }
1552 }
1553
1554 // Only increment next_free_dof if we're on the processor
1555 // that holds this SCALAR variable
1556 if (this->processor_id() == (this->n_processors()-1))
1557 next_free_dof += _n_SCALAR_dofs;
1558}

References libMesh::FEType::family, libMesh::OrderWrapper::get_order(), libMesh::make_range(), libMesh::VariableGroup::n_variables(), libMesh::FEType::order, libMesh::SCALAR, and libMesh::Variable::type().

◆ dof_indices() [1/6]

void libMesh::DofMap::dof_indices ( const Elem elem,
unsigned int  n,
std::vector< dof_id_type > &  di,
const unsigned int  vn 
) const

Appends to the vector di the global degree of freedom indices for elem.node_ref(n), for one variable vn.

On hanging nodes with both vertex and non-vertex DoFs, only those indices which are directly supported on elem are included.

Definition at line 2466 of file dof_map.C.

2470{
2471 this->_node_dof_indices(elem, n, elem.node_ref(n), di, vn);
2472}
void _node_dof_indices(const Elem &elem, unsigned int n, const DofObject &obj, std::vector< dof_id_type > &di, const unsigned int vn) const
Helper function that implements the element-nodal versions of dof_indices and old_dof_indices.
Definition dof_map.C:2491

References libMesh::Elem::node_ref().

◆ dof_indices() [2/6]

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

Definition at line 2201 of file dof_map.C.

2203{
2204 // We now allow elem==nullptr to request just SCALAR dofs
2205 // libmesh_assert(elem);
2206
2207 // If we are asking for current indices on an element, it ought to
2208 // be an active element (or a temporary side, which also thinks it's
2209 // active)
2210 libmesh_assert(!elem || elem->active());
2211
2212 // dof_indices() is a relatively light-weight function that is
2213 // called millions of times in normal codes. Therefore, it is not a
2214 // good candidate for logging, since the cost of the logging code
2215 // itself is roughly on par with the time required to call
2216 // dof_indices().
2217 // LOG_SCOPE("dof_indices()", "DofMap");
2218
2219 // Clear the DOF indices vector
2220 di.clear();
2221
2222 const unsigned int n_var_groups = this->n_variable_groups();
2223
2224#ifdef DEBUG
2225 // Check that sizes match in DEBUG mode
2226 std::size_t tot_size = 0;
2227#endif
2228
2229 if (elem && elem->type() == TRI3SUBDIVISION)
2230 {
2231 // Subdivision surface FE require the 1-ring around elem
2232 const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
2233
2234 // Ghost subdivision elements have no real dofs
2235 if (!sd_elem->is_ghost())
2236 {
2237 // Determine the nodes contributing to element elem
2238 std::vector<const Node *> elem_nodes;
2239 MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
2240
2241 // Get the dof numbers
2242 for (unsigned int vg=0; vg<n_var_groups; vg++)
2243 {
2244 const VariableGroup & var = this->variable_group(vg);
2245 const unsigned int vars_in_group = var.n_variables();
2246
2247 if (var.type().family == SCALAR &&
2248 var.active_on_subdomain(elem->subdomain_id()))
2249 {
2250 for (unsigned int vig=0; vig != vars_in_group; ++vig)
2251 {
2252#ifdef DEBUG
2253 tot_size += var.type().order;
2254#endif
2255 std::vector<dof_id_type> di_new;
2256 this->SCALAR_dof_indices(di_new,var.number(vig));
2257 di.insert( di.end(), di_new.begin(), di_new.end());
2258 }
2259 }
2260 else
2261 for (unsigned int vig=0; vig != vars_in_group; ++vig)
2262 {
2263 _dof_indices(*elem, elem->p_level(), di, vg, vig,
2264 elem_nodes.data(),
2265 cast_int<unsigned int>(elem_nodes.size()),
2266 var.number(vig)
2267#ifdef DEBUG
2268 , tot_size
2269#endif
2270 );
2271 }
2272 }
2273 }
2274
2275 return;
2276 }
2277
2278 // Get the dof numbers for each variable
2279 const unsigned int n_nodes = elem ? elem->n_nodes() : 0;
2280 for (unsigned int vg=0; vg<n_var_groups; vg++)
2281 {
2282 const VariableGroup & var = this->variable_group(vg);
2283 const unsigned int vars_in_group = var.n_variables();
2284
2285 if (var.type().family == SCALAR &&
2286 (!elem ||
2287 var.active_on_subdomain(elem->subdomain_id())))
2288 {
2289 for (unsigned int vig=0; vig != vars_in_group; ++vig)
2290 {
2291#ifdef DEBUG
2292 tot_size += var.type().order;
2293#endif
2294 std::vector<dof_id_type> di_new;
2295 this->SCALAR_dof_indices(di_new,var.number(vig));
2296 di.insert( di.end(), di_new.begin(), di_new.end());
2297 }
2298 }
2299 else if (elem)
2300 for (unsigned int vig=0; vig != vars_in_group; ++vig)
2301 {
2302 _dof_indices(*elem, elem->p_level(), di, vg, vig,
2303 elem->get_nodes(), n_nodes, var.number(vig)
2304#ifdef DEBUG
2305 , tot_size
2306#endif
2307 );
2308 }
2309 }
2310
2311#ifdef DEBUG
2312 libmesh_assert_equal_to (tot_size, di.size());
2313#endif
2314}
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Fills the vector di with the global degree of freedom indices corresponding to the SCALAR variable vn...
Definition dof_map.C:2605
void find_one_ring(const Tri3Subdivision *elem, std::vector< const Node * > &nodes)
Determines the 1-ring of element elem, and writes it to the nodes vector.

References libMesh::Elem::active(), libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::Elem::get_nodes(), libMesh::Tri3Subdivision::is_ghost(), libMesh::libmesh_assert(), libMesh::Elem::n_nodes(), n_nodes, libMesh::VariableGroup::n_variables(), libMesh::VariableGroup::number(), libMesh::FEType::order, libMesh::Elem::p_level(), libMesh::SCALAR, libMesh::Elem::subdomain_id(), libMesh::TRI3SUBDIVISION, libMesh::Variable::type(), and libMesh::Elem::type().

Referenced by libMesh::ExactSolution::_compute_error(), libMesh::UniformRefinementEstimator::_estimate_error(), libMesh::MeshFunction::_gradient_on_elem(), add_constraints_to_send_list(), libMesh::HPCoarsenTest::add_projection(), LinearElasticity::assemble(), assemble(), assemble(), AssembleOptimization::assemble_A_and_F(), libMesh::ClawSystem::assemble_advection_matrices(), libMesh::ClawSystem::assemble_avg_coupling_matrices(), libMesh::ClawSystem::assemble_boundary_condition_matrices(), assemble_cd(), assemble_cd(), assemble_elasticity(), libMesh::ClawSystem::assemble_jump_coupling_matrix(), assemble_mass(), libMesh::ClawSystem::assemble_mass_matrix(), assemble_matrices(), assemble_poisson(), assemble_SchroedingerEquation(), assemble_shell(), assemble_shell(), assemble_stokes(), assemble_wave(), Biharmonic::JR::bounds(), libMesh::EquationSystems::build_parallel_solution_vector(), libMesh::FEGenericBase< OutputType >::coarsened_dof_values(), compute_enriched_soln(), compute_jacobian(), libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), libMesh::FEGenericBase< OutputType >::compute_proj_constraints(), compute_residual(), LinearElasticity::compute_stresses(), LargeDeformationElasticity::compute_stresses(), LinearElasticityWithContact::compute_stresses(), compute_stresses(), libMesh::MeshFunction::discontinuous_value(), DMCreateDomainDecomposition_libMesh(), DMCreateFieldDecomposition_libMesh(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::DTKEvaluator::evaluate(), libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::find_dofs_to_send(), libMesh::MeshFunction::hessian(), libMesh::InfFE< Dim, T_radial, T_map >::inf_compute_constraints(), libMesh::SystemSubsetBySubdomain::init(), LargeDeformationElasticity::jacobian(), libMesh::HDGProblem::jacobian(), libMesh::System::local_dof_indices(), max_constraint_error(), LinearElasticityWithContact::move_mesh(), libMesh::DGFEMContext::neighbor_side_fe_reinit(), libMesh::PatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::SmoothnessEstimator::EstimateSmoothness::operator()(), libMesh::WeightedPatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::BoundaryProjectSolution::operator()(), libMesh::MeshFunction::operator()(), libMesh::ErrorVector::plot_error(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), libMesh::FEMContext::pre_fe_reinit(), process_mesh_constraint_rows(), libMesh::StaticCondensationDofMap::reinit(), LargeDeformationElasticity::residual(), libMesh::HDGProblem::residual(), LinearElasticityWithContact::residual_and_jacobian(), Biharmonic::JR::residual_and_jacobian(), scatter_constraints(), libMesh::HPCoarsenTest::select_refinement(), libMesh::PetscDMWrapper::set_point_range_in_section(), FETestBase< order, family, elem_type, build_nx, CaseName >::setUp(), SolidSystem::side_time_derivative(), libMesh::SparsityPattern::Build::sorted_connected_dofs(), ProjectSolutionTest::test_partial_project_solution(), MixedDimensionMeshTest::testDofOrdering(), MixedDimensionRefinedMeshTest::testDofOrdering(), MixedDimensionNonUniformRefinement::testDofOrdering(), MixedDimensionNonUniformRefinementTriangle::testDofOrdering(), MixedDimensionNonUniformRefinement3D::testDofOrdering(), MeshInputTest::testExodusWriteElementDataFromDiscontinuousNodalData(), InfFERadialTest::testRefinement(), BoundaryInfoTest::testShellFaceConstraints(), libMesh::BoundaryVolumeSolutionTransfer::transfer_boundary_volume(), NonManifoldGhostingFunctorTest::verify_send_list_entries_helper(), libMesh::Nemesis_IO_Helper::write_nodal_solution(), libMesh::EnsightIO::write_scalar_ascii(), and libMesh::EnsightIO::write_vector_ascii().

◆ dof_indices() [3/6]

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

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

Implements libMesh::DofMapBase.

Definition at line 2317 of file dof_map.C.

2321{
2323 elem,
2324 di,
2325 vn,
2326 [](const Elem &,
2327 std::vector<dof_id_type> & dof_indices,
2328 const std::vector<dof_id_type> & scalar_dof_indices) {
2329 dof_indices.insert(dof_indices.end(), scalar_dof_indices.begin(), scalar_dof_indices.end());
2330 },
2331 [](const Elem &,
2332 unsigned int,
2333 unsigned int,
2334 std::vector<dof_id_type> & dof_indices,
2335 const dof_id_type dof) { dof_indices.push_back(dof); },
2336 p_level);
2337}

References int.

◆ dof_indices() [4/6]

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

Retrieves degree of freedom indices for a given elem and then performs actions for these indices defined by the user-provided functors scalar_dofs_functor and field_dofs_functor.

This API is useful when a user wants to do more than simply fill a degree of freedom container

Parameters
elemThe element to get degrees of freedom for
diA container for degrees of freedom. It is up to the provided functors how this gets filled
vnThe variable number to retrieve degrees of freedom for
scalar_dofs_functorThe functor that acts on scalar degrees of freedom. This functor has the interface: void scalar_dofs_functor(const Elem & elem, std::vector<dof_id_type> & di, const std::vector<dof_id_type> & scalar_dof_indices) where di is the degree of freedom container described above and scalar_dof_indices are the scalar dof indices available to elem
field_dofs_functorThe functor that acts on "field" (e.g. non-scalar, non-global) degrees of freedom. This functor has the interface: void field_dofs_functor(const Elem & elem, const unsigned int node_num, const unsigned int var_num, std::vector<dof_id_type> & di, const dof_id_type field_dof) where field_dof represents a field degree of freedom to act on and is associated with node_num and var_num. If the degree of freedom is elemental than node_num will be invalid_uint. di is again the degree of freedom container provided above

Definition at line 2777 of file dof_map.h.

2783{
2784 // We now allow elem==nullptr to request just SCALAR dofs
2785 // libmesh_assert(elem);
2786
2787 // dof_indices() is a relatively light-weight function that is
2788 // called millions of times in normal codes. Therefore, it is not a
2789 // good candidate for logging, since the cost of the logging code
2790 // itself is roughly on par with the time required to call
2791 // dof_indices().
2792 // LOG_SCOPE("dof_indices()", "DofMap");
2793
2794 // Clear the DOF indices vector
2795 di.clear();
2796
2797 // Use the default p refinement level?
2798 if (p_level == -12345)
2799 p_level = elem ? elem->p_level() : 0;
2800
2801 const unsigned int vg = this->_variable_group_numbers[vn];
2802 const VariableGroup & var = this->variable_group(vg);
2803 const unsigned int vig = vn - var.number();
2804
2805#ifdef DEBUG
2806 // Check that sizes match in DEBUG mode
2807 std::size_t tot_size = 0;
2808#endif
2809
2810 if (elem && elem->type() == TRI3SUBDIVISION)
2811 {
2812 // Subdivision surface FE require the 1-ring around elem
2813 const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
2814
2815 // Ghost subdivision elements have no real dofs
2816 if (!sd_elem->is_ghost())
2817 {
2818 // Determine the nodes contributing to element elem
2819 std::vector<const Node *> elem_nodes;
2820 MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
2821
2822 _dof_indices(*elem, p_level, di, vg, vig, elem_nodes.data(),
2823 cast_int<unsigned int>(elem_nodes.size()), vn,
2824#ifdef DEBUG
2825 tot_size,
2826#endif
2827 field_dofs_functor);
2828 }
2829
2830 return;
2831 }
2832
2833 // Get the dof numbers
2834 if (var.type().family == SCALAR &&
2835 (!elem ||
2836 var.active_on_subdomain(elem->subdomain_id())))
2837 {
2838#ifdef DEBUG
2839 tot_size += var.type().order;
2840#endif
2841 std::vector<dof_id_type> di_new;
2842 this->SCALAR_dof_indices(di_new,vn);
2843 scalar_dofs_functor(*elem, di, di_new);
2844 }
2845 else if (elem)
2846 _dof_indices(*elem, p_level, di, vg, vig, elem->get_nodes(),
2847 elem->n_nodes(), vn,
2848#ifdef DEBUG
2849 tot_size,
2850#endif
2851 field_dofs_functor);
2852
2853#ifdef DEBUG
2854 libmesh_assert_equal_to (tot_size, di.size());
2855#endif
2856}

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

◆ dof_indices() [5/6]

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

2364{
2365 // We allow node==nullptr to request just SCALAR dofs
2366 // libmesh_assert(elem);
2367
2368 // dof_indices() is a relatively light-weight function that is
2369 // called millions of times in normal codes. Therefore, it is not a
2370 // good candidate for logging, since the cost of the logging code
2371 // itself is roughly on par with the time required to call
2372 // dof_indices().
2373 // LOG_SCOPE("dof_indices(Node)", "DofMap");
2374
2375 // Clear the DOF indices vector
2376 di.clear();
2377
2378 const unsigned int n_var_groups = this->n_variable_groups();
2379 const unsigned int sys_num = this->sys_number();
2380
2381 // Get the dof numbers
2382 for (unsigned int vg=0; vg<n_var_groups; vg++)
2383 {
2384 const VariableGroup & var = this->variable_group(vg);
2385 const unsigned int vars_in_group = var.n_variables();
2386
2387 if (var.type().family == SCALAR)
2388 {
2389 for (unsigned int vig=0; vig != vars_in_group; ++vig)
2390 {
2391 std::vector<dof_id_type> di_new;
2392 this->SCALAR_dof_indices(di_new,var.number(vig));
2393 di.insert( di.end(), di_new.begin(), di_new.end());
2394 }
2395 }
2396 else
2397 {
2398 const int n_comp = node->n_comp_group(sys_num,vg);
2399 for (unsigned int vig=0; vig != vars_in_group; ++vig)
2400 {
2401 for (int i=0; i != n_comp; ++i)
2402 {
2403 const dof_id_type d =
2404 node->dof_number(sys_num, vg, vig, i, n_comp);
2405 libmesh_assert_not_equal_to
2407 di.push_back(d);
2408 }
2409 }
2410 }
2411 }
2412}

References libMesh::DofObject::dof_number(), libMesh::FEType::family, libMesh::DofObject::n_comp_group(), libMesh::VariableGroup::n_variables(), libMesh::VariableGroup::number(), libMesh::SCALAR, and libMesh::Variable::type().

◆ dof_indices() [6/6]

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

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

Implements libMesh::DofMapBase.

Definition at line 2415 of file dof_map.C.

2418{
2419 if (vn == libMesh::invalid_uint)
2420 {
2421 this->dof_indices(node, di);
2422 return;
2423 }
2424
2425 // We allow node==nullptr to request just SCALAR dofs
2426 // libmesh_assert(elem);
2427
2428 // dof_indices() is a relatively light-weight function that is
2429 // called millions of times in normal codes. Therefore, it is not a
2430 // good candidate for logging, since the cost of the logging code
2431 // itself is roughly on par with the time required to call
2432 // dof_indices().
2433 // LOG_SCOPE("dof_indices(Node)", "DofMap");
2434
2435 // Clear the DOF indices vector
2436 di.clear();
2437
2438 const unsigned int sys_num = this->sys_number();
2439
2440 // Get the dof numbers
2441 const unsigned int vg = this->_variable_group_numbers[vn];
2442 const VariableGroup & var = this->variable_group(vg);
2443
2444 if (var.type().family == SCALAR)
2445 {
2446 std::vector<dof_id_type> di_new;
2447 this->SCALAR_dof_indices(di_new,vn);
2448 di.insert( di.end(), di_new.begin(), di_new.end());
2449 }
2450 else
2451 {
2452 const unsigned int vig = vn - var.number();
2453 const int n_comp = node->n_comp_group(sys_num,vg);
2454 for (int i=0; i != n_comp; ++i)
2455 {
2456 const dof_id_type d =
2457 node->dof_number(sys_num, vg, vig, i, n_comp);
2458 libmesh_assert_not_equal_to
2460 di.push_back(d);
2461 }
2462 }
2463}

References libMesh::DofObject::dof_number(), libMesh::FEType::family, libMesh::invalid_uint, libMesh::DofObject::n_comp_group(), libMesh::VariableGroup::number(), libMesh::SCALAR, and libMesh::Variable::type().

◆ dof_owner()

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

Definition at line 815 of file dof_map.h.

816 { std::vector<dof_id_type>::const_iterator ub =
817 std::upper_bound(_end_df.begin(), _end_df.end(), dof);
818 libmesh_assert (ub != _end_df.end());
819 return cast_int<processor_id_type>(ub - _end_df.begin());
820 }

References libMesh::DofMapBase::_end_df, and libMesh::libmesh_assert().

Referenced by libMesh::StaticCondensationDofMap::add_uncondensed_dof(), libMesh::PetscDMWrapper::build_sf(), and DofMapTest::testDofOwner().

◆ elem_ptr()

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

Definition at line 310 of file dof_map.C.

311{
312 return mesh.elem_ptr(i);
313}

References mesh.

◆ enable_print_counter_info()

void libMesh::ReferenceCounter::enable_print_counter_info ( )
staticinherited

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

Enabled by default.

Definition at line 94 of file reference_counter.C.

95{
97 return;
98}

References libMesh::ReferenceCounter::_enable_print_counter.

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

◆ end_dof() [1/2]

dof_id_type libMesh::DofMapBase::end_dof ( ) const
inlineinherited

◆ end_dof() [2/2]

dof_id_type libMesh::DofMapBase::end_dof ( const processor_id_type  proc) const
inlineinherited

◆ end_old_dof() [1/2]

dof_id_type libMesh::DofMapBase::end_old_dof ( ) const
inlineinherited

Definition at line 140 of file dof_map_base.h.

140{ return this->end_old_dof(this->processor_id()); }
dof_id_type end_old_dof() const

References libMesh::DofMapBase::end_old_dof(), and libMesh::ParallelObject::processor_id().

Referenced by libMesh::DofMapBase::end_old_dof().

◆ end_old_dof() [2/2]

dof_id_type libMesh::DofMapBase::end_old_dof ( const processor_id_type  proc) const
inlineinherited
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 210 of file dof_map_base.h.

211{
212 libmesh_assert_less(proc, _end_old_df.size());
213 return _end_old_df[proc];
214}

References libMesh::DofMapBase::_end_old_df.

Referenced by libMesh::PetscDMWrapper::init_petscdm(), libMesh::BuildProjectionList::operator()(), SystemsTest::testProjectMatrix1D(), SystemsTest::testProjectMatrix2D(), and SystemsTest::testProjectMatrix3D().

◆ enforce_adjoint_constraints_exactly()

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

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

2523 {}

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

◆ enforce_constraints_exactly()

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

Constrains the numeric vector v, which represents a solution defined on the mesh.

This may need to be used after a linear solve, if your linear solver's solutions do not satisfy your DoF constraints to a tight enough tolerance.

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

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

Definition at line 2518 of file dof_map.h.

2520 {}

Referenced by libMesh::__libmesh_petsc_diff_solver_jacobian(), libMesh::__libmesh_petsc_diff_solver_residual(), libMesh::Problem_Interface::computeJacobian(), libMesh::Problem_Interface::computePreconditioner(), DMlibMeshFunction(), DMlibMeshJacobian(), libMesh::CondensedEigenSystem::get_eigenpair(), main(), libMesh::ImplicitSystem::sensitivity_solve(), libMesh::NewtonSolver::solve(), libMesh::PetscDiffSolver::solve(), libMesh::RBConstruction::solve_for_matrix_and_rhs(), libMesh::ImplicitSystem::weighted_sensitivity_adjoint_solve(), and libMesh::ImplicitSystem::weighted_sensitivity_solve().

◆ enforce_constraints_on_jacobian()

void libMesh::DofMap::enforce_constraints_on_jacobian ( const NonlinearImplicitSystem system,
SparseMatrix< Number > *  jac 
) const
inline

Definition at line 2532 of file dof_map.h.

2534 {}

◆ enforce_constraints_on_residual()

void libMesh::DofMap::enforce_constraints_on_residual ( const NonlinearImplicitSystem system,
NumericVector< Number > *  rhs,
NumericVector< Number > const *  solution,
bool  homogeneous = true 
) const
inline

Definition at line 2526 of file dof_map.h.

2530 {}

Referenced by libMesh::PetscNonlinearSolver< Number >::force_new_preconditioner().

◆ extract_local_vector()

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

Builds the local element vector Ue from the global vector Ug, accounting for any constrained degrees of freedom.

For an element without constrained degrees of freedom this is the trivial mapping \( Ue[i] = Ug[dof_indices[i]] \)

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

Definition at line 2119 of file dof_map.C.

2122{
2123 const unsigned int n_original_dofs = dof_indices_in.size();
2124
2125#ifdef LIBMESH_ENABLE_AMR
2126
2127 // Trivial mapping
2128 libmesh_assert_equal_to (dof_indices_in.size(), Ue.size());
2129 bool has_constrained_dofs = false;
2130
2131 for (unsigned int il=0; il != n_original_dofs; ++il)
2132 {
2133 const dof_id_type ig = dof_indices_in[il];
2134
2135 if (this->is_constrained_dof (ig)) has_constrained_dofs = true;
2136
2137 libmesh_assert_less (ig, Ug.size());
2138
2139 Ue.el(il) = Ug(ig);
2140 }
2141
2142 // If the element has any constrained DOFs then we need
2143 // to account for them in the mapping. This will handle
2144 // the case that the input vector is not constrained.
2145 if (has_constrained_dofs)
2146 {
2147 // Copy the input DOF indices.
2148 std::vector<dof_id_type> constrained_dof_indices(dof_indices_in);
2149
2150 DenseMatrix<Number> C;
2151 DenseVector<Number> H;
2152
2153 this->build_constraint_matrix_and_vector (C, H, constrained_dof_indices);
2154
2155 libmesh_assert_equal_to (dof_indices_in.size(), C.m());
2156 libmesh_assert_equal_to (constrained_dof_indices.size(), C.n());
2157
2158 // zero-out Ue
2159 Ue.zero();
2160
2161 // compute Ue = C Ug, with proper mapping.
2162 for (unsigned int i=0; i != n_original_dofs; i++)
2163 {
2164 Ue.el(i) = H(i);
2165
2166 const unsigned int n_constrained =
2167 cast_int<unsigned int>(constrained_dof_indices.size());
2168 for (unsigned int j=0; j<n_constrained; j++)
2169 {
2170 const dof_id_type jg = constrained_dof_indices[j];
2171
2172 // If Ug is a serial or ghosted vector, then this assert is
2173 // overzealous. If Ug is a parallel vector, then this assert
2174 // is redundant.
2175 // libmesh_assert ((jg >= Ug.first_local_index()) &&
2176 // (jg < Ug.last_local_index()));
2177
2178 Ue.el(i) += C(i,j)*Ug(jg);
2179 }
2180 }
2181 }
2182
2183#else
2184
2185 // Trivial mapping
2186
2187 libmesh_assert_equal_to (n_original_dofs, Ue.size());
2188
2189 for (unsigned int il=0; il<n_original_dofs; il++)
2190 {
2191 const dof_id_type ig = dof_indices_in[il];
2192
2193 libmesh_assert ((ig >= Ug.first_local_index()) && (ig < Ug.last_local_index()));
2194
2195 Ue.el(il) = Ug(ig);
2196 }
2197
2198#endif
2199}
virtual void zero()=0
Set every element in the vector to 0.
virtual T el(const unsigned int i) const =0
virtual unsigned int size() const =0
virtual numeric_index_type last_local_index() const =0
virtual numeric_index_type size() const =0
virtual numeric_index_type first_local_index() const =0

References libMesh::DenseVectorBase< T >::el(), libMesh::NumericVector< T >::first_local_index(), 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().

◆ find_connected_dof_objects()

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

Finds all the DofObjects associated with the set in objs.

This will account for off-element couplings via hanging nodes.

◆ find_connected_dofs()

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

Finds all the DOFS associated with the element DOFs elem_dofs.

This will account for off-element couplings via hanging nodes.

Definition at line 2915 of file dof_map.C.

2916{
2917 typedef std::set<dof_id_type> RCSet;
2918
2919 // First insert the DOFS we already depend on into the set.
2920 RCSet dof_set (elem_dofs.begin(), elem_dofs.end());
2921
2922 bool done = true;
2923
2924 // Next insert any dofs those might be constrained in terms
2925 // of. Note that in this case we may not be done: Those may
2926 // in turn depend on others. So, we need to repeat this process
2927 // in that case until the system depends only on unconstrained
2928 // degrees of freedom.
2929 for (const auto & dof : elem_dofs)
2930 if (this->is_constrained_dof(dof))
2931 {
2932 // If the DOF is constrained
2933 DofConstraints::const_iterator
2934 pos = _dof_constraints.find(dof);
2935
2936 libmesh_assert (pos != _dof_constraints.end());
2937
2938 const DofConstraintRow & constraint_row = pos->second;
2939
2940 // adaptive p refinement currently gives us lots of empty constraint
2941 // rows - we should optimize those DoFs away in the future. [RHS]
2942 //libmesh_assert (!constraint_row.empty());
2943
2944 // Add the DOFs this dof is constrained in terms of.
2945 // note that these dofs might also be constrained, so
2946 // we will need to call this function recursively.
2947 for (const auto & pr : constraint_row)
2948 if (!dof_set.count (pr.first))
2949 {
2950 dof_set.insert (pr.first);
2951 done = false;
2952 }
2953 }
2954
2955
2956 // If not done then we need to do more work
2957 // (obviously :-) )!
2958 if (!done)
2959 {
2960 // Fill the vector with the contents of the set
2961 elem_dofs.clear();
2962 elem_dofs.insert (elem_dofs.end(),
2963 dof_set.begin(), dof_set.end());
2964
2965
2966 // May need to do this recursively. It is possible
2967 // that we just replaced a constrained DOF with another
2968 // constrained DOF.
2969 this->find_connected_dofs (elem_dofs);
2970
2971 } // end if (!done)
2972}
void find_connected_dofs(std::vector< dof_id_type > &elem_dofs) const
Finds all the DOFS associated with the element DOFs elem_dofs.
Definition dof_map.C:2915

References libMesh::libmesh_assert().

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

◆ first_dof() [1/2]

dof_id_type libMesh::DofMapBase::first_dof ( ) const
inlineinherited

◆ first_dof() [2/2]

dof_id_type libMesh::DofMapBase::first_dof ( const processor_id_type  proc) const
inlineinherited

◆ first_old_dof() [1/2]

dof_id_type libMesh::DofMapBase::first_old_dof ( ) const
inlineinherited

Definition at line 130 of file dof_map_base.h.

130{ return this->first_old_dof(this->processor_id()); }
dof_id_type first_old_dof() const

References libMesh::DofMapBase::first_old_dof(), and libMesh::ParallelObject::processor_id().

Referenced by libMesh::DofMapBase::first_old_dof().

◆ first_old_dof() [2/2]

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

Definition at line 204 of file dof_map_base.h.

205{
206 libmesh_assert_less(proc, _first_old_df.size());
207 return _first_old_df[proc];
208}

References libMesh::DofMapBase::_first_old_df.

Referenced by libMesh::PetscDMWrapper::init_petscdm(), libMesh::BuildProjectionList::operator()(), SystemsTest::testProjectMatrix1D(), SystemsTest::testProjectMatrix2D(), and SystemsTest::testProjectMatrix3D().

◆ full_sparsity_pattern_needed()

void libMesh::DofMap::full_sparsity_pattern_needed ( )
inline

Sets need_full_sparsity_pattern to true regardless of the requirements by matrices.

Definition at line 2554 of file dof_map.h.

2555{
2557}

References need_full_sparsity_pattern.

◆ gather_constraints()

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

Helper function for querying about constraint equations on other processors.

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

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

Definition at line 5019 of file dof_map_constraints.C.

5022{
5023 typedef std::set<dof_id_type> DoF_RCSet;
5024
5025 // If we have heterogeneous adjoint constraints we need to
5026 // communicate those too.
5027 const unsigned int max_qoi_num =
5029 0 : _adjoint_constraint_values.rbegin()->first+1;
5030
5031 // We have to keep recursing while the unexpanded set is
5032 // nonempty on *any* processor
5033 bool unexpanded_set_nonempty = !unexpanded_dofs.empty();
5034 this->comm().max(unexpanded_set_nonempty);
5035
5036 while (unexpanded_set_nonempty)
5037 {
5038 // Let's make sure we don't lose sync in this loop.
5039 parallel_object_only();
5040
5041 // Request sets
5042 DoF_RCSet dof_request_set;
5043
5044 // Request sets to send to each processor
5045 std::map<processor_id_type, std::vector<dof_id_type>>
5046 requested_dof_ids;
5047
5048 // And the sizes of each
5049 std::map<processor_id_type, dof_id_type>
5050 dof_ids_on_proc;
5051
5052 // Fill (and thereby sort and uniq!) the main request sets
5053 for (const auto & unexpanded_dof : unexpanded_dofs)
5054 {
5055 // If we were asked for a DoF and we don't already have a
5056 // constraint for it, then we need to check for one.
5057 if (auto pos = _dof_constraints.find(unexpanded_dof);
5058 pos == _dof_constraints.end())
5059 {
5060 if (!this->local_index(unexpanded_dof) &&
5061 !_dof_constraints.count(unexpanded_dof) )
5062 dof_request_set.insert(unexpanded_dof);
5063 }
5064 // If we were asked for a DoF and we already have a
5065 // constraint for it, then we need to check if the
5066 // constraint is recursive.
5067 else
5068 {
5069 const DofConstraintRow & row = pos->second;
5070 for (const auto & j : row)
5071 {
5072 const dof_id_type constraining_dof = j.first;
5073
5074 // If it's non-local and we haven't already got a
5075 // constraint for it, we might need to ask for one
5076 if (!this->local_index(constraining_dof) &&
5077 !_dof_constraints.count(constraining_dof))
5078 dof_request_set.insert(constraining_dof);
5079 }
5080 }
5081 }
5082
5083 // Clear the unexpanded constraint set; we're about to expand it
5084 unexpanded_dofs.clear();
5085
5086 // Count requests by processor
5087 processor_id_type proc_id = 0;
5088 for (const auto & i : dof_request_set)
5089 {
5090 while (i >= _end_df[proc_id])
5091 proc_id++;
5092 dof_ids_on_proc[proc_id]++;
5093 }
5094
5095 for (auto & pair : dof_ids_on_proc)
5096 {
5097 requested_dof_ids[pair.first].reserve(pair.second);
5098 }
5099
5100 // Prepare each processor's request set
5101 proc_id = 0;
5102 for (const auto & i : dof_request_set)
5103 {
5104 while (i >= _end_df[proc_id])
5105 proc_id++;
5106 requested_dof_ids[proc_id].push_back(i);
5107 }
5108
5109 typedef std::vector<std::pair<dof_id_type, Real>> row_datum;
5110
5111 typedef std::vector<Number> rhss_datum;
5112
5113 auto row_gather_functor =
5114 [this]
5116 const std::vector<dof_id_type> & ids,
5117 std::vector<row_datum> & data)
5118 {
5119 // Fill those requests
5120 const std::size_t query_size = ids.size();
5121
5122 data.resize(query_size);
5123 for (std::size_t i=0; i != query_size; ++i)
5124 {
5125 dof_id_type constrained = ids[i];
5126 if (_dof_constraints.count(constrained))
5127 {
5128 DofConstraintRow & row = _dof_constraints[constrained];
5129 std::size_t row_size = row.size();
5130 data[i].reserve(row_size);
5131 for (const auto & j : row)
5132 {
5133 data[i].push_back(j);
5134
5135 // We should never have an invalid constraining
5136 // dof id
5138
5139 // We should never have a 0 constraint
5140 // coefficient; that's implicit via sparse
5141 // constraint storage
5142 //
5143 // But we can't easily control how users add
5144 // constraints, so we can't safely assert that
5145 // we're being efficient here.
5146 //
5147 // libmesh_assert(j.second);
5148 }
5149 }
5150 else
5151 {
5152 // We have to distinguish "constraint with no
5153 // constraining dofs" (e.g. due to Dirichlet
5154 // constraint equations) from "no constraint".
5155 // We'll use invalid_id for the latter.
5156 data[i].emplace_back(DofObject::invalid_id, Real(0));
5157 }
5158 }
5159 };
5160
5161 auto rhss_gather_functor =
5162 [this,
5163 max_qoi_num]
5165 const std::vector<dof_id_type> & ids,
5166 std::vector<rhss_datum> & data)
5167 {
5168 // Fill those requests
5169 const std::size_t query_size = ids.size();
5170
5171 data.resize(query_size);
5172 for (std::size_t i=0; i != query_size; ++i)
5173 {
5174 dof_id_type constrained = ids[i];
5175 data[i].clear();
5176 if (_dof_constraints.count(constrained))
5177 {
5178 DofConstraintValueMap::const_iterator rhsit =
5179 _primal_constraint_values.find(constrained);
5180 data[i].push_back
5181 ((rhsit == _primal_constraint_values.end()) ?
5182 0 : rhsit->second);
5183
5184 for (unsigned int q = 0; q != max_qoi_num; ++q)
5185 {
5186 AdjointDofConstraintValues::const_iterator adjoint_map_it =
5188
5189 if (adjoint_map_it == _adjoint_constraint_values.end())
5190 {
5191 data[i].push_back(0);
5192 continue;
5193 }
5194
5195 const DofConstraintValueMap & constraint_map =
5196 adjoint_map_it->second;
5197
5198 DofConstraintValueMap::const_iterator adj_rhsit =
5199 constraint_map.find(constrained);
5200 data[i].push_back
5201 ((adj_rhsit == constraint_map.end()) ?
5202 0 : adj_rhsit->second);
5203 }
5204 }
5205 }
5206 };
5207
5208 auto row_action_functor =
5209 [this,
5210 & unexpanded_dofs]
5212 const std::vector<dof_id_type> & ids,
5213 const std::vector<row_datum> & data)
5214 {
5215 // Add any new constraint rows we've found
5216 const std::size_t query_size = ids.size();
5217
5218 for (std::size_t i=0; i != query_size; ++i)
5219 {
5220 const dof_id_type constrained = ids[i];
5221
5222 // An empty row is an constraint with an empty row; for
5223 // no constraint we use a "no row" placeholder
5224 if (data[i].empty())
5225 {
5226 DofConstraintRow & row = _dof_constraints[constrained];
5227 row.clear();
5228 }
5229 else if (data[i][0].first != DofObject::invalid_id)
5230 {
5231 DofConstraintRow & row = _dof_constraints[constrained];
5232 row.clear();
5233 for (auto & pair : data[i])
5234 {
5235 libmesh_assert_less(pair.first, this->n_dofs());
5236 row[pair.first] = pair.second;
5237 }
5238
5239 // And prepare to check for more recursive constraints
5240 unexpanded_dofs.insert(constrained);
5241 }
5242 }
5243 };
5244
5245 auto rhss_action_functor =
5246 [this,
5247 max_qoi_num]
5249 const std::vector<dof_id_type> & ids,
5250 const std::vector<rhss_datum> & data)
5251 {
5252 // Add rhs data for any new constraint rows we've found
5253 const std::size_t query_size = ids.size();
5254
5255 for (std::size_t i=0; i != query_size; ++i)
5256 {
5257 if (!data[i].empty())
5258 {
5259 dof_id_type constrained = ids[i];
5260 if (data[i][0] != Number(0))
5261 _primal_constraint_values[constrained] = data[i][0];
5262 else
5263 _primal_constraint_values.erase(constrained);
5264
5265 for (unsigned int q = 0; q != max_qoi_num; ++q)
5266 {
5267 AdjointDofConstraintValues::iterator adjoint_map_it =
5269
5270 if ((adjoint_map_it == _adjoint_constraint_values.end()) &&
5271 data[i][q+1] == Number(0))
5272 continue;
5273
5274 if (adjoint_map_it == _adjoint_constraint_values.end())
5275 adjoint_map_it = _adjoint_constraint_values.emplace
5276 (q, DofConstraintValueMap()).first;
5277
5278 DofConstraintValueMap & constraint_map =
5279 adjoint_map_it->second;
5280
5281 if (data[i][q+1] != Number(0))
5282 constraint_map[constrained] =
5283 data[i][q+1];
5284 else
5285 constraint_map.erase(constrained);
5286 }
5287 }
5288 }
5289
5290 };
5291
5292 // Now request constraint rows from other processors
5293 row_datum * row_ex = nullptr;
5295 (this->comm(), requested_dof_ids, row_gather_functor,
5296 row_action_functor, row_ex);
5297
5298 // And request constraint right hand sides from other procesors
5299 rhss_datum * rhs_ex = nullptr;
5301 (this->comm(), requested_dof_ids, rhss_gather_functor,
5302 rhss_action_functor, rhs_ex);
5303
5304 // We have to keep recursing while the unexpanded set is
5305 // nonempty on *any* processor
5306 unexpanded_set_nonempty = !unexpanded_dofs.empty();
5307 this->comm().max(unexpanded_set_nonempty);
5308 }
5309}

References _adjoint_constraint_values, _dof_constraints, libMesh::DofMapBase::_end_df, _primal_constraint_values, libMesh::ParallelObject::comm(), libMesh::DofObject::invalid_id, libMesh::libmesh_assert(), local_index(), libMesh::Parallel::Communicator::max(), TIMPI::pull_parallel_vector_data(), and libMesh::Real.

Referenced by allgather_recursive_constraints(), and scatter_constraints().

◆ get_adjoint_dirichlet_boundaries() [1/2]

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

Definition at line 5474 of file dof_map_constraints.C.

5475{
5476 unsigned int old_size = cast_int<unsigned int>
5478 for (unsigned int i = old_size; i <= q; ++i)
5479 _adjoint_dirichlet_boundaries.push_back(std::make_unique<DirichletBoundaries>());
5480
5481 return _adjoint_dirichlet_boundaries[q].get();
5482}

References _adjoint_dirichlet_boundaries.

◆ get_adjoint_dirichlet_boundaries() [2/2]

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

Definition at line 5466 of file dof_map_constraints.C.

5467{
5468 libmesh_assert_greater(_adjoint_dirichlet_boundaries.size(),q);
5469 return _adjoint_dirichlet_boundaries[q].get();
5470}

References _adjoint_dirichlet_boundaries.

◆ get_all_variable_numbers()

void libMesh::DofMap::get_all_variable_numbers ( std::vector< unsigned int > &  all_variable_numbers) const

Fills all_variable_numbers with all the variable numbers for the variables that have been added to this system.

Definition at line 3389 of file dof_map.C.

3390{
3391 all_variable_numbers.resize(n_vars());
3392
3393 unsigned int count = 0;
3394 for (auto vn : _variable_numbers)
3395 all_variable_numbers[count++] = vn.second;
3396}

References n_vars.

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

◆ get_dirichlet_boundaries() [1/2]

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

Definition at line 1641 of file dof_map.h.

1642 {
1643 return _dirichlet_boundaries.get();
1644 }

References _dirichlet_boundaries.

◆ get_dirichlet_boundaries() [2/2]

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

Definition at line 1636 of file dof_map.h.

1637 {
1638 return _dirichlet_boundaries.get();
1639 }

References _dirichlet_boundaries.

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

◆ get_dof_constraints()

const DofConstraints & libMesh::DofMap::get_dof_constraints ( ) const
inline

Provide a const accessor to the DofConstraints map.

This allows the user to quickly search the data structure rather than just iterating over it.

Definition at line 1177 of file dof_map.h.

1177{ return _dof_constraints; }

References _dof_constraints.

Referenced by libMesh::StaticCondensationDofMap::add_uncondensed_dof_plus_constraint_dofs().

◆ get_info() [1/2]

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

Gets a string containing the reference information.

Definition at line 47 of file reference_counter.C.

48{
49#if defined(LIBMESH_ENABLE_REFERENCE_COUNTING) && defined(DEBUG)
50
51 std::ostringstream oss;
52
53 oss << '\n'
54 << " ---------------------------------------------------------------------------- \n"
55 << "| Reference count information |\n"
56 << " ---------------------------------------------------------------------------- \n";
57
58 for (const auto & [name, cd] : _counts)
59 oss << "| " << name << " reference count information:\n"
60 << "| Creations: " << cd.first << '\n'
61 << "| Destructions: " << cd.second << '\n';
62
63 oss << " ---------------------------------------------------------------------------- \n";
64
65 return oss.str();
66
67#else
68
69 return "";
70
71#endif
72}
static Counts _counts
Actually holds the data.
std::string name(const ElemQuality q)
This function returns a string containing some name for q.

References libMesh::ReferenceCounter::_counts.

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

◆ get_info() [2/2]

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

Gets summary info about the sparsity bandwidth and constraints.

Definition at line 2985 of file dof_map.C.

2986{
2987 std::ostringstream os;
2988
2989 // If we didn't calculate the exact sparsity pattern, the threaded
2990 // sparsity pattern assembly may have just given us an upper bound
2991 // on sparsity.
2992 const char * may_equal = " <= ";
2993
2994 // If we calculated the exact sparsity pattern, then we can report
2995 // exact bandwidth figures:
2996 for (const auto & mat : _matrices)
2998 may_equal = " = ";
2999
3000 dof_id_type max_n_nz = 0, max_n_oz = 0;
3001 long double avg_n_nz = 0, avg_n_oz = 0;
3002
3003 if (_sp)
3004 {
3005 for (const auto & val : _sp->get_n_nz())
3006 {
3007 max_n_nz = std::max(max_n_nz, val);
3008 avg_n_nz += val;
3009 }
3010
3011 std::size_t n_nz_size = _sp->get_n_nz().size();
3012
3013 this->comm().max(max_n_nz);
3014 this->comm().sum(avg_n_nz);
3015 this->comm().sum(n_nz_size);
3016
3017 avg_n_nz /= std::max(n_nz_size,std::size_t(1));
3018
3019 for (const auto & val : _sp->get_n_oz())
3020 {
3021 max_n_oz = std::max(max_n_oz, val);
3022 avg_n_oz += val;
3023 }
3024
3025 std::size_t n_oz_size = _sp->get_n_oz().size();
3026
3027 this->comm().max(max_n_oz);
3028 this->comm().sum(avg_n_oz);
3029 this->comm().sum(n_oz_size);
3030
3031 avg_n_oz /= std::max(n_oz_size,std::size_t(1));
3032 }
3033
3034 os << " DofMap Sparsity\n Average On-Processor Bandwidth"
3035 << may_equal << avg_n_nz << '\n';
3036
3037 os << " Average Off-Processor Bandwidth"
3038 << may_equal << avg_n_oz << '\n';
3039
3040 os << " Maximum On-Processor Bandwidth"
3041 << may_equal << max_n_nz << '\n';
3042
3043 os << " Maximum Off-Processor Bandwidth"
3044 << may_equal << max_n_oz << std::endl;
3045
3046#ifdef LIBMESH_ENABLE_CONSTRAINTS
3047
3048 std::size_t n_constraints = 0, max_constraint_length = 0,
3049 n_rhss = 0;
3050 long double avg_constraint_length = 0.;
3051
3052 for (const auto & [constrained_dof, row] : _dof_constraints)
3053 {
3054 // Only count local constraints, then sum later
3055 if (!this->local_index(constrained_dof))
3056 continue;
3057
3058 std::size_t rowsize = row.size();
3059
3060 max_constraint_length = std::max(max_constraint_length,
3061 rowsize);
3062 avg_constraint_length += rowsize;
3063 n_constraints++;
3064
3065 if (_primal_constraint_values.count(constrained_dof))
3066 n_rhss++;
3067 }
3068
3069 this->comm().sum(n_constraints);
3070 this->comm().sum(n_rhss);
3071 this->comm().sum(avg_constraint_length);
3072 this->comm().max(max_constraint_length);
3073
3074 os << " DofMap Constraints\n Number of DoF Constraints = "
3075 << n_constraints;
3076 if (n_rhss)
3077 os << '\n'
3078 << " Number of Heterogenous Constraints= " << n_rhss;
3079 if (n_constraints)
3080 {
3081 avg_constraint_length /= n_constraints;
3082
3083 os << '\n'
3084 << " Average DoF Constraint Length= " << avg_constraint_length;
3085 }
3086
3087#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3088 std::size_t n_node_constraints = 0, max_node_constraint_length = 0,
3089 n_node_rhss = 0;
3090 long double avg_node_constraint_length = 0.;
3091
3092 for (const auto & [node, pr] : _node_constraints)
3093 {
3094 // Only count local constraints, then sum later
3095 if (node->processor_id() != this->processor_id())
3096 continue;
3097
3098 const NodeConstraintRow & row = pr.first;
3099 std::size_t rowsize = row.size();
3100
3101 max_node_constraint_length = std::max(max_node_constraint_length,
3102 rowsize);
3103 avg_node_constraint_length += rowsize;
3104 n_node_constraints++;
3105
3106 if (pr.second != Point(0))
3107 n_node_rhss++;
3108 }
3109
3110 this->comm().sum(n_node_constraints);
3111 this->comm().sum(n_node_rhss);
3112 this->comm().sum(avg_node_constraint_length);
3113 this->comm().max(max_node_constraint_length);
3114
3115 os << "\n Number of Node Constraints = " << n_node_constraints;
3116 if (n_node_rhss)
3117 os << '\n'
3118 << " Number of Heterogenous Node Constraints= " << n_node_rhss;
3119 if (n_node_constraints)
3120 {
3121 avg_node_constraint_length /= n_node_constraints;
3122 os << "\n Maximum Node Constraint Length= " << max_node_constraint_length
3123 << '\n'
3124 << " Average Node Constraint Length= " << avg_node_constraint_length;
3125 }
3126#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
3127
3128 os << std::endl;
3129
3130#endif // LIBMESH_ENABLE_CONSTRAINTS
3131
3132 return os.str();
3133}
const std::vector< dof_id_type > & get_n_oz() const
Definition dof_map.h:555
const std::vector< dof_id_type > & get_n_nz() const
Definition dof_map.h:542

◆ get_local_constraints()

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

Gets a string reporting all DoF and Node constraints local to this processor.

If print_nonlocal is true, then nonlocal constraints which are locally known are included.

Definition at line 2279 of file dof_map_constraints.C.

2280{
2281 std::ostringstream os;
2282#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2283 if (print_nonlocal)
2284 os << "All ";
2285 else
2286 os << "Local ";
2287
2288 os << "Node Constraints:"
2289 << std::endl;
2290
2291 for (const auto & [node, pr] : _node_constraints)
2292 {
2293 // Skip non-local nodes if requested
2294 if (!print_nonlocal &&
2295 node->processor_id() != this->processor_id())
2296 continue;
2297
2298 const NodeConstraintRow & row = pr.first;
2299 const Point & offset = pr.second;
2300
2301 os << "Constraints for Node id " << node->id()
2302 << ": \t";
2303
2304 for (const auto & [cnode, val] : row)
2305 os << " (" << cnode->id() << "," << val << ")\t";
2306
2307 os << "rhs: " << offset;
2308
2309 os << std::endl;
2310 }
2311#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
2312
2313 if (print_nonlocal)
2314 os << "All ";
2315 else
2316 os << "Local ";
2317
2318 os << "DoF Constraints:"
2319 << std::endl;
2320
2321 for (const auto & [i, row] : _dof_constraints)
2322 {
2323 // Skip non-local dofs if requested
2324 if (!print_nonlocal && !this->local_index(i))
2325 continue;
2326
2327 DofConstraintValueMap::const_iterator rhsit =
2329 const Number rhs = (rhsit == _primal_constraint_values.end()) ?
2330 0 : rhsit->second;
2331
2332 os << "Constraints for DoF " << i
2333 << ": \t";
2334
2335 for (const auto & item : row)
2336 os << " (" << item.first << "," << item.second << ")\t";
2337
2338 os << "rhs: " << rhs;
2339 os << std::endl;
2340 }
2341
2342 for (unsigned int qoi_index = 0,
2343 n_qois = cast_int<unsigned int>(_adjoint_dirichlet_boundaries.size());
2344 qoi_index != n_qois; ++qoi_index)
2345 {
2346 os << "Adjoint " << qoi_index << " DoF rhs values:"
2347 << std::endl;
2348
2349 if (auto adjoint_map_it = _adjoint_constraint_values.find(qoi_index);
2350 adjoint_map_it != _adjoint_constraint_values.end())
2351 for (const auto & [i, rhs] : adjoint_map_it->second)
2352 {
2353 // Skip non-local dofs if requested
2354 if (!print_nonlocal && !this->local_index(i))
2355 continue;
2356
2357 os << "RHS for DoF " << i
2358 << ": " << rhs;
2359
2360 os << std::endl;
2361 }
2362 }
2363
2364 return os.str();
2365}

References _adjoint_constraint_values, _adjoint_dirichlet_boundaries, _dof_constraints, _node_constraints, _primal_constraint_values, local_index(), and libMesh::ParallelObject::processor_id().

Referenced by print_dof_constraints().

◆ get_n_nz()

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

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

Definition at line 542 of file dof_map.h.

543 {
545 return _sp->get_n_nz();
546 }

References _sp, and libMesh::libmesh_assert().

◆ get_n_oz()

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

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

Definition at line 555 of file dof_map.h.

556 {
558 return _sp->get_n_oz();
559 }

References _sp, and libMesh::libmesh_assert().

◆ get_periodic_boundaries() [1/2]

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

Definition at line 1583 of file dof_map.h.

1584 {
1585 return _periodic_boundaries.get();
1586 }

References _periodic_boundaries.

Referenced by main().

◆ get_periodic_boundaries() [2/2]

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

Definition at line 1588 of file dof_map.h.

1589 {
1590 return _periodic_boundaries.get();
1591 }

References _periodic_boundaries.

◆ get_primal_constraint_values()

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

Definition at line 2471 of file dof_map.h.

2472{
2474}

References _primal_constraint_values.

◆ get_send_list()

const std::vector< dof_id_type > & libMesh::DofMap::get_send_list ( ) const
inline

◆ get_sparsity_pattern()

const SparsityPattern::Build * libMesh::DofMap::get_sparsity_pattern ( ) const
inline
Returns
A constant pointer to the sparsity pattern stored here, once that has been computed. Returns null if no sparsity pattern has yet been computed.

If need_full_sparsity_pattern is false, the "sparsity pattern" may only own n_nz and n_oz lists.

Definition at line 570 of file dof_map.h.

571 {
572 return _sp.get();
573 }

References _sp.

Referenced by libMesh::SparseMatrix< T >::attach_dof_map().

◆ get_static_condensation() [1/2]

StaticCondensationDofMap & libMesh::DofMap::get_static_condensation ( )
inline
Returns
the static condensation class. This should have been already added with a call to add_static_condensation()

Definition at line 2859 of file dof_map.h.

2860{
2862 return *_sc;
2863}

References _sc, and libMesh::libmesh_assert().

Referenced by add_constraints_to_send_list().

◆ get_static_condensation() [2/2]

const StaticCondensationDofMap & libMesh::DofMap::get_static_condensation ( ) const
inline
Returns
the static condensation class. This should have been already added with a call to add_static_condensation()

Definition at line 2866 of file dof_map.h.

2867{
2869 return *_sc;
2870}

References _sc, and libMesh::libmesh_assert().

◆ get_variable_array()

const std::pair< unsigned int, unsigned int > & libMesh::DofMap::get_variable_array ( unsigned int  vi) const
inlineprivate

Retrieve the array variable bounds for a given variable vi.

This variable may lie anywhere within an array variable range. An 'array variable' is simply a sequence of contiguous variable numbers defined by pair where the first member of the pair is the first number in the variable sequence and the second member of the pair is the number of the last variable in the sequence plus one. Array variables may be used in tandem with variable grouping by downstream code to build optimized physics kernels since each variable in the array will have the same shape functions.

We note that we store array variables as a container of the above described pairs. Within this API we will do a binary search such that the complexity is O(log(N)) where N is the number of array variables present in this

Definition at line 2873 of file dof_map.h.

2874{
2875 auto it = std::upper_bound(
2876 _array_variables.begin(),
2877 _array_variables.end(),
2878 vi,
2879 [](unsigned int value, const std::pair<unsigned int, unsigned int> & b) { return value < b.first; });
2880
2881 libmesh_assert_msg(it != _array_variables.begin(),
2882 "Passed in " << std::to_string(vi) << " is not in any of our array variables");
2883 --it;
2884 libmesh_assert_msg(vi < it->second,
2885 "Passed in " << std::to_string(vi) << " is not in any of our array variables");
2886 return *it;
2887}
static const Real b
static const bool value
Definition xdr_io.C:55

References _array_variables, b, and value.

Referenced by array_dof_indices().

◆ has_adjoint_dirichlet_boundaries()

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

Definition at line 5456 of file dof_map_constraints.C.

5457{
5458 if (_adjoint_dirichlet_boundaries.size() > q)
5459 return true;
5460
5461 return false;
5462}

References _adjoint_dirichlet_boundaries.

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

◆ has_blocked_representation()

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

Definition at line 749 of file dof_map.h.

750 {
751 return ((this->n_variable_groups() == 1) && (this->n_variables() > 1));
752 }

References n_variable_groups(), and n_variables().

Referenced by block_size().

◆ has_heterogeneous_adjoint_constraint()

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

Definition at line 2450 of file dof_map.h.

2452{
2453 AdjointDofConstraintValues::const_iterator it =
2454 _adjoint_constraint_values.find(qoi_num);
2455 if (it != _adjoint_constraint_values.end())
2456 {
2457 DofConstraintValueMap::const_iterator rhsit =
2458 it->second.find(dof);
2459 if (rhsit == it->second.end())
2460 return 0;
2461 else
2462 return rhsit->second;
2463 }
2464
2465 return 0;
2466}

References _adjoint_constraint_values.

Referenced by has_heterogenous_adjoint_constraint().

◆ has_heterogeneous_adjoint_constraints()

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

Definition at line 2436 of file dof_map.h.

2437{
2438 AdjointDofConstraintValues::const_iterator it =
2439 _adjoint_constraint_values.find(qoi_num);
2440 if (it == _adjoint_constraint_values.end())
2441 return false;
2442 if (it->second.empty())
2443 return false;
2444
2445 return true;
2446}

References _adjoint_constraint_values.

Referenced by has_heterogenous_adjoint_constraints().

◆ has_heterogenous_adjoint_constraint()

Number libMesh::DofMap::has_heterogenous_adjoint_constraint ( const unsigned int  qoi_num,
const dof_id_type  dof 
) const
inline

Backwards compatibility with misspelling.

Definition at line 1253 of file dof_map.h.

1255 {
1256 return this->has_heterogeneous_adjoint_constraint (qoi_num, dof);
1257 }
Number has_heterogeneous_adjoint_constraint(const unsigned int qoi_num, const dof_id_type dof) const
Definition dof_map.h:2450

References has_heterogeneous_adjoint_constraint().

◆ has_heterogenous_adjoint_constraints()

bool libMesh::DofMap::has_heterogenous_adjoint_constraints ( const unsigned int  qoi_num) const
inline

Backwards compatibility with misspelling.

Definition at line 1237 of file dof_map.h.

1238 {
1239 return this->has_heterogeneous_adjoint_constraints (qoi_num);
1240 }
bool has_heterogeneous_adjoint_constraints(const unsigned int qoi_num) const
Definition dof_map.h:2436

References has_heterogeneous_adjoint_constraints().

◆ has_static_condensation()

bool libMesh::DofMap::has_static_condensation ( ) const
inline

Checks whether we have static condensation.

Definition at line 1797 of file dof_map.h.

1797{ return _sc.get(); }

References _sc.

Referenced by add_constraints_to_send_list(), and build_sparsity().

◆ has_variable()

bool libMesh::DofMap::has_variable ( std::string_view  var) const
inline
Returns
true if a variable named var exists in this System

Definition at line 2986 of file dof_map.h.

2987{
2988 return _variable_numbers.count(var);
2989}

References _variable_numbers.

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

◆ heterogeneously_constrain_element_jacobian_and_residual()

void libMesh::DofMap::heterogeneously_constrain_element_jacobian_and_residual ( DenseMatrix< Number > &  matrix,
DenseVector< Number > &  rhs,
std::vector< dof_id_type > &  elem_dofs,
NumericVector< Number > &  solution_local 
) const

Constrains the element Jacobian and residual.

The element Jacobian is square, and the elem_dofs should correspond to the global DOF indices of both the rows and columns of the element matrix.

The residual-constraining version of this method creates linear systems in which heterogeneously constrained degrees of freedom create non-zero residual terms when not at their correct offset values, as would be appropriate for finding a solution to a nonlinear problem in a quasi-Newton solve.

Note the sign difference from the linear heterogeneous constraint method: Solving u:=u_in-J\r has the opposite sign convention from u:=K\f, and we apply heterogeneous constraints accordingly.

The solution vector passed in should be a serialized or ghosted primal solution

Definition at line 2619 of file dof_map_constraints.C.

2624{
2625 libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
2626 libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
2627 libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
2628
2629 libmesh_assert (solution_local.type() == SERIAL ||
2630 solution_local.type() == GHOSTED);
2631
2632 // check for easy return
2633 if (this->_dof_constraints.empty())
2634 return;
2635
2636 // The constrained matrix is built up as C^T K C.
2637 // The constrained RHS is built up as C^T F
2638 // Asymmetric residual terms are added if we do not have x = Cx+h
2641
2642 this->build_constraint_matrix_and_vector (C, H, elem_dofs);
2643
2644 LOG_SCOPE("hetero_cnstrn_elem_jac_res()", "DofMap");
2645
2646 // It is possible that the matrix is not constrained at all.
2647 if ((C.m() != matrix.m()) ||
2648 (C.n() != elem_dofs.size()))
2649 return;
2650
2651 // Compute the matrix-vector product C^T F
2652 DenseVector<Number> old_rhs(rhs);
2653 C.vector_mult_transpose(rhs, old_rhs);
2654
2655 // Compute the matrix-matrix-matrix product C^T K C
2656 matrix.left_multiply_transpose (C);
2657 matrix.right_multiply (C);
2658
2659 libmesh_assert_equal_to (matrix.m(), matrix.n());
2660 libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
2661 libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
2662
2663 for (unsigned int i=0,
2664 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2665 i != n_elem_dofs; i++)
2666 {
2667 const dof_id_type dof_id = elem_dofs[i];
2668
2669 if (auto pos = _dof_constraints.find(dof_id);
2670 pos != _dof_constraints.end())
2671 {
2672 for (auto j : make_range(matrix.n()))
2673 matrix(i,j) = 0.;
2674
2675 // If the DOF is constrained
2676 matrix(i,i) = 1.;
2677
2678 // This will put a nonsymmetric entry in the constraint
2679 // row to ensure that the linear system produces the
2680 // correct value for the constrained DOF.
2681 const DofConstraintRow & constraint_row = pos->second;
2682
2683 for (const auto & item : constraint_row)
2684 for (unsigned int j=0; j != n_elem_dofs; j++)
2685 if (elem_dofs[j] == item.first)
2686 matrix(i,j) = -item.second;
2687
2688 const DofConstraintValueMap::const_iterator valpos =
2689 _primal_constraint_values.find(dof_id);
2690
2691 Number & rhs_val = rhs(i);
2692 rhs_val = (valpos == _primal_constraint_values.end()) ?
2693 0 : -valpos->second;
2694 for (const auto & [constraining_dof, coef] : constraint_row)
2695 rhs_val -= coef * solution_local(constraining_dof);
2696 rhs_val += solution_local(dof_id);
2697 }
2698 }
2699}
void left_multiply_transpose(const DenseMatrix< T > &A)
Left multiplies by the transpose of the matrix A.

References _dof_constraints, _primal_constraint_values, build_constraint_matrix_and_vector(), libMesh::GHOSTED, libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::libmesh_assert(), libMesh::DenseMatrixBase< T >::m(), libMesh::make_range(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::right_multiply(), libMesh::SERIAL, libMesh::DenseVector< T >::size(), libMesh::NumericVector< T >::type(), and libMesh::DenseMatrix< T >::vector_mult_transpose().

◆ heterogeneously_constrain_element_matrix_and_vector()

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

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

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

Definition at line 2503 of file dof_map.h.

2505 {}

Referenced by heterogenously_constrain_element_matrix_and_vector(), and process_mesh_constraint_rows().

◆ heterogeneously_constrain_element_residual()

void libMesh::DofMap::heterogeneously_constrain_element_residual ( DenseVector< Number > &  rhs,
std::vector< dof_id_type > &  elem_dofs,
NumericVector< Number > &  solution_local 
) const

Constrains the element residual.

The element Jacobian is square, and the elem_dofs should correspond to the global DOF indices of both the rows and columns of the element matrix.

The residual-constraining version of this method creates linear systems in which heterogeneously constrained degrees of freedom create non-zero residual terms when not at their correct offset values, as would be appropriate for finding a solution to a nonlinear problem in a quasi-Newton solve.

The solution vector passed in should be a serialized or ghosted primal solution

Definition at line 2702 of file dof_map_constraints.C.

2706{
2707 libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
2708
2709 libmesh_assert (solution_local.type() == SERIAL ||
2710 solution_local.type() == GHOSTED);
2711
2712 // check for easy return
2713 if (this->_dof_constraints.empty())
2714 return;
2715
2716 // The constrained RHS is built up as C^T F
2717 // Asymmetric residual terms are added if we do not have x = Cx+h
2720
2721 this->build_constraint_matrix_and_vector (C, H, elem_dofs);
2722
2723 LOG_SCOPE("hetero_cnstrn_elem_res()", "DofMap");
2724
2725 // It is possible that the element is not constrained at all.
2726 if ((C.m() != rhs.size()) ||
2727 (C.n() != elem_dofs.size()))
2728 return;
2729
2730 // Compute the matrix-vector product C^T F
2731 DenseVector<Number> old_rhs(rhs);
2732 C.vector_mult_transpose(rhs, old_rhs);
2733
2734 for (unsigned int i=0,
2735 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2736 i != n_elem_dofs; i++)
2737 {
2738 const dof_id_type dof_id = elem_dofs[i];
2739
2740 if (auto pos = _dof_constraints.find(dof_id);
2741 pos != _dof_constraints.end())
2742 {
2743 // This will put a nonsymmetric entry in the constraint
2744 // row to ensure that the linear system produces the
2745 // correct value for the constrained DOF.
2746 const DofConstraintRow & constraint_row = pos->second;
2747
2748 const DofConstraintValueMap::const_iterator valpos =
2749 _primal_constraint_values.find(dof_id);
2750
2751 Number & rhs_val = rhs(i);
2752 rhs_val = (valpos == _primal_constraint_values.end()) ?
2753 0 : -valpos->second;
2754 for (const auto & [constraining_dof, coef] : constraint_row)
2755 rhs_val -= coef * solution_local(constraining_dof);
2756 rhs_val += solution_local(dof_id);
2757 }
2758 }
2759}

References _dof_constraints, _primal_constraint_values, build_constraint_matrix_and_vector(), libMesh::GHOSTED, libMesh::libmesh_assert(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::SERIAL, libMesh::DenseVector< T >::size(), libMesh::NumericVector< T >::type(), and libMesh::DenseMatrix< T >::vector_mult_transpose().

◆ heterogeneously_constrain_element_vector()

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

Constrains the element vector.

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

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

Note the sign difference from the nonlinear heterogeneous constraint method: Solving u:=K\f has the opposite sign convention from u:=u_in-J\r, and we apply heterogeneous constraints accordingly.

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

Definition at line 2507 of file dof_map.h.

2509 {}

Referenced by heterogenously_constrain_element_vector().

◆ heterogenously_constrain_element_matrix_and_vector()

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

Definition at line 1388 of file dof_map.h.

1393 {
1395 (matrix, rhs, elem_dofs, asymmetric_constraint_rows, qoi_index);
1396 }
void heterogeneously_constrain_element_matrix_and_vector(DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true, int qoi_index=-1) const
Constrains the element matrix and vector.
Definition dof_map.h:2504

References heterogeneously_constrain_element_matrix_and_vector().

Referenced by assemble_stokes(), and libMesh::System::solve_for_unconstrained_dofs().

◆ heterogenously_constrain_element_vector()

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

Definition at line 1432 of file dof_map.h.

1437 {
1439 (matrix, rhs, elem_dofs, asymmetric_constraint_rows, qoi_index);
1440 }
void heterogeneously_constrain_element_vector(const DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true, int qoi_index=-1) const
Constrains the element vector.
Definition dof_map.h:2508

References heterogeneously_constrain_element_vector().

◆ identify_variable_groups() [1/2]

bool libMesh::DofMap::identify_variable_groups ( ) const
inline
Returns
true when VariableGroup structures should be automatically identified, false otherwise.

Definition at line 2951 of file dof_map.h.

2952{
2954}
bool _identify_variable_groups
true when VariableGroup structures should be automatically identified, false otherwise.
Definition dof_map.h:2130

References _identify_variable_groups.

◆ identify_variable_groups() [2/2]

void libMesh::DofMap::identify_variable_groups ( const bool  ivg)
inline

Toggle automatic VariableGroup identification.

Definition at line 2957 of file dof_map.h.

2958{
2960}

References _identify_variable_groups.

◆ increment_constructor_count()

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

Increments the construction counter.

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

Definition at line 183 of file reference_counter.h.

184{
185 libmesh_try
186 {
187 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
188 std::pair<unsigned int, unsigned int> & p = _counts[name];
189 p.first++;
190 }
191 libmesh_catch (...)
192 {
193 auto stream = libMesh::err.get();
194 stream->exceptions(stream->goodbit); // stream must not throw
195 libMesh::err << "Encountered unrecoverable error while calling "
196 << "ReferenceCounter::increment_constructor_count() "
197 << "for a(n) " << name << " object." << std::endl;
198 std::terminate();
199 }
200}
streamT * get()
Rather than implement every ostream/ios/ios_base function, we'll be lazy and make esoteric uses go th...
OStreamProxy err

References libMesh::err, libMesh::BasicOStreamProxy< charT, traits >::get(), and libMesh::Threads::spin_mtx.

Referenced by libMesh::ReferenceCountedObject< T >::ReferenceCountedObject(), libMesh::ReferenceCountedObject< T >::ReferenceCountedObject(), and libMesh::ReferenceCountedObject< T >::ReferenceCountedObject().

◆ increment_destructor_count()

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

Increments the destruction counter.

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

Definition at line 207 of file reference_counter.h.

208{
209 libmesh_try
210 {
211 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
212 std::pair<unsigned int, unsigned int> & p = _counts[name];
213 p.second++;
214 }
215 libmesh_catch (...)
216 {
217 auto stream = libMesh::err.get();
218 stream->exceptions(stream->goodbit); // stream must not throw
219 libMesh::err << "Encountered unrecoverable error while calling "
220 << "ReferenceCounter::increment_destructor_count() "
221 << "for a(n) " << name << " object." << std::endl;
222 std::terminate();
223 }
224}

References libMesh::err, libMesh::BasicOStreamProxy< charT, traits >::get(), and libMesh::Threads::spin_mtx.

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

◆ invalidate_dofs()

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

Invalidates all active DofObject dofs for this system.

Definition at line 856 of file dof_map.C.

857{
858 const unsigned int sys_num = this->sys_number();
859
860 // All the nodes
861 for (auto & node : mesh.node_ptr_range())
862 node->invalidate_dofs(sys_num);
863
864 // All the active elements.
865 for (auto & elem : mesh.active_element_ptr_range())
866 elem->invalidate_dofs(sys_num);
867}

References mesh.

◆ is_attached()

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

Matrices should not be attached more than once.

We can test for an already-attached matrix if necessary using is_attached

Definition at line 295 of file dof_map.C.

296{
297 return (std::find(_matrices.begin(), _matrices.end(),
298 &matrix) != _matrices.end());
299}

References _matrices.

Referenced by OverlappingCouplingGhostingTest::run_sparsity_pattern_test().

◆ is_constrained_dof()

bool libMesh::DofMap::is_constrained_dof ( const dof_id_type  dof) const
inline

◆ is_constrained_node()

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

Definition at line 2410 of file dof_map.h.

2415{
2416#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2417 if (_node_constraints.count(node))
2418 return true;
2419#endif
2420
2421 return false;
2422}

References _node_constraints.

Referenced by allgather_recursive_constraints(), and scatter_constraints().

◆ is_evaluable()

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

Definition at line 2673 of file dof_map.C.

2675{
2676 // Everything is evaluable on a local object
2677 if (obj.processor_id() == this->processor_id())
2678 return true;
2679
2680 std::vector<dof_id_type> di;
2681
2682 if (var_num == libMesh::invalid_uint)
2683 this->dof_indices(&obj, di);
2684 else
2685 this->dof_indices(&obj, di, var_num);
2686
2687 return this->all_semilocal_indices(di);
2688}
bool all_semilocal_indices(const std::vector< dof_id_type > &dof_indices) const
Definition dof_map.C:2660

References libMesh::invalid_uint.

Referenced by libMesh::MeshFunction::check_found_elem(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), DefaultCouplingTest::testCoupling(), and PointNeighborCouplingTest::testCoupling().

◆ is_periodic_boundary()

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

Definition at line 217 of file dof_map.C.

218{
219 if (_periodic_boundaries->count(boundaryid) != 0)
220 return true;
221
222 return false;
223}

References _periodic_boundaries.

◆ local_index()

bool libMesh::DofMap::local_index ( dof_id_type  dof_index) const
inline

◆ local_variable_indices() [1/2]

template<typename T , std::enable_if_t< std::is_same_v< T, dof_id_type >||std::is_same_v< T, std::vector< dof_id_type > >, int > >
void libMesh::DofMap::local_variable_indices ( T &  idx,
const MeshBase mesh,
unsigned int  var_num 
) const

If T == dof_id_type, counts, if T == std::vector<dof_id_type>, fills an array of, those dof indices which belong to the given variable number and live on the current processor.

Definition at line 1122 of file dof_map.C.

1125{
1126 // Only used if T == dof_id_type to keep track of the greatest dof we've seen
1127 dof_id_type greatest = 0;
1128
1129 if constexpr (std::is_same_v<T, dof_id_type>)
1130 idx = 0;
1131 else if constexpr (std::is_same_v<T, std::vector<dof_id_type>>)
1132 idx.clear();
1133
1134 // Count dofs in the *exact* order that distribute_dofs numbered
1135 // them, so that we can assume ascending indices and use push_back
1136 // instead of find+insert.
1137
1138 const unsigned int sys_num = this->sys_number();
1139
1140 // If this isn't a SCALAR variable, we need to find all its field
1141 // dofs on the mesh
1142 if (this->variable_type(var_num).family != SCALAR)
1143 {
1144 const Variable & var(this->variable(var_num));
1145
1146 for (auto & elem : mesh.active_local_element_ptr_range())
1147 {
1148 if (!var.active_on_subdomain(elem->subdomain_id()))
1149 continue;
1150
1151 // Only count dofs connected to active
1152 // elements on this processor.
1153 const unsigned int n_nodes = elem->n_nodes();
1154
1155 // First get any new nodal DOFS
1156 for (unsigned int n=0; n<n_nodes; n++)
1157 {
1158 const Node & node = elem->node_ref(n);
1159
1160 if (node.processor_id() != this->processor_id())
1161 continue;
1162
1163 const unsigned int n_comp = node.n_comp(sys_num, var_num);
1164 for(unsigned int i=0; i<n_comp; i++)
1165 {
1166 const dof_id_type index = node.dof_number(sys_num,var_num,i);
1167 libmesh_assert (this->local_index(index));
1168
1169 if constexpr (std::is_same_v<T, dof_id_type>)
1170 {
1171 if (idx == 0 || index > greatest)
1172 { idx++; greatest = index; }
1173 }
1174 else if constexpr (std::is_same_v<T, std::vector<dof_id_type>>)
1175 {
1176 if (idx.empty() || index > idx.back())
1177 idx.push_back(index);
1178 }
1179 }
1180 }
1181
1182 // Next get any new element DOFS
1183 const unsigned int n_comp = elem->n_comp(sys_num, var_num);
1184 for (unsigned int i=0; i<n_comp; i++)
1185 {
1186 const dof_id_type index = elem->dof_number(sys_num,var_num,i);
1187
1188 if constexpr (std::is_same_v<T, dof_id_type>)
1189 {
1190 if (idx == 0 || index > greatest)
1191 { idx++; greatest = index; }
1192 }
1193 else if constexpr (std::is_same_v<T, std::vector<dof_id_type>>)
1194 {
1195 if (idx.empty() || index > idx.back())
1196 idx.push_back(index);
1197 }
1198 }
1199 } // done looping over elements
1200
1201
1202 // we may have missed assigning DOFs to nodes that we own
1203 // but to which we have no connected elements matching our
1204 // variable restriction criterion. this will happen, for example,
1205 // if variable V is restricted to subdomain S. We may not own
1206 // any elements which live in S, but we may own nodes which are
1207 // *connected* to elements which do. in this scenario these nodes
1208 // will presently have unnumbered DOFs. we need to take care of
1209 // them here since we own them and no other processor will touch them.
1210 for (const auto & node : mesh.local_node_ptr_range())
1211 {
1212 libmesh_assert(node);
1213
1214 const unsigned int n_comp = node->n_comp(sys_num, var_num);
1215 for (unsigned int i=0; i<n_comp; i++)
1216 {
1217 const dof_id_type index = node->dof_number(sys_num,var_num,i);
1218
1219 if constexpr (std::is_same_v<T, dof_id_type>)
1220 {
1221 if (idx == 0 || index > greatest)
1222 { idx++; greatest = index; }
1223 }
1224 else if constexpr (std::is_same_v<T, std::vector<dof_id_type>>)
1225 {
1226 if (idx.empty() || index > idx.back())
1227 idx.push_back(index);
1228 }
1229 }
1230 }
1231 }
1232 // Otherwise, count up the SCALAR dofs, if we're on the processor
1233 // that holds this SCALAR variable
1234 else if (this->processor_id() == (this->n_processors()-1))
1235 {
1236 std::vector<dof_id_type> di_scalar;
1237 this->SCALAR_dof_indices(di_scalar,var_num);
1238
1239 if constexpr (std::is_same_v<T, dof_id_type>)
1240 idx += std::distance(di_scalar.begin(), di_scalar.end());
1241 else if constexpr (std::is_same_v<T, std::vector<dof_id_type>>)
1242 idx.insert(idx.end(), di_scalar.begin(), di_scalar.end());
1243 }
1244}
unsigned int idx(const ElemType type, const unsigned int nx, const unsigned int i, const unsigned int j)
A useful inline function which replaces the macros used previously.

References libMesh::Variable::active_on_subdomain(), libMesh::DofObject::dof_number(), libMesh::libmesh_assert(), mesh, libMesh::DofObject::n_comp(), n_nodes, libMesh::DofObject::processor_id(), and libMesh::SCALAR.

Referenced by libMesh::PetscDMWrapper::init_petscdm(), local_variable_indices(), n_local_dofs(), libMesh::petsc_auto_fieldsplit(), libMesh::PetscPreconditioner< T >::set_hypre_ads_data(), libMesh::PetscPreconditioner< T >::set_hypre_ams_data(), and SystemsTest::testBlockRestrictedVarNDofs().

◆ local_variable_indices() [2/2]

template<typename T , std::enable_if_t< std::is_same_v< T, dof_id_type >||std::is_same_v< T, std::vector< dof_id_type > >, int > = 0>
void libMesh::DofMap::local_variable_indices ( T &  idx,
unsigned int  var_num 
) const
inline

If T == dof_id_type, counts, if T == std::vector<dof_id_type>, fills an array of, those dof indices which belong to the given variable number and live on the current processor.

Definition at line 1035 of file dof_map.h.

1036 { this->local_variable_indices(idx, this->_mesh, var_num); }
void local_variable_indices(T &idx, const MeshBase &mesh, unsigned int var_num) const
If T == dof_id_type, counts, if T == std::vector<dof_id_type>, fills an array of, those dof indices w...
Definition dof_map.C:1122

References _mesh, and local_variable_indices().

◆ max_constraint_error()

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

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

Useful for debugging purposes.

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

Definition at line 3355 of file dof_map_constraints.C.

3357{
3358 if (!v)
3359 v = system.solution.get();
3360 NumericVector<Number> & vec = *v;
3361
3362 // We'll assume the vector is closed
3363 libmesh_assert (vec.closed());
3364
3365 Real max_absolute_error = 0., max_relative_error = 0.;
3366
3367 const MeshBase & mesh = system.get_mesh();
3368
3369 libmesh_assert_equal_to (this, &(system.get_dof_map()));
3370
3371 // indices on each element
3372 std::vector<dof_id_type> local_dof_indices;
3373
3374 for (const auto & elem : mesh.active_local_element_ptr_range())
3375 {
3376 this->dof_indices(elem, local_dof_indices);
3377 std::vector<dof_id_type> raw_dof_indices = local_dof_indices;
3378
3379 // Constraint matrix for each element
3381
3382 this->build_constraint_matrix (C, local_dof_indices);
3383
3384 // Continue if the element is unconstrained
3385 if (!C.m())
3386 continue;
3387
3388 libmesh_assert_equal_to (C.m(), raw_dof_indices.size());
3389 libmesh_assert_equal_to (C.n(), local_dof_indices.size());
3390
3391 for (auto i : make_range(C.m()))
3392 {
3393 // Recalculate any constrained dof owned by this processor
3394 dof_id_type global_dof = raw_dof_indices[i];
3395 if (this->is_constrained_dof(global_dof) &&
3396 global_dof >= vec.first_local_index() &&
3397 global_dof < vec.last_local_index())
3398 {
3399#ifndef NDEBUG
3400 DofConstraints::const_iterator
3401 pos = _dof_constraints.find(global_dof);
3402
3403 libmesh_assert (pos != _dof_constraints.end());
3404#endif
3405
3406 Number exact_value = 0;
3407 DofConstraintValueMap::const_iterator rhsit =
3408 _primal_constraint_values.find(global_dof);
3409 if (rhsit != _primal_constraint_values.end())
3410 exact_value = rhsit->second;
3411
3412 for (auto j : make_range(C.n()))
3413 {
3414 if (local_dof_indices[j] != global_dof)
3415 exact_value += C(i,j) *
3416 vec(local_dof_indices[j]);
3417 }
3418
3419 max_absolute_error = std::max(max_absolute_error,
3420 std::abs(vec(global_dof) - exact_value));
3421 max_relative_error = std::max(max_relative_error,
3422 std::abs(vec(global_dof) - exact_value)
3423 / std::abs(exact_value));
3424 }
3425 }
3426 }
3427
3428 return std::pair<Real, Real>(max_absolute_error, max_relative_error);
3429}
Number exact_value(const Point &p, const Parameters &parameters, const std::string &, const std::string &)
This is the MeshBase class.
Definition mesh_base.h:81
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
virtual bool closed() const
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition system.h:1655
const DofMap & get_dof_map() const
Definition system.h:2417
const MeshBase & get_mesh() const
Definition system.h:2401

References _dof_constraints, _primal_constraint_values, build_constraint_matrix(), libMesh::NumericVector< T >::closed(), dof_indices(), exact_value(), libMesh::NumericVector< T >::first_local_index(), libMesh::System::get_dof_map(), libMesh::System::get_mesh(), is_constrained_dof(), libMesh::NumericVector< T >::last_local_index(), libMesh::libmesh_assert(), libMesh::DenseMatrixBase< T >::m(), libMesh::make_range(), mesh, libMesh::DenseMatrixBase< T >::n(), libMesh::Real, and libMesh::System::solution.

◆ merge_ghost_functor_outputs()

void libMesh::DofMap::merge_ghost_functor_outputs ( GhostingFunctor::map_type elements_to_ghost,
CouplingMatricesSet temporary_coupling_matrices,
const GhostingFunctorIterator gf_begin,
const GhostingFunctorIterator gf_end,
const MeshBase::const_element_iterator elems_begin,
const MeshBase::const_element_iterator elems_end,
processor_id_type  p 
)
staticprivate

Definition at line 1584 of file dof_map.C.

1592{
1593 for (const auto & gf : as_range(gf_begin, gf_end))
1594 {
1595 GhostingFunctor::map_type more_elements_to_ghost;
1596
1597 libmesh_assert(gf);
1598 (*gf)(elems_begin, elems_end, p, more_elements_to_ghost);
1599
1600 // A GhostingFunctor should only return active elements, but
1601 // I forgot to *document* that, so let's go as easy as we
1602 // can on functors that return inactive elements.
1603#if defined(LIBMESH_ENABLE_DEPRECATED) && defined(LIBMESH_ENABLE_AMR)
1604 std::vector<std::pair<const Elem*, const CouplingMatrix*>> children_to_couple;
1605 for (auto it = more_elements_to_ghost.begin();
1606 it != more_elements_to_ghost.end();)
1607 {
1608 const Elem * elem = it->first;
1609 if (!elem->active())
1610 {
1611 libmesh_deprecated();
1612 std::vector<const Elem*> children_to_ghost;
1613 elem->active_family_tree(children_to_ghost,
1614 /*reset=*/ false);
1615 for (const Elem * child : children_to_ghost)
1616 if (child->processor_id() != p)
1617 children_to_couple.emplace_back(child, it->second);
1618
1619 it = more_elements_to_ghost.erase(it);
1620 }
1621 else
1622 ++it;
1623 }
1624 more_elements_to_ghost.insert(children_to_couple.begin(),
1625 children_to_couple.end());
1626#endif
1627
1628 for (const auto & [elem, elem_cm] : more_elements_to_ghost)
1629 {
1630 // At this point we should only have active elements, even
1631 // if we had to fix up gf output to get here.
1632 libmesh_assert(elem->active());
1633
1634 if (const auto existing_it = elements_to_ghost.find(elem);
1635 existing_it == elements_to_ghost.end())
1636 elements_to_ghost.emplace(elem, elem_cm);
1637 else
1638 {
1639 if (existing_it->second)
1640 {
1641 if (elem_cm)
1642 {
1643 // If this isn't already a temporary
1644 // then we need to make one so we'll
1645 // have a non-const matrix to merge
1646 if (temporary_coupling_matrices.empty() ||
1647 !temporary_coupling_matrices.count(existing_it->second))
1648 {
1649 // Make copy. This just calls the
1650 // compiler-generated copy constructor
1651 // because the CouplingMatrix class does not
1652 // define a custom copy constructor.
1653 auto result_pr = temporary_coupling_matrices.insert(std::make_unique<CouplingMatrix>(*existing_it->second));
1654 existing_it->second = result_pr.first->get();
1655 }
1656
1657 // Merge elem_cm into existing CouplingMatrix
1658 const_cast<CouplingMatrix &>(*existing_it->second) &= *elem_cm;
1659 }
1660 else // elem_cm == nullptr
1661 {
1662 // Any existing_it matrix merged with a full
1663 // matrix (symbolized as nullptr) gives another
1664 // full matrix (symbolizable as nullptr).
1665
1666 // So if existing_it->second is a temporary then
1667 // we don't need it anymore; we might as well
1668 // remove it to keep the set of temporaries
1669 // small.
1670 if (const auto temp_it = temporary_coupling_matrices.find(existing_it->second);
1671 temp_it != temporary_coupling_matrices.end())
1672 temporary_coupling_matrices.erase(temp_it);
1673
1674 existing_it->second = nullptr;
1675 }
1676 }
1677 // else we have a nullptr already, then we have a full
1678 // coupling matrix, already, and merging with anything
1679 // else won't change that, so we're done.
1680 }
1681 }
1682 }
1683}

References libMesh::Elem::active(), libMesh::Elem::active_family_tree(), libMesh::as_range(), and libMesh::libmesh_assert().

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

◆ n_components()

unsigned int libMesh::DofMap::n_components ( const MeshBase mesh) const
inline
Returns
The total number of scalar components in the system's variables. This will equal n_vars() in the case of all scalar-valued variables. If vector variables are involved, we will need to leverage the mesh

Definition at line 2963 of file dof_map.h.

2964{
2965 if (_variables.empty())
2966 return 0;
2967
2968 const Variable & last = _variables.back();
2969 return last.first_scalar_number() + last.n_components(mesh);
2970}

References _variables, libMesh::Variable::first_scalar_number(), mesh, and libMesh::Variable::n_components().

◆ n_constrained_dofs()

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

Definition at line 1714 of file dof_map_constraints.C.

1715{
1716 parallel_object_only();
1717
1718 dof_id_type nc_dofs = this->n_local_constrained_dofs();
1719 this->comm().sum(nc_dofs);
1720 return nc_dofs;
1721}
dof_id_type n_local_constrained_dofs() const

References libMesh::ParallelObject::comm(), n_local_constrained_dofs(), and libMesh::Parallel::Communicator::sum().

Referenced by libMesh::CondensedEigenSystem::initialize_condensed_dofs(), ConstraintOperatorTest::test1DCoarseningNewNodes(), ConstraintOperatorTest::test1DCoarseningOperator(), and MeshInputTest::testDynaReadPatch().

◆ n_constrained_nodes()

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

Definition at line 1059 of file dof_map.h.

1060 { return cast_int<dof_id_type>(_node_constraints.size()); }

References _node_constraints.

◆ n_dofs() [1/2]

dof_id_type libMesh::DofMapBase::n_dofs ( ) const
inline
Returns
The total number of degrees of freedom in the problem.

Definition at line 105 of file dof_map_base.h.

105{ return _n_dfs; }
dof_id_type _n_dfs
Total number of degrees of freedom.

Referenced by _dof_indices(), add_constraint_row(), and process_mesh_constraint_rows().

◆ n_dofs() [2/2]

dof_id_type libMesh::DofMap::n_dofs ( const unsigned int  vn) const
inline

◆ n_dofs_on_processor()

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

Definition at line 197 of file dof_map_base.h.

198{
199 libmesh_assert_less(proc, _first_df.size());
200 return cast_int<dof_id_type>(_end_df[proc] - _first_df[proc]);
201}

References libMesh::DofMapBase::_end_df, and libMesh::DofMapBase::_first_df.

Referenced by libMesh::DofMapBase::n_local_dofs(), and SystemsTest::testProjectMatrix3D().

◆ n_dofs_per_processor()

std::vector< dof_id_type > libMesh::DofMap::n_dofs_per_processor ( const unsigned int  vn) const
inline
Returns
The number of degrees of freedom on each partition for a particular variable vn.

Definition at line 805 of file dof_map.h.

806 {
807 std::vector<dof_id_type> n_local_dofs(this->n_processors(), 0);
808 this->comm().allgather(this->n_local_dofs(vn), n_local_dofs);
809 return n_local_dofs;
810 }
void allgather(const T &send_data, std::vector< T, A > &recv_data) const

References libMesh::Parallel::Communicator::allgather(), libMesh::ParallelObject::comm(), n_local_dofs(), and libMesh::ParallelObject::n_processors().

Referenced by libMesh::PetscPreconditioner< T >::set_hypre_ads_data(), libMesh::PetscPreconditioner< T >::set_hypre_ams_data(), and SystemsTest::test100KVariables().

◆ n_local_constrained_dofs()

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

Definition at line 1724 of file dof_map_constraints.C.

1725{
1726 const DofConstraints::const_iterator lower =
1727 _dof_constraints.lower_bound(this->first_dof()),
1728 upper =
1729 _dof_constraints.lower_bound(this->end_dof());
1730
1731 return cast_int<dof_id_type>(std::distance(lower, upper));
1732}

References _dof_constraints, libMesh::DofMapBase::end_dof(), and libMesh::DofMapBase::first_dof().

Referenced by n_constrained_dofs().

◆ n_local_dofs() [1/2]

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

Definition at line 115 of file dof_map_base.h.

115{ return this->n_dofs_on_processor(this->processor_id()); }
dof_id_type n_dofs_on_processor(const processor_id_type proc) const

Referenced by n_dofs(), n_dofs_per_processor(), and process_mesh_constraint_rows().

◆ n_local_dofs() [2/2]

dof_id_type libMesh::DofMap::n_local_dofs ( const unsigned int  vn) const
inline

◆ n_objects()

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

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

Definition at line 85 of file reference_counter.h.

86 { return _n_objects; }
static Threads::atomic< unsigned int > _n_objects
The number of objects.

References libMesh::ReferenceCounter::_n_objects.

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

◆ n_old_dofs()

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

Definition at line 123 of file dof_map_base.h.

123{ return _n_old_dfs; }

References libMesh::DofMapBase::_n_old_dfs.

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

◆ n_processors()

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

Definition at line 103 of file parallel_object.h.

104 {
105 processor_id_type returnval =
106 cast_int<processor_id_type>(_communicator.size());
107 libmesh_assert(returnval); // We never have an empty comm
108 return returnval;
109 }
processor_id_type size() const

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

Referenced by libMesh::Partitioner::_find_global_index_by_pid_map(), libMesh::BoundaryInfo::_find_id_maps(), add_constraints_to_send_list(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::DistributedMesh::add_elem(), libMesh::DistributedMesh::add_node(), libMesh::System::add_vector(), libMesh::LaplaceMeshSmoother::allgather_graph(), allgather_recursive_constraints(), libMesh::FEMSystem::assembly(), libMesh::Nemesis_IO::assert_symmetric_cmaps(), libMesh::Partitioner::assign_partitioning(), libMesh::AztecLinearSolver< T >::AztecLinearSolver(), libMesh::Partitioner::build_graph(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::DistributedMesh::clear(), libMesh::DistributedMesh::clear_elems(), libMesh::Nemesis_IO_Helper::compute_border_node_ids(), libMesh::Nemesis_IO_Helper::construct_nemesis_filename(), libMesh::UnstructuredMesh::copy_nodes_and_elements(), libMesh::ExodusII_IO::copy_scalar_solution(), libMesh::Nemesis_IO::copy_scalar_solution(), libMesh::UnstructuredMesh::create_pid_mesh(), libMesh::MeshTools::create_processor_bounding_box(), libMesh::DistributedMesh::DistributedMesh(), libMesh::EnsightIO::EnsightIO(), libMesh::RBEIMEvaluation::gather_bfs(), libMesh::MeshBase::get_info(), libMesh::StaticCondensation::init(), libMesh::SystemSubsetBySubdomain::init(), libMesh::PetscDMWrapper::init_petscdm(), libMesh::ExodusII_IO_Helper::initialize(), libMesh::Nemesis_IO_Helper::initialize(), libMesh::DistributedMesh::insert_elem(), libMesh::NumericVector< T >::is_effectively_ghosted(), libMesh::NumericVector< T >::is_effectively_serial(), libMesh::MeshTools::libmesh_assert_contiguous_dof_ids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_new_node_procids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Elem >(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_topology_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), libMesh::MeshTools::libmesh_assert_valid_refinement_flags(), libMesh::MeshBase::n_active_elem_on_proc(), n_dofs_per_processor(), libMesh::MeshBase::n_elem_on_proc(), libMesh::MeshBase::n_nodes_on_proc(), libMesh::RBEIMEvaluation::node_gather_bfs(), libMesh::MeshBase::partition(), libMesh::Partitioner::partition(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::MeshBase::print_constraint_rows(), print_dof_constraints(), libMesh::Nemesis_IO::read(), libMesh::CheckpointIO::read(), libMesh::NameBasedIO::read(), libMesh::CheckpointIO::read_connectivity(), libMesh::XdrIO::read_header(), libMesh::CheckpointIO::read_nodes(), libMesh::System::read_parallel_data(), libMesh::System::read_SCALAR_dofs(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::System::read_serialized_vector(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::Partitioner::repartition(), OverlappingFunctorTest::run_partitioner_test(), scatter_constraints(), libMesh::DistributedMesh::set_next_unique_id(), set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), WriteVecAndScalar::setupTests(), libMesh::RBEIMEvaluation::side_gather_bfs(), DistributedMeshTest::testRemoteElemError(), CheckpointIOTest::testSplitter(), libMesh::DistributedMesh::update_parallel_id_counts(), libMesh::GMVIO::write_binary(), libMesh::GMVIO::write_discontinuous_gmv(), libMesh::ExodusII_IO_Helper::write_nodal_coordinates(), libMesh::ExodusII_IO::write_nodal_data(), libMesh::VTKIO::write_nodal_data(), libMesh::System::write_parallel_data(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), and libMesh::XdrIO::write_serialized_nodesets().

◆ n_SCALAR_dofs()

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

Definition at line 786 of file dof_map.h.

786{ return _n_SCALAR_dofs; }

References _n_SCALAR_dofs.

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

◆ n_variable_groups()

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

Definition at line 733 of file dof_map.h.

734 { return cast_int<unsigned int>(_variable_groups.size()); }

References _variable_groups.

Referenced by has_blocked_representation(), libMesh::StaticCondensationDofMap::reinit(), reinit(), and set_nonlocal_dof_objects().

◆ n_variables()

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

Implements libMesh::DofMapBase.

Definition at line 736 of file dof_map.h.

737 { return cast_int<unsigned int>(_variables.size()); }

References _variables.

Referenced by block_size(), libMesh::FEGenericBase< OutputType >::coarsened_dof_values(), create_dof_constraints(), DMlibMeshSetSystem_libMesh(), has_blocked_representation(), libMesh::SparsityPattern::Build::operator()(), process_mesh_constraint_rows(), and var_group_from_var_number().

◆ n_vars()

unsigned int libMesh::DofMap::n_vars ( ) const
inline
Returns
The number of variables in the system

Definition at line 2937 of file dof_map.h.

2938{
2939 return cast_int<unsigned int>(_variables.size());
2940}

References _variables.

Referenced by allgather_recursive_constraints(), and create_dof_constraints().

◆ node_constraint_rows_begin()

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

Definition at line 1212 of file dof_map.h.

1213 { return _node_constraints.begin(); }

References _node_constraints.

◆ node_constraint_rows_end()

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

Definition at line 1218 of file dof_map.h.

1219 { return _node_constraints.end(); }

References _node_constraints.

◆ node_ptr()

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

Definition at line 303 of file dof_map.C.

304{
305 return mesh.node_ptr(i);
306}

References mesh.

◆ old_dof_indices() [1/2]

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

Appends to the vector di the old global degree of freedom indices for elem.node_ref(n), for one variable vn.

On hanging nodes with both vertex and non-vertex DoFs, only those indices which are directly supported on elem are included.

Definition at line 2478 of file dof_map.C.

2482{
2483 const DofObject & old_obj = elem.node_ref(n).get_old_dof_object_ref();
2484 this->_node_dof_indices(elem, n, old_obj, di, vn);
2485}

References libMesh::DofObject::get_old_dof_object_ref(), and libMesh::Elem::node_ref().

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

◆ old_dof_indices() [2/2]

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

After a mesh is refined and repartitioned it is possible that the _send_list will need to be augmented.

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

Definition at line 2694 of file dof_map.C.

2697{
2698 // dof_indices() is a relatively light-weight function; the cost of
2699 // the logging code itself is roughly on par with the time required
2700 // to call dof_indices().
2701 // LOG_SCOPE("old_dof_indices()", "DofMap");
2702
2703 libmesh_assert(elem);
2704
2705 const ElemType type = elem->type();
2706 const unsigned int sys_num = this->sys_number();
2707 const unsigned int n_var_groups = this->n_variable_groups();
2708#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2709 const bool is_inf = elem->infinite();
2710#endif
2711
2712 // If we have dof indices stored on the elem, and there's no chance
2713 // that we only have those indices because we were just p refined,
2714 // then we should have old dof indices too.
2715 libmesh_assert(!elem->has_dofs(sys_num) ||
2716 elem->p_refinement_flag() == Elem::JUST_REFINED ||
2717 elem->get_old_dof_object());
2718
2719 // Clear the DOF indices vector.
2720 di.clear();
2721
2722 // Determine the nodes contributing to element elem
2723 std::vector<const Node *> elem_nodes;
2724 const Node * const * nodes_ptr;
2725 unsigned int n_nodes;
2726 if (elem->type() == TRI3SUBDIVISION)
2727 {
2728 // Subdivision surface FE require the 1-ring around elem
2729 const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
2730 MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
2731 nodes_ptr = elem_nodes.data();
2732 n_nodes = cast_int<unsigned int>(elem_nodes.size());
2733 }
2734 else
2735 {
2736 // All other FE use only the nodes of elem itself
2737 nodes_ptr = elem->get_nodes();
2738 n_nodes = elem->n_nodes();
2739 }
2740
2741 // Get the dof numbers
2742 for (unsigned int vg=0; vg<n_var_groups; vg++)
2743 {
2744 const VariableGroup & var = this->variable_group(vg);
2745 const unsigned int vars_in_group = var.n_variables();
2746
2747 for (unsigned int vig=0; vig<vars_in_group; vig++)
2748 {
2749 const unsigned int v = var.number(vig);
2750 if ((vn == v) || (vn == libMesh::invalid_uint))
2751 {
2752 if (var.type().family == SCALAR &&
2753 (!elem ||
2754 var.active_on_subdomain(elem->subdomain_id())))
2755 {
2756 // We asked for this variable, so add it to the vector.
2757 std::vector<dof_id_type> di_new;
2758 this->SCALAR_dof_indices(di_new,v,true);
2759 di.insert( di.end(), di_new.begin(), di_new.end());
2760 }
2761 else
2762 if (var.active_on_subdomain(elem->subdomain_id()))
2763 { // Do this for all the variables if one was not specified
2764 // or just for the specified variable
2765
2766 FEType fe_type = var.type();
2767 const bool add_p_level = fe_type.p_refinement;
2768
2769 // Increase the polynomial order on p refined elements,
2770 // but make sure you get the right polynomial order for
2771 // the OLD degrees of freedom
2772 int p_adjustment = 0;
2773 if (elem->p_refinement_flag() == Elem::JUST_REFINED)
2774 {
2775 libmesh_assert_greater (elem->p_level(), 0);
2776 p_adjustment = -1;
2777 }
2778 else if (elem->p_refinement_flag() == Elem::JUST_COARSENED)
2779 {
2780 p_adjustment = 1;
2781 }
2782 p_adjustment *= add_p_level;
2783
2784 // Compute the net amount of "extra" order, including Elem::p_level()
2785 int extra_order = int(add_p_level*elem->p_level()) + p_adjustment;
2786
2787 const bool extra_hanging_dofs =
2789
2792
2793 // Get the node-based DOF numbers
2794 for (unsigned int n=0; n<n_nodes; n++)
2795 {
2796 const Node * node = nodes_ptr[n];
2797 const DofObject & old_dof_obj = node->get_old_dof_object_ref();
2798
2799 // There is a potential problem with h refinement. Imagine a
2800 // quad9 that has a linear FE on it. Then, on the hanging side,
2801 // it can falsely identify a DOF at the mid-edge node. This is why
2802 // we call FEInterface instead of node->n_comp() directly.
2803 const unsigned int nc =
2804#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2805 is_inf ?
2806 FEInterface::n_dofs_at_node(var.type(), extra_order, elem, n) :
2807#endif
2808 ndan (type, var.type().order + extra_order, n);
2809
2810 const int n_comp = old_dof_obj.n_comp_group(sys_num,vg);
2811
2812 // If this is a non-vertex on a hanging node with extra
2813 // degrees of freedom, we use the non-vertex dofs (which
2814 // come in reverse order starting from the end, to
2815 // simplify p refinement)
2816 if (extra_hanging_dofs && !elem->is_vertex(n))
2817 {
2818 const int dof_offset = n_comp - nc;
2819
2820 // We should never have fewer dofs than necessary on a
2821 // node unless we're getting indices on a parent element
2822 // or a just-coarsened element
2823 if (dof_offset < 0)
2824 {
2825 libmesh_assert(!elem->active() || elem->refinement_flag() ==
2827 di.resize(di.size() + nc, DofObject::invalid_id);
2828 }
2829 else
2830 for (int i=n_comp-1; i>=dof_offset; i--)
2831 {
2832 const dof_id_type d =
2833 old_dof_obj.dof_number(sys_num, vg, vig, i, n_comp);
2834
2835 // On a newly-expanded subdomain, we
2836 // may have some DoFs that didn't
2837 // exist in the old system, in which
2838 // case we can't assert this:
2839 // libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2840
2841 di.push_back(d);
2842 }
2843 }
2844 // If this is a vertex or an element without extra hanging
2845 // dofs, our dofs come in forward order coming from the
2846 // beginning. But we still might not have all
2847 // those dofs on the old_dof_obj, in cases
2848 // where a subdomain-restricted variable just
2849 // had its subdomain expanded.
2850 else
2851 {
2852 const unsigned int old_nc =
2853 std::min(static_cast<unsigned int>(n_comp), nc);
2854 for (unsigned int i=0; i != old_nc; ++i)
2855 {
2856 const dof_id_type d =
2857 old_dof_obj.dof_number(sys_num, vg, vig, i, n_comp);
2858
2859 libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2860
2861 di.push_back(d);
2862 }
2863 for (unsigned int i=old_nc; i != nc; ++i)
2864 di.push_back(DofObject::invalid_id);
2865 }
2866 }
2867
2868 // If there are any element-based DOF numbers, get them
2869 const unsigned int nc =
2870 FEInterface::n_dofs_per_elem(fe_type, extra_order, elem);
2871
2872 if (nc != 0)
2873 {
2874 const DofObject & old_dof_obj = elem->get_old_dof_object_ref();
2875
2876 const unsigned int n_comp =
2877 old_dof_obj.n_comp_group(sys_num,vg);
2878
2879 if (old_dof_obj.n_systems() > sys_num &&
2880 nc <= n_comp)
2881 {
2882
2883 for (unsigned int i=0; i<nc; i++)
2884 {
2885 const dof_id_type d =
2886 old_dof_obj.dof_number(sys_num, vg, vig, i, n_comp);
2887
2888 di.push_back(d);
2889 }
2890 }
2891 else
2892 {
2893 // We should never have fewer dofs than
2894 // necessary on an element unless we're
2895 // getting indices on a parent element, a
2896 // just-coarsened element ... or a
2897 // subdomain-restricted variable with a
2898 // just-expanded subdomain
2899 // libmesh_assert(!elem->active() || fe_type.family == LAGRANGE ||
2900 // elem->refinement_flag() == Elem::JUST_COARSENED);
2901 di.resize(di.size() + nc, DofObject::invalid_id);
2902 }
2903 }
2904 }
2905 }
2906 } // end loop over variables within group
2907 } // end loop over variable groups
2908}
@ JUST_COARSENED
Definition elem.h:1450

References libMesh::Elem::active(), libMesh::Variable::active_on_subdomain(), libMesh::DofObject::dof_number(), libMesh::FEType::family, libMesh::Elem::get_nodes(), libMesh::DofObject::get_old_dof_object(), libMesh::DofObject::get_old_dof_object_ref(), libMesh::DofObject::has_dofs(), libMesh::Elem::infinite(), int, libMesh::invalid_uint, libMesh::Elem::is_vertex(), libMesh::libmesh_assert(), libMesh::DofObject::n_comp_group(), libMesh::Elem::n_nodes(), n_nodes, libMesh::DofObject::n_systems(), libMesh::VariableGroup::n_variables(), libMesh::VariableGroup::number(), libMesh::FEType::order, libMesh::Elem::p_level(), libMesh::FEType::p_refinement, libMesh::Elem::p_refinement_flag(), libMesh::Elem::refinement_flag(), libMesh::SCALAR, libMesh::Elem::subdomain_id(), libMesh::TRI3SUBDIVISION, libMesh::Variable::type(), and libMesh::Elem::type().

◆ prepare_send_list()

void libMesh::DofMap::prepare_send_list ( )

Takes the _send_list vector (which may have duplicate entries) and sorts it.

The duplicate entries are then removed, resulting in a sorted _send_list with unique entries. Also calls any user-provided methods for adding to the send list.

Definition at line 1835 of file dof_map.C.

1836{
1837 LOG_SCOPE("prepare_send_list()", "DofMap");
1838
1839 // Return immediately if there's no ghost data
1840 if (this->n_processors() == 1)
1841 return;
1842
1843 // Check to see if we have any extra stuff to add to the send_list
1845 {
1847 {
1848 libmesh_here();
1849 libMesh::out << "WARNING: You have specified both an extra send list function and object.\n"
1850 << " Are you sure this is what you meant to do??"
1851 << std::endl;
1852 }
1853
1855 }
1856
1859
1860 // First sort the send list. After this
1861 // duplicated elements will be adjacent in the
1862 // vector
1863 std::sort(_send_list.begin(), _send_list.end());
1864
1865 // Now use std::unique to remove duplicate entries
1866 std::vector<dof_id_type>::iterator new_end =
1867 std::unique (_send_list.begin(), _send_list.end());
1868
1869 // Remove the end of the send_list. Use the "swap trick"
1870 // from Effective STL
1871 std::vector<dof_id_type> (_send_list.begin(), new_end).swap (_send_list);
1872
1873 // Make sure the send list has nothing invalid in it.
1874 libmesh_assert(_send_list.empty() || _send_list.back() < this->n_dofs());
1875}
virtual void augment_send_list(std::vector< dof_id_type > &send_list)=0
User-defined function to augment the send list.

References libMesh::libmesh_assert(), and libMesh::out.

Referenced by libMesh::PetscDMWrapper::init_petscdm(), and libMesh::System::reinit_constraints().

◆ print_dof_constraints()

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

Prints (from processor 0) all DoF and Node constraints.

If print_nonlocal is true, then each constraint is printed once for each processor that knows about it, which may be useful for DistributedMesh debugging.

Definition at line 2253 of file dof_map_constraints.C.

2255{
2256 parallel_object_only();
2257
2258 std::string local_constraints =
2259 this->get_local_constraints(print_nonlocal);
2260
2261 if (this->processor_id())
2262 {
2263 this->comm().send(0, local_constraints);
2264 }
2265 else
2266 {
2267 os << "Processor 0:\n";
2268 os << local_constraints;
2269
2270 for (auto p : IntRange<processor_id_type>(1, this->n_processors()))
2271 {
2272 this->comm().receive(p, local_constraints);
2273 os << "Processor " << p << ":\n";
2274 os << local_constraints;
2275 }
2276 }
2277}
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
std::string get_local_constraints(bool print_nonlocal=false) const
Gets a string reporting all DoF and Node constraints local to this processor.
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
Definition int_range.h:54

References libMesh::ParallelObject::comm(), get_local_constraints(), libMesh::ParallelObject::n_processors(), libMesh::ParallelObject::processor_id(), libMesh::Parallel::Communicator::receive(), and libMesh::Parallel::Communicator::send().

Referenced by main(), and libMesh::System::reinit_constraints().

◆ print_info() [1/2]

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

Prints summary info about the sparsity bandwidth and constraints.

Definition at line 2978 of file dof_map.C.

2979{
2980 os << this->get_info();
2981}
std::string get_info() const
Gets summary info about the sparsity bandwidth and constraints.
Definition dof_map.C:2985

◆ print_info() [2/2]

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

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

Definition at line 81 of file reference_counter.C.

82{
84 out_stream << ReferenceCounter::get_info();
85}
static std::string get_info()
Gets a string containing the reference information.

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

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

◆ process_constraints()

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

Postprocesses any constrained degrees of freedom to be constrained only in terms of unconstrained dofs, then adds unconstrained dofs to the send_list and prepares that for use.

This should be run after both system (create_dof_constraints) and user constraints have all been added.

Definition at line 4341 of file dof_map_constraints.C.

4342{
4343 // We've computed our local constraints, but they may depend on
4344 // non-local constraints that we'll need to take into account.
4346
4348 {
4349 // Optionally check for constraint loops and throw an error
4350 // if they're detected. We always do this check below in dbg/devel
4351 // mode but here we optionally do it in opt mode as well.
4353 }
4354
4355 // Adjoints will be constrained where the primal is
4356 // Therefore, we will expand the adjoint_constraint_values
4357 // map whenever the primal_constraint_values map is expanded
4358
4359 // First, figure out the total number of QoIs
4360 const unsigned int max_qoi_num =
4362 0 : _adjoint_constraint_values.rbegin()->first+1;
4363
4364 // Create a set containing the DOFs we already depend on
4365 typedef std::set<dof_id_type> RCSet;
4366 RCSet unexpanded_set;
4367
4368 for (const auto & i : _dof_constraints)
4369 unexpanded_set.insert(i.first);
4370
4371 while (!unexpanded_set.empty())
4372 for (RCSet::iterator i = unexpanded_set.begin();
4373 i != unexpanded_set.end(); /* nothing */)
4374 {
4375 // If the DOF is constrained
4376 DofConstraints::iterator
4377 pos = _dof_constraints.find(*i);
4378
4379 libmesh_assert (pos != _dof_constraints.end());
4380
4381 DofConstraintRow & constraint_row = pos->second;
4382
4383 DofConstraintValueMap::iterator rhsit =
4385 Number constraint_rhs = (rhsit == _primal_constraint_values.end()) ?
4386 0 : rhsit->second;
4387
4388 // A vector of DofConstraintValueMaps for each adjoint variable
4389 std::vector<DofConstraintValueMap::iterator> adjoint_rhs_iterators;
4390 adjoint_rhs_iterators.resize(max_qoi_num);
4391
4392 // Another to hold the adjoint constraint rhs
4393 std::vector<Number> adjoint_constraint_rhs(max_qoi_num, 0.0);
4394
4395 // Find and gather recursive constraints for each adjoint variable
4396 for (auto & adjoint_map : _adjoint_constraint_values)
4397 {
4398 const std::size_t q = adjoint_map.first;
4399 adjoint_rhs_iterators[q] = adjoint_map.second.find(*i);
4400
4401 adjoint_constraint_rhs[q] =
4402 (adjoint_rhs_iterators[q] == adjoint_map.second.end()) ?
4403 0 : adjoint_rhs_iterators[q]->second;
4404 }
4405
4406 std::vector<dof_id_type> constraints_to_expand;
4407
4408 for (const auto & item : constraint_row)
4409 if (item.first != *i && this->is_constrained_dof(item.first))
4410 {
4411 unexpanded_set.insert(item.first);
4412 constraints_to_expand.push_back(item.first);
4413 }
4414
4415 for (const auto & expandable : constraints_to_expand)
4416 {
4417 const Real this_coef = constraint_row[expandable];
4418
4419 DofConstraints::const_iterator
4420 subpos = _dof_constraints.find(expandable);
4421
4422 libmesh_assert (subpos != _dof_constraints.end());
4423
4424 const DofConstraintRow & subconstraint_row = subpos->second;
4425
4426 for (const auto & item : subconstraint_row)
4427 {
4428 // Assert that the constraint does not form a cycle.
4429 libmesh_assert(item.first != expandable);
4430 constraint_row[item.first] += item.second * this_coef;
4431 }
4432
4433 if (auto subrhsit = _primal_constraint_values.find(expandable);
4434 subrhsit != _primal_constraint_values.end())
4435 constraint_rhs += subrhsit->second * this_coef;
4436
4437 // Find and gather recursive constraints for each adjoint variable
4438 for (const auto & adjoint_map : _adjoint_constraint_values)
4439 {
4440 if (auto adjoint_subrhsit = adjoint_map.second.find(expandable);
4441 adjoint_subrhsit != adjoint_map.second.end())
4442 adjoint_constraint_rhs[adjoint_map.first] += adjoint_subrhsit->second * this_coef;
4443 }
4444
4445 constraint_row.erase(expandable);
4446 }
4447
4448 if (rhsit == _primal_constraint_values.end())
4449 {
4450 if (constraint_rhs != Number(0))
4451 _primal_constraint_values[*i] = constraint_rhs;
4452 else
4453 _primal_constraint_values.erase(*i);
4454 }
4455 else
4456 {
4457 if (constraint_rhs != Number(0))
4458 rhsit->second = constraint_rhs;
4459 else
4460 _primal_constraint_values.erase(rhsit);
4461 }
4462
4463 // Finally fill in the adjoint constraints for each adjoint variable if possible
4464 for (auto & adjoint_map : _adjoint_constraint_values)
4465 {
4466 const std::size_t q = adjoint_map.first;
4467
4468 if(adjoint_rhs_iterators[q] == adjoint_map.second.end())
4469 {
4470 if (adjoint_constraint_rhs[q] != Number(0))
4471 (adjoint_map.second)[*i] = adjoint_constraint_rhs[q];
4472 else
4473 adjoint_map.second.erase(*i);
4474 }
4475 else
4476 {
4477 if (adjoint_constraint_rhs[q] != Number(0))
4478 adjoint_rhs_iterators[q]->second = adjoint_constraint_rhs[q];
4479 else
4480 adjoint_map.second.erase(adjoint_rhs_iterators[q]);
4481 }
4482 }
4483
4484 if (constraints_to_expand.empty())
4485 i = unexpanded_set.erase(i);
4486 else
4487 ++i;
4488 }
4489
4490 // In parallel we can't guarantee that nodes/dofs which constrain
4491 // others are on processors which are aware of that constraint, yet
4492 // we need such awareness for sparsity pattern generation. So send
4493 // other processors any constraints they might need to know about.
4494 this->scatter_constraints(mesh);
4495
4496 // Now that we have our root constraint dependencies sorted out, add
4497 // them to the send_list
4499}
void add_constraints_to_send_list()
Adds entries to the _send_list vector corresponding to DoFs which are dependencies for constraint equ...
void allgather_recursive_constraints(MeshBase &)
Gathers constraint equation dependencies from other processors.
void scatter_constraints(MeshBase &)
Sends constraint equations to constraining processors.

References _adjoint_constraint_values, _dof_constraints, _error_on_constraint_loop, _primal_constraint_values, add_constraints_to_send_list(), allgather_recursive_constraints(), check_for_constraint_loops(), libMesh::libmesh_assert(), libMesh::Real, and scatter_constraints().

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

◆ process_mesh_constraint_rows()

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

Adds any spline constraints from the Mesh to our DoF constraints.

If any Dirichlet constraints exist on spline-constrained nodes, l2-projects those constraints onto the spline basis.

Definition at line 1898 of file dof_map_constraints.C.

1899{
1900 // If we already have simple Dirichlet constraints (with right hand
1901 // sides but with no coupling between DoFs) on spline-constrained FE
1902 // nodes, then we'll need a solve to compute the corresponding
1903 // constraints on the relevant spline nodes. (If we already have
1904 // constraints with coupling between DoFs on spline-constrained FE
1905 // nodes, then we'll need to go sit down and cry until we figure out
1906 // how to handle that.)
1907
1908 const auto & constraint_rows = mesh.get_constraint_rows();
1909
1910 // This routine is too expensive to use unless we really might
1911 // need it
1912#ifdef DEBUG
1913 bool constraint_rows_empty = constraint_rows.empty();
1914 this->comm().min(constraint_rows_empty);
1915 libmesh_assert(!constraint_rows_empty);
1916#endif
1917
1918 // We can't handle periodic boundary conditions on spline meshes
1919 // yet.
1920#ifdef LIBMESH_ENABLE_PERIODIC
1921 libmesh_error_msg_if (!_periodic_boundaries->empty(),
1922 "Periodic boundary conditions are not yet implemented for spline meshes");
1923#endif
1924
1925 // We can handle existing Dirichlet constraints, but we'll need
1926 // to do solves to project them down onto the spline basis.
1927 std::unique_ptr<SparsityPattern::Build> sp;
1928 std::unique_ptr<SparseMatrix<Number>> mat;
1929
1930 const unsigned int n_adjoint_rhs =
1932
1933 // [0] for primal rhs, [q+1] for adjoint qoi q
1934 std::vector<std::unique_ptr<NumericVector<Number>>>
1935 solve_rhs(n_adjoint_rhs+1);
1936
1937 // Keep track of which spline DoFs will be Dirichlet.
1938 // We use a set here to make it easier to find what processors
1939 // to send the DoFs to later.
1940 std::set<dof_id_type> my_dirichlet_spline_dofs;
1941
1942 // And keep track of which non-spline Dofs were Dirichlet
1943 std::unordered_set<dof_id_type> was_previously_constrained;
1944
1945 const unsigned int sys_num = this->sys_number();
1946 for (auto & node_row : constraint_rows)
1947 {
1948 const Node * node = node_row.first;
1949 libmesh_assert(node == mesh.node_ptr(node->id()));
1950
1951 // Each processor only computes its own (and in distributed
1952 // cases, is only guaranteed to have the dependency data to
1953 // compute its own) constraints here.
1954 if (node->processor_id() != mesh.processor_id())
1955 continue;
1956
1957 for (auto var_num : IntRange<unsigned int>(0, this->n_variables()))
1958 {
1959 const FEFamily & fe_family = this->variable_type(var_num).family;
1960
1961 // constraint_rows only applies to nodal variables
1962 if (fe_family != LAGRANGE &&
1963 fe_family != RATIONAL_BERNSTEIN)
1964 continue;
1965
1966 DofConstraintRow dc_row;
1967
1968 const dof_id_type constrained_id =
1969 node->dof_number(sys_num, var_num, 0);
1970 for (const auto & [pr, val] : node_row.second)
1971 {
1972 const Elem * spline_elem = pr.first;
1973 libmesh_assert(spline_elem == mesh.elem_ptr(spline_elem->id()));
1974
1975 const Node & spline_node =
1976 spline_elem->node_ref(pr.second);
1977
1978 const dof_id_type spline_dof_id =
1979 spline_node.dof_number(sys_num, var_num, 0);
1980 dc_row[spline_dof_id] = val;
1981 }
1982
1983 // See if we already have a constraint here.
1984 if (this->is_constrained_dof(constrained_id))
1985 {
1986 was_previously_constrained.insert(constrained_id);
1987
1988 // Keep track of which spline DoFs will be
1989 // inheriting this non-spline DoF's constraints
1990 for (auto & row_entry : dc_row)
1991 my_dirichlet_spline_dofs.insert(row_entry.first);
1992
1993 // If it wasn't a simple Dirichlet-type constraint
1994 // then I don't know what to do with it. We'll make
1995 // this an assertion only because this should only
1996 // crop up with periodic boundary conditions, which
1997 // we've already made sure we don't have.
1998 libmesh_assert(_dof_constraints[constrained_id].empty());
1999 }
2000
2001 // Add the constraint, replacing any previous, so we can
2002 // use the new constraint in setting up the solve below
2003 this->add_constraint_row(constrained_id, dc_row, false);
2004 }
2005 }
2006
2007 // my_dirichlet_spline_dofs may now include DoFs whose owners
2008 // don't know they need to become spline DoFs! We need to push
2009 // this data to them.
2010 if (this->comm().size() > 1)
2011 {
2012 std::unordered_map
2013 <processor_id_type, std::vector<dof_id_type>>
2014 their_dirichlet_spline_dofs;
2015
2016 // If we ever change the underlying container here then we'd
2017 // better do some kind of sort before using it; we'll rely
2018 // on sorting to make the processor id lookup efficient.
2019 libmesh_assert(std::is_sorted(my_dirichlet_spline_dofs.begin(),
2020 my_dirichlet_spline_dofs.end()));
2021 processor_id_type destination_pid = 0;
2022 for (auto d : my_dirichlet_spline_dofs)
2023 {
2024 libmesh_assert_less(d, this->end_dof(this->comm().size()-1));
2025 while (d >= this->end_dof(destination_pid))
2026 destination_pid++;
2027
2028 if (destination_pid != this->processor_id())
2029 their_dirichlet_spline_dofs[destination_pid].push_back(d);
2030 }
2031
2032 auto receive_dof_functor =
2033 [& my_dirichlet_spline_dofs]
2035 const std::vector<dof_id_type> & dofs)
2036 {
2037 my_dirichlet_spline_dofs.insert(dofs.begin(), dofs.end());
2038 };
2039
2041 (this->comm(), their_dirichlet_spline_dofs, receive_dof_functor);
2042 }
2043
2044
2045 // If anyone had any prior constraints in effect, then we need
2046 // to convert them to constraints on the spline nodes.
2047 //
2048 // NOT simply testing prior_constraints here; maybe it turned
2049 // out that all our constraints were on non-spline-constrained
2050 // parts of a hybrid mesh?
2051 bool important_prior_constraints =
2052 !was_previously_constrained.empty();
2053 this->comm().max(important_prior_constraints);
2054
2055 if (important_prior_constraints)
2056 {
2057 // Now that we have the spline constraints added, we can
2058 // finally construct a sparsity pattern that correctly
2059 // accounts for those constraints!
2060 mat = SparseMatrix<Number>::build(this->comm());
2061 for (auto q : IntRange<unsigned int>(0, n_adjoint_rhs+1))
2062 {
2063 solve_rhs[q] = NumericVector<Number>::build(this->comm());
2064 solve_rhs[q]->init(this->n_dofs(), this->n_local_dofs(),
2065 false, PARALLEL);
2066 }
2067
2068 // We need to compute our own sparsity pattern, to take into
2069 // account the particularly non-sparse rows that can be
2070 // created by the spline constraints we just added.
2071 mat->attach_dof_map(*this);
2072 sp = this->build_sparsity(mesh);
2073 mat->attach_sparsity_pattern(*sp);
2074 mat->init();
2075
2076 for (auto & node_row : constraint_rows)
2077 {
2078 const Node * node = node_row.first;
2079 libmesh_assert(node == mesh.node_ptr(node->id()));
2080
2081 for (auto var_num : IntRange<unsigned int>(0, this->n_variables()))
2082 {
2083 const FEFamily & fe_family = this->variable_type(var_num).family;
2084
2085 // constraint_rows only applies to nodal variables
2086 if (fe_family != LAGRANGE &&
2087 fe_family != RATIONAL_BERNSTEIN)
2088 continue;
2089
2090 const dof_id_type constrained_id =
2091 node->dof_number(sys_num, var_num, 0);
2092
2093 if (was_previously_constrained.count(constrained_id))
2094 {
2095 for (auto q : IntRange<int>(0, n_adjoint_rhs+1))
2096 {
2097 DenseMatrix<Number> K(1,1);
2099 std::vector<dof_id_type> dof_indices(1, constrained_id);
2100
2101 K(0,0) = 1;
2102
2103 DofConstraintValueMap & vals = q ?
2106
2107 DofConstraintValueMap::const_iterator rhsit =
2108 vals.find(constrained_id);
2109 F(0) = (rhsit == vals.end()) ? 0 : rhsit->second;
2110
2111 // We no longer need any rhs values here directly.
2112 if (rhsit != vals.end())
2113 vals.erase(rhsit);
2114
2116 (K, F, dof_indices, false, q ? (q-1) : -1);
2117 if (!q)
2118 mat->add_matrix(K, dof_indices);
2119 solve_rhs[q]->add_vector(F, dof_indices);
2120 }
2121 }
2122 }
2123 }
2124
2125 // Any DoFs that aren't part of any constraint, directly or
2126 // indirectly, need a diagonal term to make the matrix
2127 // here invertible.
2128 for (dof_id_type d : IntRange<dof_id_type>(this->first_dof(),
2129 this->end_dof()))
2130 if (!was_previously_constrained.count(d) &&
2131 !my_dirichlet_spline_dofs.count(d))
2132 mat->add(d,d,1);
2133
2134 // At this point, we're finally ready to solve for Dirichlet
2135 // constraint values on spline nodes.
2136 std::unique_ptr<LinearSolver<Number>> linear_solver =
2138
2139 std::unique_ptr<NumericVector<Number>> projected_vals =
2141
2142 projected_vals->init(this->n_dofs(), this->n_local_dofs(),
2143 false, PARALLEL);
2144
2145 DofConstraintRow empty_row;
2146 for (auto sd : my_dirichlet_spline_dofs)
2147 if (this->local_index(sd))
2148 this->add_constraint_row(sd, empty_row);
2149
2150 for (auto q : IntRange<unsigned int>(0, n_adjoint_rhs+1))
2151 {
2152 // FIXME: we don't have an EquationSystems here, but I'd
2153 // rather not hardcode these...
2154 const double tol = double(TOLERANCE * TOLERANCE);
2155 const unsigned int max_its = 5000;
2156
2157 linear_solver->solve(*mat, *projected_vals,
2158 *(solve_rhs[q]), tol, max_its);
2159
2160 DofConstraintValueMap & vals = q ?
2163
2164 for (auto sd : my_dirichlet_spline_dofs)
2165 if (this->local_index(sd))
2166 {
2167 Number constraint_rhs = (*projected_vals)(sd);
2168
2169 std::pair<DofConstraintValueMap::iterator, bool> rhs_it =
2170 vals.emplace(sd, constraint_rhs);
2171 if (!rhs_it.second)
2172 rhs_it.first->second = constraint_rhs;
2173 }
2174 }
2175 }
2176}
This is the base class from which all geometric element types are derived.
Definition elem.h:96
FEFamily family
The type of finite element.
Definition fe_type.h:228
static std::unique_ptr< LinearSolver< T > > build(const libMesh::Parallel::Communicator &comm_in, const SolverPackage solver_package=libMesh::default_solver_package())
Builds a LinearSolver using the linear solver package specified by solver_package.
virtual const Elem * elem_ptr(const dof_id_type i) const =0
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, SolverPackage solver_package=libMesh::default_solver_package(), ParallelType parallel_type=AUTOMATIC)
Builds a NumericVector on the processors in communicator comm using the linear solver package specifi...
static std::unique_ptr< SparseMatrix< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package(), const MatrixBuildType matrix_build_type=MatrixBuildType::AUTOMATIC)
Builds a SparseMatrix<T> using the linear solver package specified by solver_package.
static constexpr Real TOLERANCE
@ RATIONAL_BERNSTEIN

References _adjoint_constraint_values, _dof_constraints, _periodic_boundaries, _primal_constraint_values, add_constraint_row(), libMesh::LinearSolver< T >::build(), libMesh::SparseMatrix< T >::build(), libMesh::NumericVector< T >::build(), build_sparsity(), libMesh::ParallelObject::comm(), dof_indices(), libMesh::DofObject::dof_number(), libMesh::MeshBase::elem_ptr(), libMesh::DofMapBase::end_dof(), libMesh::FEType::family, libMesh::DofMapBase::first_dof(), libMesh::MeshBase::get_constraint_rows(), heterogeneously_constrain_element_matrix_and_vector(), libMesh::DofObject::id(), is_constrained_dof(), libMesh::LAGRANGE, libMesh::libmesh_assert(), local_index(), libMesh::Parallel::Communicator::max(), mesh, libMesh::Parallel::Communicator::min(), n_dofs(), n_local_dofs(), n_variables(), libMesh::MeshBase::node_ptr(), libMesh::Elem::node_ref(), libMesh::PARALLEL, libMesh::DofObject::processor_id(), libMesh::ParallelObject::processor_id(), TIMPI::push_parallel_vector_data(), libMesh::RATIONAL_BERNSTEIN, sys_number(), libMesh::TOLERANCE, and variable_type().

Referenced by create_dof_constraints().

◆ processor_id()

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

Definition at line 114 of file parallel_object.h.

115 { return cast_int<processor_id_type>(_communicator.rank()); }
processor_id_type rank() const

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

Referenced by libMesh::BoundaryInfo::_find_id_maps(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::DistributedMesh::add_elem(), libMesh::BoundaryInfo::add_elements(), libMesh::DistributedMesh::add_node(), libMesh::MeshTools::Modification::all_tri(), libMesh::FEMSystem::assembly(), libMesh::Nemesis_IO::assert_symmetric_cmaps(), libMesh::Partitioner::assign_partitioning(), libMesh::Nemesis_IO_Helper::build_element_and_node_maps(), libMesh::Partitioner::build_graph(), libMesh::InfElemBuilder::build_inf_elem(), libMesh::BoundaryInfo::build_node_list_from_side_list(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::EquationSystems::build_parallel_solution_vector(), libMesh::MeshFunction::check_found_elem(), libMesh::DistributedMesh::clear(), libMesh::DistributedMesh::clear_elems(), libMesh::ExodusII_IO_Helper::close(), libMesh::Nemesis_IO_Helper::compute_border_node_ids(), libMesh::Nemesis_IO_Helper::compute_communication_map_parameters(), libMesh::Nemesis_IO_Helper::compute_internal_and_border_elems_and_internal_nodes(), libMesh::RBConstruction::compute_max_error_bound(), libMesh::Nemesis_IO_Helper::compute_node_communication_maps(), libMesh::Nemesis_IO_Helper::compute_num_global_elem_blocks(), libMesh::Nemesis_IO_Helper::compute_num_global_nodesets(), libMesh::Nemesis_IO_Helper::compute_num_global_sidesets(), libMesh::Nemesis_IO_Helper::construct_nemesis_filename(), libMesh::ExodusII_IO::copy_elemental_solution(), libMesh::ExodusII_IO::copy_nodal_solution(), libMesh::ExodusII_IO::copy_scalar_solution(), libMesh::Nemesis_IO::copy_scalar_solution(), libMesh::MeshTools::correct_node_proc_ids(), libMesh::ExodusII_IO_Helper::create(), libMesh::MeshCommunication::delete_remote_elements(), libMesh::DistributedMesh::DistributedMesh(), libMesh::DistributedMesh::DistributedMesh(), libMesh::DofMapBase::end_dof(), libMesh::DofMapBase::end_old_dof(), libMesh::EnsightIO::EnsightIO(), libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::find_dofs_to_send(), libMesh::UnstructuredMesh::find_neighbors(), libMesh::DofMapBase::first_dof(), libMesh::DofMapBase::first_old_dof(), libMesh::RBEIMEvaluation::gather_bfs(), libMesh::Nemesis_IO_Helper::get_cmap_params(), libMesh::Nemesis_IO_Helper::get_eb_info_global(), libMesh::Nemesis_IO_Helper::get_elem_cmap(), libMesh::Nemesis_IO_Helper::get_elem_map(), libMesh::MeshBase::get_info(), libMesh::Nemesis_IO_Helper::get_init_global(), libMesh::Nemesis_IO_Helper::get_init_info(), libMesh::RBEIMEvaluation::get_interior_basis_functions_as_vecs(), libMesh::Nemesis_IO_Helper::get_loadbal_param(), get_local_constraints(), libMesh::MeshBase::get_local_constraints(), libMesh::Nemesis_IO_Helper::get_node_cmap(), libMesh::Nemesis_IO_Helper::get_node_map(), libMesh::Nemesis_IO_Helper::get_ns_param_global(), libMesh::Nemesis_IO_Helper::get_ss_param_global(), libMesh::SparsityPattern::Build::handle_vi_vj(), libMesh::LaplaceMeshSmoother::init(), libMesh::SystemSubsetBySubdomain::init(), HeatSystem::init_data(), libMesh::ExodusII_IO_Helper::initialize(), libMesh::ExodusII_IO_Helper::initialize_element_variables(), libMesh::ExodusII_IO_Helper::initialize_global_variables(), libMesh::ExodusII_IO_Helper::initialize_nodal_variables(), libMesh::DistributedMesh::insert_elem(), libMesh::MeshTools::Modification::interpolate_surface(), libMesh::SparsityPattern::Build::join(), libMesh::RBEvaluation::legacy_write_offline_data_to_files(), libMesh::RBSCMEvaluation::legacy_write_offline_data_to_files(), libMesh::TransientRBEvaluation::legacy_write_offline_data_to_files(), libMesh::MeshTools::libmesh_assert_consistent_distributed(), libMesh::MeshTools::libmesh_assert_consistent_distributed_nodes(), libMesh::MeshTools::libmesh_assert_contiguous_dof_ids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Elem >(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_object_ids(), main(), AugmentSparsityOnInterface::mesh_reinit(), libMesh::TriangulatorInterface::MeshedHole::MeshedHole(), libMesh::MeshBase::n_active_local_elem(), libMesh::BoundaryInfo::n_boundary_conds(), libMesh::MeshTools::n_connected_components(), libMesh::MeshBase::n_constraint_rows(), libMesh::BoundaryInfo::n_edge_conds(), libMesh::DofMapBase::n_local_dofs(), libMesh::MeshBase::n_local_elem(), libMesh::MeshBase::n_local_nodes(), libMesh::BoundaryInfo::n_nodeset_conds(), libMesh::BoundaryInfo::n_shellface_conds(), libMesh::RBEIMEvaluation::node_gather_bfs(), libMesh::DistributedMesh::own_node(), libMesh::BoundaryInfo::parallel_sync_node_ids(), libMesh::BoundaryInfo::parallel_sync_side_ids(), libMesh::MeshBase::print_constraint_rows(), print_dof_constraints(), process_mesh_constraint_rows(), libMesh::Nemesis_IO_Helper::put_cmap_params(), libMesh::Nemesis_IO_Helper::put_elem_cmap(), libMesh::Nemesis_IO_Helper::put_elem_map(), libMesh::Nemesis_IO_Helper::put_loadbal_param(), libMesh::Nemesis_IO_Helper::put_node_cmap(), libMesh::Nemesis_IO_Helper::put_node_map(), libMesh::XdrIO::read(), libMesh::Nemesis_IO::read(), libMesh::CheckpointIO::read(), libMesh::NameBasedIO::read(), libMesh::EquationSystems::read(), libMesh::EquationSystems::read(), libMesh::ExodusII_IO_Helper::read_elem_num_map(), libMesh::ExodusII_IO_Helper::read_global_values(), libMesh::CheckpointIO::read_header(), libMesh::ExodusII_IO::read_header(), libMesh::System::read_header(), libMesh::XdrIO::read_header(), libMesh::DynaIO::read_mesh(), libMesh::ExodusII_IO_Helper::read_node_num_map(), libMesh::System::read_parallel_data(), libMesh::RBConstruction::read_riesz_representors_from_files(), libMesh::TransientRBConstruction::read_riesz_representors_from_files(), libMesh::System::read_SCALAR_dofs(), libMesh::XdrIO::read_serialized_bc_names(), libMesh::XdrIO::read_serialized_bcs_helper(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::System::read_serialized_data(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::System::read_serialized_vector(), libMesh::System::read_serialized_vectors(), libMesh::Nemesis_IO_Helper::read_var_names_impl(), libMesh::SimplexRefiner::refine_via_edges(), libMesh::SimplexRefiner::refine_via_edges(), libMesh::StaticCondensationDofMap::reinit(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::DistributedMesh::renumber_nodes_and_elements(), scatter_constraints(), libMesh::CheckpointIO::select_split_config(), libMesh::DistributedMesh::set_next_unique_id(), set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), libMesh::RBEIMEvaluation::side_gather_bfs(), MeshFunctionTest::test_bad_gradient_var_with_out_of_mesh_value(), MeshFunctionTest::test_bad_hessian_var_with_out_of_mesh_value(), ExodusTest< elem_type >::test_read_gold(), ExodusTest< elem_type >::test_write(), ExodusC0PolyhedronTest::test_write_and_read_hexagonal_prism(), ExodusC0PolygonTest::test_write_and_read_pentagon(), MeshInputTest::testAbaqusRead(), MeshInputTest::testBadGmsh(), BoundaryInfoTest::testBoundaryIDs(), MeshInputTest::testCopyElementSolutionImpl(), MeshInputTest::testCopyElementVectorImpl(), MeshInputTest::testCopyNodalSolutionImpl(), DefaultCouplingTest::testCoupling(), PointNeighborCouplingTest::testCoupling(), MeshInputTest::testDynaFileMappings(), MeshInputTest::testDynaNoSplines(), MeshInputTest::testDynaReadElem(), MeshInputTest::testDynaReadPatch(), MeshInputTest::testExodusFileMappings(), MeshInputTest::testExodusIGASidesets(), MeshInputTest::testExodusWriteElementDataFromDiscontinuousNodalData(), MeshInputTest::testGmshBCIDOverlap(), MeshInputTest::testGoodGmsh(), MeshInputTest::testGoodSTL(), MeshInputTest::testGoodSTLBinary(), BoundaryInfoTest::testInternalBoundary(), MeshInputTest::testLowOrderEdgeBlocks(), BoundaryMeshSubdomainTest::testPerBoundarySubdomain(), SystemsTest::testProjectMatrix3D(), BoundaryInfoTest::testShellFaceConstraints(), MeshInputTest::testSingleElementImpl(), BoundaryMeshSubdomainTest::testSingleSubdomain(), WriteVecAndScalar::testSolution(), CheckpointIOTest::testSplitter(), MeshInputTest::testTetgenIO(), MeshSmootherTest::testVariationalSmoother(), libMesh::MeshTools::total_weight(), libMesh::NetGenMeshInterface::triangulate(), libMesh::Parallel::Packing< Elem * >::unpack(), libMesh::Parallel::Packing< Node * >::unpack(), libMesh::DistributedMesh::update_parallel_id_counts(), libMesh::DTKAdapter::update_variable_values(), libMesh::MeshTools::volume(), libMesh::STLIO::write(), libMesh::XdrIO::write(), libMesh::NameBasedIO::write(), libMesh::CheckpointIO::write(), libMesh::EquationSystems::write(), libMesh::EquationSystems::write(), libMesh::GMVIO::write_discontinuous_gmv(), libMesh::ExodusII_IO::write_element_data(), libMesh::ExodusII_IO::write_element_data_from_discontinuous_nodal_data(), libMesh::ExodusII_IO_Helper::write_element_values(), libMesh::ExodusII_IO_Helper::write_element_values_element_major(), libMesh::ExodusII_IO_Helper::write_elements(), libMesh::ExodusII_IO_Helper::write_elemset_data(), libMesh::ExodusII_IO_Helper::write_elemsets(), libMesh::ExodusII_IO::write_global_data(), libMesh::ExodusII_IO_Helper::write_global_values(), libMesh::System::write_header(), libMesh::ExodusII_IO::write_information_records(), libMesh::ExodusII_IO_Helper::write_information_records(), libMesh::ExodusII_IO_Helper::write_nodal_coordinates(), libMesh::ExodusII_IO::write_nodal_data(), libMesh::VTKIO::write_nodal_data(), libMesh::UCDIO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data_common(), libMesh::ExodusII_IO::write_nodal_data_discontinuous(), libMesh::ExodusII_IO_Helper::write_nodal_values(), libMesh::ExodusII_IO_Helper::write_nodeset_data(), libMesh::ExodusII_IO_Helper::write_nodesets(), libMesh::Nemesis_IO_Helper::write_nodesets(), libMesh::RBEIMEvaluation::write_out_interior_basis_functions(), libMesh::RBEIMEvaluation::write_out_node_basis_functions(), libMesh::RBEIMEvaluation::write_out_side_basis_functions(), write_output_solvedata(), libMesh::System::write_parallel_data(), libMesh::RBConstruction::write_riesz_representors_to_files(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bc_names(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::System::write_serialized_data(), libMesh::XdrIO::write_serialized_nodes(), libMesh::XdrIO::write_serialized_nodesets(), libMesh::XdrIO::write_serialized_subdomain_names(), libMesh::System::write_serialized_vector(), libMesh::System::write_serialized_vectors(), libMesh::ExodusII_IO_Helper::write_sideset_data(), libMesh::ExodusII_IO_Helper::write_sidesets(), libMesh::Nemesis_IO_Helper::write_sidesets(), libMesh::ExodusII_IO::write_timestep(), libMesh::ExodusII_IO_Helper::write_timestep(), and libMesh::ExodusII_IO::write_timestep_discontinuous().

◆ reinit()

void libMesh::DofMap::reinit ( MeshBase mesh,
const std::map< const Node *, std::set< subdomain_id_type > > &  constraining_subdomains 
)

Reinitialize the underlying data structures conformal to the current mesh.

Definition at line 468 of file dof_map.C.

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

References _default_coupling, _dof_coupling, libMesh::CouplingMatrix::empty(), libMesh::libmesh_assert(), mesh, n_variable_groups(), libMesh::Threads::parallel_for(), sys_number(), and use_coupled_neighbor_dofs().

Referenced by libMesh::HPCoarsenTest::add_projection().

◆ reinit_send_list()

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

Clears the _send_list vector and then rebuilds it.

This may be needed in special situations, for example when an algebraic coupling functor cannot be added to the DofMap until after it is completely setup. Then this method can be used to rebuild the send_list once the algebraic coupling functor is added. Note that while this will recommunicate constraints with the updated send_list, this does assume no new constraints have been added since the previous reinit_constraints call.

Definition at line 1877 of file dof_map.C.

1878{
1879 this->clear_send_list();
1881
1882#ifdef LIBMESH_ENABLE_CONSTRAINTS
1883 // This is assuming that we only need to recommunicate
1884 // the constraints and no new ones have been added since
1885 // a previous call to reinit_constraints.
1887#endif
1888 this->prepare_send_list();
1889}
void prepare_send_list()
Takes the _send_list vector (which may have duplicate entries) and sorts it.
Definition dof_map.C:1835
void process_constraints(MeshBase &)
Postprocesses any constrained degrees of freedom to be constrained only in terms of unconstrained dof...

References mesh.

Referenced by OverlappingAlgebraicGhostingTest::run_ghosting_test(), and OverlappingCouplingGhostingTest::run_sparsity_pattern_test().

◆ reinit_static_condensation()

void libMesh::DofMap::reinit_static_condensation ( )

Calls reinit on the static condensation map if it exists.

Definition at line 3140 of file dof_map.C.

3141{
3142 if (_sc)
3143 _sc->reinit();
3144}

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

◆ remove_adjoint_dirichlet_boundary()

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

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

Definition at line 5499 of file dof_map_constraints.C.

5501{
5502 libmesh_assert_greater(_adjoint_dirichlet_boundaries.size(),
5503 qoi_index);
5504
5505 auto lam = [&boundary_to_remove](const auto & bdy)
5506 {return bdy->b == boundary_to_remove.b && bdy->variables == boundary_to_remove.variables;};
5507
5508 auto it = std::find_if(_adjoint_dirichlet_boundaries[qoi_index]->begin(),
5509 _adjoint_dirichlet_boundaries[qoi_index]->end(),
5510 lam);
5511
5512 // Assert it was actually found and remove it from the vector
5513 libmesh_assert (it != _adjoint_dirichlet_boundaries[qoi_index]->end());
5514 _adjoint_dirichlet_boundaries[qoi_index]->erase(it);
5515}

References _adjoint_dirichlet_boundaries, libMesh::DirichletBoundary::b, libMesh::libmesh_assert(), and libMesh::DirichletBoundary::variables.

◆ remove_algebraic_ghosting_functor()

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

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

Definition at line 2089 of file dof_map.C.

2090{
2091 auto raw_it = std::find(_algebraic_ghosting_functors.begin(),
2093 &evaluable_functor);
2094
2095#ifndef LIBMESH_ENABLE_DEPRECATED
2096 // We shouldn't be trying to remove a functor that isn't there
2098#else
2099 // Our old API supported trying to remove a functor that isn't there
2100 if (raw_it != _algebraic_ghosting_functors.end())
2101#endif
2102 _algebraic_ghosting_functors.erase(raw_it);
2103
2104 // We shouldn't have had two copies of the same functor
2107 &evaluable_functor) ==
2109
2110 _mesh.remove_ghosting_functor(evaluable_functor);
2111
2112 if (const auto it = _shared_functors.find(&evaluable_functor);
2113 it != _shared_functors.end())
2114 _shared_functors.erase(it);
2115}

References libMesh::libmesh_assert().

Referenced by PointNeighborCouplingTest::testCoupling().

◆ remove_coupling_functor()

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

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

Definition at line 2032 of file dof_map.C.

2033{
2034 auto raw_it = std::find(_coupling_functors.begin(),
2035 _coupling_functors.end(), &coupling_functor);
2036
2037#ifndef LIBMESH_ENABLE_DEPRECATED
2038 // We shouldn't be trying to remove a functor that isn't there
2039 libmesh_assert(raw_it != _coupling_functors.end());
2040#else
2041 // Our old API supported trying to remove a functor that isn't there
2042 if (raw_it != _coupling_functors.end())
2043#endif
2044 _coupling_functors.erase(raw_it);
2045
2046 // We shouldn't have had two copies of the same functor
2047 libmesh_assert(std::find(_coupling_functors.begin(),
2048 _coupling_functors.end(),
2049 &coupling_functor) ==
2050 _coupling_functors.end());
2051
2052 _mesh.remove_ghosting_functor(coupling_functor);
2053
2054 if (const auto it = _shared_functors.find(&coupling_functor);
2055 it != _shared_functors.end())
2056 _shared_functors.erase(it);
2057}

References libMesh::libmesh_assert().

Referenced by PointNeighborCouplingTest::testCoupling().

◆ remove_default_ghosting()

void libMesh::DofMap::remove_default_ghosting ( )

Remove any default ghosting functor(s).

User-added ghosting functors will be unaffected.

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

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

Definition at line 1988 of file dof_map.C.

1989{
1992}
void remove_coupling_functor(GhostingFunctor &coupling_functor)
Removes a functor which was previously added to the set of coupling functors, from both this DofMap a...
Definition dof_map.C:2032
void remove_algebraic_ghosting_functor(GhostingFunctor &evaluable_functor)
Removes a functor which was previously added to the set of algebraic ghosting functors,...
Definition dof_map.C:2089

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

◆ remove_dirichlet_boundary()

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

Removes the specified Dirichlet boundary from the system.

Definition at line 5485 of file dof_map_constraints.C.

5486{
5487 // Find a boundary condition matching the one to be removed
5488 auto lam = [&boundary_to_remove](const auto & bdy)
5489 {return bdy->b == boundary_to_remove.b && bdy->variables == boundary_to_remove.variables;};
5490
5491 auto it = std::find_if(_dirichlet_boundaries->begin(), _dirichlet_boundaries->end(), lam);
5492
5493 // Assert it was actually found and remove it from the vector
5495 _dirichlet_boundaries->erase(it);
5496}

References _dirichlet_boundaries, libMesh::DirichletBoundary::b, libMesh::libmesh_assert(), and libMesh::DirichletBoundary::variables.

◆ SCALAR_dof_indices()

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

Fills the vector di with the global degree of freedom indices corresponding to the SCALAR variable vn.

If old_dofs=true, the old SCALAR dof indices are returned.

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

Definition at line 2605 of file dof_map.C.

2613{
2614 // dof_indices() is a relatively light-weight function; the cost of
2615 // the logging code itself is roughly on par with the time required
2616 // to call dof_indices().
2617 // LOG_SCOPE("SCALAR_dof_indices()", "DofMap");
2618
2619 libmesh_assert(this->variable(vn).type().family == SCALAR);
2620
2621#ifdef LIBMESH_ENABLE_AMR
2622 // If we're asking for old dofs then we'd better have some
2623 if (old_dofs)
2624 libmesh_assert_greater_equal(n_old_dofs(), n_SCALAR_dofs());
2625
2626 dof_id_type my_idx = old_dofs ?
2627 this->_first_old_scalar_df[vn] : this->_first_scalar_df[vn];
2628#else
2629 dof_id_type my_idx = this->_first_scalar_df[vn];
2630#endif
2631
2632 libmesh_assert_not_equal_to(my_idx, DofObject::invalid_id);
2633
2634 // The number of SCALAR dofs comes from the variable order
2635 const int n_dofs_vn = this->variable(vn).type().order.get_order();
2636
2637 di.resize(n_dofs_vn);
2638 for (int i = 0; i != n_dofs_vn; ++i)
2639 di[i] = my_idx++;
2640}
dof_id_type n_old_dofs() const

References libMesh::libmesh_assert(), and libMesh::SCALAR.

Referenced by libMesh::ExodusII_IO::copy_scalar_solution(), libMesh::Nemesis_IO::copy_scalar_solution(), dof_indices(), libMesh::System::project_vector(), libMesh::System::project_vector(), libMesh::System::projection_matrix(), libMesh::System::read_parallel_data(), libMesh::System::read_SCALAR_dofs(), libMesh::StaticCondensationDofMap::reinit(), SystemsTest::testProjectScalarCoarsening(), libMesh::Nemesis_IO_Helper::write_nodal_solution(), libMesh::System::write_parallel_data(), and libMesh::System::write_SCALAR_dofs().

◆ scatter_constraints()

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

Sends constraint equations to constraining processors.

Definition at line 4607 of file dof_map_constraints.C.

4608{
4609 // At this point each processor with a constrained node knows
4610 // the corresponding constraint row, but we also need each processor
4611 // with a constrainer node to know the corresponding row(s).
4612
4613 // This function must be run on all processors at once
4614 parallel_object_only();
4615
4616 // Return immediately if there's nothing to gather
4617 if (this->n_processors() == 1)
4618 return;
4619
4620 // We might get to return immediately if none of the processors
4621 // found any constraints
4622 unsigned int has_constraints = !_dof_constraints.empty()
4623#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
4624 || !_node_constraints.empty()
4625#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
4626 ;
4627 this->comm().max(has_constraints);
4628 if (!has_constraints)
4629 return;
4630
4631 // We may be receiving packed_range sends out of order with
4632 // parallel_sync tags, so make sure they're received correctly.
4633 Parallel::MessageTag range_tag = this->comm().get_unique_tag();
4634
4635#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
4636 std::map<processor_id_type, std::set<dof_id_type>> pushed_node_ids;
4637#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
4638
4639 std::map<processor_id_type, std::set<dof_id_type>> pushed_ids;
4640
4641 // Collect the dof constraints I need to push to each processor
4642 dof_id_type constrained_proc_id = 0;
4643 for (const auto & [constrained, row] : _dof_constraints)
4644 {
4645 while (constrained >= _end_df[constrained_proc_id])
4646 constrained_proc_id++;
4647
4648 if (constrained_proc_id != this->processor_id())
4649 continue;
4650
4651 for (auto & j : row)
4652 {
4653 const dof_id_type constraining = j.first;
4654
4655 processor_id_type constraining_proc_id = 0;
4656 while (constraining >= _end_df[constraining_proc_id])
4657 constraining_proc_id++;
4658
4659 if (constraining_proc_id != this->processor_id() &&
4660 constraining_proc_id != constrained_proc_id)
4661 pushed_ids[constraining_proc_id].insert(constrained);
4662 }
4663 }
4664
4665 // Pack the dof constraint rows and rhs's to push
4666
4667 std::map<processor_id_type,
4668 std::vector<std::vector<std::pair<dof_id_type, Real>>>>
4669 pushed_keys_vals, pushed_keys_vals_to_me;
4670
4671 std::map<processor_id_type, std::vector<std::pair<dof_id_type, Number>>>
4672 pushed_ids_rhss, pushed_ids_rhss_to_me;
4673
4674 auto gather_ids =
4675 [this,
4676 & pushed_ids,
4677 & pushed_keys_vals,
4678 & pushed_ids_rhss]
4679 ()
4680 {
4681 for (const auto & [pid, pid_ids] : pushed_ids)
4682 {
4683 const std::size_t ids_size = pid_ids.size();
4684 std::vector<std::vector<std::pair<dof_id_type, Real>>> &
4685 keys_vals = pushed_keys_vals[pid];
4686 std::vector<std::pair<dof_id_type,Number>> &
4687 ids_rhss = pushed_ids_rhss[pid];
4688 keys_vals.resize(ids_size);
4689 ids_rhss.resize(ids_size);
4690
4691 std::size_t push_i;
4692 std::set<dof_id_type>::const_iterator it;
4693 for (push_i = 0, it = pid_ids.begin();
4694 it != pid_ids.end(); ++push_i, ++it)
4695 {
4696 const dof_id_type constrained = *it;
4697 DofConstraintRow & row = _dof_constraints[constrained];
4698 keys_vals[push_i].assign(row.begin(), row.end());
4699
4700 DofConstraintValueMap::const_iterator rhsit =
4701 _primal_constraint_values.find(constrained);
4702 ids_rhss[push_i].first = constrained;
4703 ids_rhss[push_i].second =
4704 (rhsit == _primal_constraint_values.end()) ?
4705 0 : rhsit->second;
4706 }
4707 }
4708 };
4709
4710 gather_ids();
4711
4712 auto ids_rhss_action_functor =
4713 [& pushed_ids_rhss_to_me]
4714 (processor_id_type pid,
4715 const std::vector<std::pair<dof_id_type, Number>> & data)
4716 {
4717 pushed_ids_rhss_to_me[pid] = data;
4718 };
4719
4720 auto keys_vals_action_functor =
4721 [& pushed_keys_vals_to_me]
4722 (processor_id_type pid,
4723 const std::vector<std::vector<std::pair<dof_id_type, Real>>> & data)
4724 {
4725 pushed_keys_vals_to_me[pid] = data;
4726 };
4727
4729 (this->comm(), pushed_ids_rhss, ids_rhss_action_functor);
4731 (this->comm(), pushed_keys_vals, keys_vals_action_functor);
4732
4733 // Now work on traded dof constraint rows
4734 auto receive_dof_constraints =
4735 [this,
4736 & pushed_ids_rhss_to_me,
4737 & pushed_keys_vals_to_me]
4738 ()
4739 {
4740 for (const auto & [pid, ids_rhss] : pushed_ids_rhss_to_me)
4741 {
4742 const auto & keys_vals = pushed_keys_vals_to_me[pid];
4743
4744 libmesh_assert_equal_to
4745 (ids_rhss.size(), keys_vals.size());
4746
4747 // Add the dof constraints that I've been sent
4748 for (auto i : index_range(ids_rhss))
4749 {
4750 dof_id_type constrained = ids_rhss[i].first;
4751
4752 // If we don't already have a constraint for this dof,
4753 // add the one we were sent
4754 if (!this->is_constrained_dof(constrained))
4755 {
4756 DofConstraintRow & row = _dof_constraints[constrained];
4757 for (auto & key_val : keys_vals[i])
4758 {
4759 libmesh_assert_less(key_val.first, this->n_dofs());
4760 row[key_val.first] = key_val.second;
4761 }
4762 if (ids_rhss[i].second != Number(0))
4763 _primal_constraint_values[constrained] =
4764 ids_rhss[i].second;
4765 else
4766 _primal_constraint_values.erase(constrained);
4767 }
4768 }
4769 }
4770 };
4771
4772 receive_dof_constraints();
4773
4774#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
4775 // Collect the node constraints to push to each processor
4776 for (auto & i : _node_constraints)
4777 {
4778 const Node * constrained = i.first;
4779
4780 if (constrained->processor_id() != this->processor_id())
4781 continue;
4782
4783 NodeConstraintRow & row = i.second.first;
4784 for (auto & j : row)
4785 {
4786 const Node * constraining = j.first;
4787
4788 if (constraining->processor_id() != this->processor_id() &&
4789 constraining->processor_id() != constrained->processor_id())
4790 pushed_node_ids[constraining->processor_id()].insert(constrained->id());
4791 }
4792 }
4793
4794 // Pack the node constraint rows and rhss to push
4795 std::map<processor_id_type,
4796 std::vector<std::vector<std::pair<dof_id_type,Real>>>>
4797 pushed_node_keys_vals, pushed_node_keys_vals_to_me;
4798 std::map<processor_id_type, std::vector<std::pair<dof_id_type, Point>>>
4799 pushed_node_ids_offsets, pushed_node_ids_offsets_to_me;
4800 std::map<processor_id_type, std::vector<const Node *>> pushed_node_vecs;
4801
4802 for (const auto & [pid, pid_ids]: pushed_node_ids)
4803 {
4804 const std::size_t ids_size = pid_ids.size();
4805 std::vector<std::vector<std::pair<dof_id_type,Real>>> &
4806 keys_vals = pushed_node_keys_vals[pid];
4807 std::vector<std::pair<dof_id_type, Point>> &
4808 ids_offsets = pushed_node_ids_offsets[pid];
4809 keys_vals.resize(ids_size);
4810 ids_offsets.resize(ids_size);
4811 std::set<Node *> nodes;
4812
4813 std::size_t push_i;
4814 std::set<dof_id_type>::const_iterator it;
4815 for (push_i = 0, it = pid_ids.begin();
4816 it != pid_ids.end(); ++push_i, ++it)
4817 {
4818 Node * constrained = mesh.node_ptr(*it);
4819
4820 if (constrained->processor_id() != pid)
4821 nodes.insert(constrained);
4822
4823 NodeConstraintRow & row = _node_constraints[constrained].first;
4824 std::size_t row_size = row.size();
4825 keys_vals[push_i].reserve(row_size);
4826 for (const auto & j : row)
4827 {
4828 Node * constraining = const_cast<Node *>(j.first);
4829
4830 keys_vals[push_i].emplace_back(constraining->id(), j.second);
4831
4832 if (constraining->processor_id() != pid)
4833 nodes.insert(constraining);
4834 }
4835
4836 ids_offsets[push_i].first = *it;
4837 ids_offsets[push_i].second = _node_constraints[constrained].second;
4838 }
4839
4840 if (!mesh.is_serial())
4841 {
4842 auto & pid_nodes = pushed_node_vecs[pid];
4843 pid_nodes.assign(nodes.begin(), nodes.end());
4844 }
4845 }
4846
4847 auto node_ids_offsets_action_functor =
4848 [& pushed_node_ids_offsets_to_me]
4849 (processor_id_type pid,
4850 const std::vector<std::pair<dof_id_type, Point>> & data)
4851 {
4852 pushed_node_ids_offsets_to_me[pid] = data;
4853 };
4854
4855 auto node_keys_vals_action_functor =
4856 [& pushed_node_keys_vals_to_me]
4857 (processor_id_type pid,
4858 const std::vector<std::vector<std::pair<dof_id_type, Real>>> & data)
4859 {
4860 pushed_node_keys_vals_to_me[pid] = data;
4861 };
4862
4863 // Trade pushed node constraint rows
4865 (this->comm(), pushed_node_ids_offsets, node_ids_offsets_action_functor);
4867 (this->comm(), pushed_node_keys_vals, node_keys_vals_action_functor);
4868
4869 // Constraining nodes might not even exist on our subset of a
4870 // distributed mesh, so let's make them exist.
4871
4872 // Node unpack() now automatically adds them to the context mesh
4873 auto null_node_functor = [](processor_id_type, const std::vector<const Node *> &){};
4874
4875 if (!mesh.is_serial())
4877 (this->comm(), pushed_node_vecs, &mesh, null_node_functor);
4878
4879 for (const auto & [pid, ids_offsets] : pushed_node_ids_offsets_to_me)
4880 {
4881 const auto & keys_vals = pushed_node_keys_vals_to_me[pid];
4882
4883 libmesh_assert_equal_to
4884 (ids_offsets.size(), keys_vals.size());
4885
4886 // Add the node constraints that I've been sent
4887 for (auto i : index_range(ids_offsets))
4888 {
4889 dof_id_type constrained_id = ids_offsets[i].first;
4890
4891 // If we don't already have a constraint for this node,
4892 // add the one we were sent
4893 const Node * constrained = mesh.node_ptr(constrained_id);
4894 if (!this->is_constrained_node(constrained))
4895 {
4896 NodeConstraintRow & row = _node_constraints[constrained].first;
4897 for (auto & key_val : keys_vals[i])
4898 {
4899 const Node * key_node = mesh.node_ptr(key_val.first);
4900 row[key_node] = key_val.second;
4901 }
4902 _node_constraints[constrained].second =
4903 ids_offsets[i].second;
4904 }
4905 }
4906 }
4907#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
4908
4909 // Next we need to push constraints to processors which don't own
4910 // the constrained dof, don't own the constraining dof, but own an
4911 // element supporting the constraining dof.
4912 //
4913 // We need to be able to quickly look up constrained dof ids by what
4914 // constrains them, so that we can handle the case where we see a
4915 // foreign element containing one of our constraining DoF ids and we
4916 // need to push that constraint.
4917 //
4918 // Getting distributed adaptive sparsity patterns right is hard.
4919
4920 typedef std::map<dof_id_type, std::set<dof_id_type>> DofConstrainsMap;
4921 DofConstrainsMap dof_id_constrains;
4922
4923 for (const auto & [constrained, row] : _dof_constraints)
4924 {
4925 for (const auto & j : row)
4926 {
4927 const dof_id_type constraining = j.first;
4928
4929 dof_id_type constraining_proc_id = 0;
4930 while (constraining >= _end_df[constraining_proc_id])
4931 constraining_proc_id++;
4932
4933 if (constraining_proc_id == this->processor_id())
4934 dof_id_constrains[constraining].insert(constrained);
4935 }
4936 }
4937
4938 // Loop over all foreign elements, find any supporting our
4939 // constrained dof indices.
4940 pushed_ids.clear();
4941
4942 for (const auto & elem : as_range(mesh.active_not_local_elements_begin(),
4943 mesh.active_not_local_elements_end()))
4944 {
4945 std::vector<dof_id_type> my_dof_indices;
4946 this->dof_indices (elem, my_dof_indices);
4947
4948 for (const auto & dof : my_dof_indices)
4949 {
4950 if (auto dcmi = dof_id_constrains.find(dof);
4951 dcmi != dof_id_constrains.end())
4952 {
4953 for (const auto & constrained : dcmi->second)
4954 {
4955 dof_id_type the_constrained_proc_id = 0;
4956 while (constrained >= _end_df[the_constrained_proc_id])
4957 the_constrained_proc_id++;
4958
4959 const processor_id_type elemproc = elem->processor_id();
4960 if (elemproc != the_constrained_proc_id)
4961 pushed_ids[elemproc].insert(constrained);
4962 }
4963 }
4964 }
4965 }
4966
4967 pushed_ids_rhss.clear();
4968 pushed_ids_rhss_to_me.clear();
4969 pushed_keys_vals.clear();
4970 pushed_keys_vals_to_me.clear();
4971
4972 gather_ids();
4973
4974 // Trade pushed dof constraint rows
4976 (this->comm(), pushed_ids_rhss, ids_rhss_action_functor);
4978 (this->comm(), pushed_keys_vals, keys_vals_action_functor);
4979
4980 receive_dof_constraints();
4981
4982 // Finally, we need to handle the case of remote dof coupling. If a
4983 // processor's element is coupled to a ghost element, then the
4984 // processor needs to know about all constraints which affect the
4985 // dofs on that ghost element, so we'll have to query the ghost
4986 // element's owner.
4987
4988 GhostingFunctor::map_type elements_to_couple;
4989 DofMap::CouplingMatricesSet temporary_coupling_matrices;
4990
4992 (elements_to_couple,
4993 temporary_coupling_matrices,
4995 this->coupling_functors_end(),
4996 mesh.active_local_elements_begin(),
4997 mesh.active_local_elements_end(),
4998 this->processor_id());
4999
5000 // Each ghost-coupled element's owner should get a request for its dofs
5001 std::set<dof_id_type> requested_dofs;
5002
5003 for (const auto & pr : elements_to_couple)
5004 {
5005 const Elem * elem = pr.first;
5006
5007 // FIXME - optimize for the non-fully-coupled case?
5008 std::vector<dof_id_type> element_dofs;
5009 this->dof_indices(elem, element_dofs);
5010
5011 for (auto dof : element_dofs)
5012 requested_dofs.insert(dof);
5013 }
5014
5015 this->gather_constraints(mesh, requested_dofs, false);
5016}
void push_parallel_packed_range(const Communicator &comm, MapToContainers &&data, Context *context, const ActionFunctor &act_on_data)

References _dof_constraints, libMesh::DofMapBase::_end_df, _node_constraints, _primal_constraint_values, libMesh::as_range(), libMesh::ParallelObject::comm(), coupling_functors_begin(), coupling_functors_end(), dof_indices(), gather_constraints(), libMesh::Parallel::Communicator::get_unique_tag(), libMesh::DofObject::id(), libMesh::index_range(), is_constrained_dof(), is_constrained_node(), libMesh::MeshBase::is_serial(), libMesh::Parallel::Communicator::max(), merge_ghost_functor_outputs(), mesh, libMesh::ParallelObject::n_processors(), libMesh::MeshBase::node_ptr(), libMesh::DofObject::processor_id(), libMesh::ParallelObject::processor_id(), TIMPI::push_parallel_packed_range(), and TIMPI::push_parallel_vector_data().

Referenced by process_constraints().

◆ semilocal_index()

bool libMesh::DofMap::semilocal_index ( dof_id_type  dof_index) const
Returns
true if degree of freedom index dof_index is either a local index or in the send_list.
Note
This is an O(logN) operation for a send_list of size N; we don't cache enough information for O(1) right now.

Definition at line 2644 of file dof_map.C.

2645{
2646 // If it's not in the local indices
2647 if (!this->local_index(dof_index))
2648 {
2649 // and if it's not in the ghost indices, then we're not
2650 // semilocal
2651 if (!std::binary_search(_send_list.begin(), _send_list.end(), dof_index))
2652 return false;
2653 }
2654
2655 return true;
2656}

◆ set_constrained_sparsity_construction()

void libMesh::DofMap::set_constrained_sparsity_construction ( bool  use_constraints)
inline

Sets the current policy for constructing sparsity patterns: if use_constraints is true (for robustness), we explicitly account for sparsity entries created by constraint matrix pre- and post- application.

If use_constraints is false (for speed), we calculate only the sparsity pattern of an unconstrained matrix. This is false by default, because in nearly all applications our constraints do not increase the number of non-zeros required in a sparse matrix.

Definition at line 2541 of file dof_map.h.

2542{
2543 // This got only partly finished...
2544 if (use_constraints)
2545 libmesh_not_implemented();
2546
2547#ifdef LIBMESH_ENABLE_CONSTRAINTS
2548 _constrained_sparsity_construction = use_constraints;
2549#endif
2550 libmesh_ignore(use_constraints);
2551}
void libmesh_ignore(const Args &...)

References _constrained_sparsity_construction, and libMesh::libmesh_ignore().

◆ set_error_on_constraint_loop()

void libMesh::DofMap::set_error_on_constraint_loop ( bool  error_on_constraint_loop)

Definition at line 234 of file dof_map.C.

235{
236 _error_on_constraint_loop = error_on_constraint_loop;
237}

References _error_on_constraint_loop.

Referenced by set_error_on_cyclic_constraint(), and DofMapTest::testConstraintLoopDetection().

◆ set_error_on_cyclic_constraint()

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

Specify whether or not we perform an extra (opt-mode enabled) check for constraint loops.

If a constraint loop is present then the system constraints are not valid, so if error_on_constraint_loop is true we will throw an error in this case.

Note
We previously referred to these types of constraints as "cyclic" but that has now been deprecated, and these will now instead be referred to as "constraint loops" in libMesh.

Definition at line 227 of file dof_map.C.

228{
229 // This function will eventually be officially libmesh_deprecated();
230 // Call DofMap::set_error_on_constraint_loop() instead.
231 set_error_on_constraint_loop(error_on_cyclic_constraint);
232}
void set_error_on_constraint_loop(bool error_on_constraint_loop)
Definition dof_map.C:234

References set_error_on_constraint_loop().

◆ set_implicit_neighbor_dofs()

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

Allow the implicit_neighbor_dofs flag to be set programmatically.

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

Definition at line 1891 of file dof_map.C.

1892{
1894 _implicit_neighbor_dofs = implicit_neighbor_dofs;
1895}

Referenced by DisjointNeighborTest::testTempJump(), and DisjointNeighborTest::testTempJumpRefine().

◆ set_nonlocal_dof_objects()

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

Helper function for distributing dofs in parallel.

Definition at line 318 of file dof_map.C.

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

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

◆ set_verify_dirichlet_bc_consistency()

void libMesh::DofMap::set_verify_dirichlet_bc_consistency ( bool  val)

Set the _verify_dirichlet_bc_consistency flag.

Definition at line 1897 of file dof_map.C.

1898{
1900}

◆ should_p_refine() [1/6]

bool libMesh::DofMap::should_p_refine ( FEFamily  ) const
delete

◆ should_p_refine() [2/6]

void libMesh::DofMap::should_p_refine ( FEFamily  ,
bool   
)
delete

◆ should_p_refine() [3/6]

bool libMesh::DofMap::should_p_refine ( Order  ) const
delete

◆ should_p_refine() [4/6]

void libMesh::DofMap::should_p_refine ( Order  ,
bool   
)
delete

◆ should_p_refine() [5/6]

bool libMesh::DofMap::should_p_refine ( unsigned int  g) const
inline

Whether the given variable group should be p-refined.

Definition at line 2588 of file dof_map.h.

2589{
2590#ifdef LIBMESH_ENABLE_AMR
2591 const VariableGroup & var = this->variable_group(g);
2592 return var.type().p_refinement;
2593#else
2594 libmesh_ignore(g);
2595 return false;
2596#endif
2597}

References libMesh::libmesh_ignore(), libMesh::FEType::p_refinement, libMesh::Variable::type(), and variable_group().

◆ should_p_refine() [6/6]

void libMesh::DofMap::should_p_refine ( unsigned int  g,
bool  p_refine 
)
inline

Set whether the given variable group should be p-refined on a p-refined Elem.

This changes the FEType of the variable group to enable or disable p-refinement.

Definition at line 2570 of file dof_map.h.

2571{
2572#ifdef LIBMESH_ENABLE_AMR
2573 VariableGroup & var = _variable_groups[g];
2574 var.type().p_refinement = p_refine;
2575
2576 for (auto v : make_range(var.first_scalar_number(0),
2577 var.first_scalar_number(0) +
2578 var.n_variables()))
2579 this->_variables[v].type().p_refinement = p_refine;
2580
2581
2582#else
2583 libmesh_ignore(g, p_refine);
2584#endif
2585}

References _variable_groups, _variables, libMesh::VariableGroup::first_scalar_number(), libMesh::libmesh_ignore(), libMesh::make_range(), libMesh::VariableGroup::n_variables(), libMesh::FEType::p_refinement, and libMesh::Variable::type().

Referenced by should_p_refine_var().

◆ should_p_refine_var()

bool libMesh::DofMap::should_p_refine_var ( unsigned int  var) const
inline

Whether the given variable should be p-refined.

Definition at line 2607 of file dof_map.h.

2608{
2609#ifdef LIBMESH_ENABLE_AMR
2610 const auto vg = this->var_group_from_var_number(var);
2611 return this->should_p_refine(vg);
2612#else
2613 libmesh_ignore(var);
2614 return false;
2615#endif
2616}
unsigned int var_group_from_var_number(unsigned int var_num) const
Definition dof_map.h:2600
void should_p_refine(unsigned int g, bool p_refine)
Set whether the given variable group should be p-refined on a p-refined Elem.
Definition dof_map.h:2570

References libMesh::libmesh_ignore(), should_p_refine(), and var_group_from_var_number().

◆ stash_dof_constraints()

void libMesh::DofMap::stash_dof_constraints ( )
inline

◆ swap_dof_constraints()

void libMesh::DofMap::swap_dof_constraints ( )
inline

Similar to the stash/unstash_dof_constraints() API, but swaps _dof_constraints and _stashed_dof_constraints without asserting that the source or destination is empty first.

Note
There is an implicit assumption that swapping between sets of Constraints does not change the sparsity pattern or expand the send_list, since the only thing changed is the DofConstraints themselves. This is intended to work for swapping between DofConstraints A and B, where A is used to define the send_list, and B is a subset of A.

Definition at line 1203 of file dof_map.h.

1204 {
1206 }

References _dof_constraints, and _stashed_dof_constraints.

◆ sys_number()

unsigned int libMesh::DofMap::sys_number ( ) const
inline
Returns
The number of the system we are responsible for.

Definition at line 2340 of file dof_map.h.

2341{
2342 return _sys_number;
2343}

References _sys_number.

Referenced by _dof_indices(), allgather_recursive_constraints(), libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), constrain_p_dofs(), process_mesh_constraint_rows(), reinit(), and set_nonlocal_dof_objects().

◆ unstash_dof_constraints()

void libMesh::DofMap::unstash_dof_constraints ( )
inline

◆ update_sparsity_pattern()

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

Additional matrices may be be temporarily initialized by this DofMap.

They are initialized to the same sparsity structure as the major matrix.

Definition at line 269 of file dof_map.C.

270{
271 matrix.attach_dof_map (*this);
272
273 // If we've already computed sparsity, then it's too late
274 // to wait for "compute_sparsity" to help with sparse matrix
275 // initialization, and we need to handle this matrix individually
276 if (this->computed_sparsity_already())
277 {
278 libmesh_assert(_sp.get());
279
280 if (matrix.need_full_sparsity_pattern())
281 {
282 // We'd better have already computed the full sparsity
283 // pattern if we need it here
285
286 matrix.update_sparsity_pattern (_sp->get_sparsity_pattern());
287 }
288
290 }
291}
virtual void update_sparsity_pattern(const SparsityPattern::Graph &)
Updates the matrix sparsity pattern.
void attach_dof_map(const DofMap &dof_map)
Set a pointer to the DofMap to use.
void attach_sparsity_pattern(const SparsityPattern::Build &sp)
Set a pointer to a sparsity pattern to use.

References _sp, libMesh::SparseMatrix< T >::attach_dof_map(), libMesh::SparseMatrix< T >::attach_sparsity_pattern(), computed_sparsity_already(), libMesh::libmesh_assert(), need_full_sparsity_pattern, libMesh::SparseMatrix< T >::need_full_sparsity_pattern(), and libMesh::SparseMatrix< T >::update_sparsity_pattern().

Referenced by attach_matrix(), and libMesh::System::solve_for_unconstrained_dofs().

◆ use_coupled_neighbor_dofs()

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

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

Definition at line 1903 of file dof_map.C.

1904{
1905 // If we were asked on the command line, then we need to
1906 // include sensitivities between neighbor degrees of freedom
1907 bool implicit_neighbor_dofs =
1908 libMesh::on_command_line ("--implicit-neighbor-dofs");
1909
1910 // If the user specifies --implicit-neighbor-dofs 0, then
1911 // presumably he knows what he is doing and we won't try to
1912 // automatically turn it on even when all the variables are
1913 // discontinuous.
1914 if (implicit_neighbor_dofs)
1915 {
1916 // No flag provided defaults to 'true'
1917 int flag = 1;
1918 flag = libMesh::command_line_next ("--implicit-neighbor-dofs", flag);
1919
1920 if (!flag)
1921 {
1922 // The user said --implicit-neighbor-dofs 0, so he knows
1923 // what he is doing and really doesn't want it.
1924 return false;
1925 }
1926 }
1927
1928 // Possibly override the commandline option, if set_implicit_neighbor_dofs
1929 // has been called.
1931 {
1932 implicit_neighbor_dofs = _implicit_neighbor_dofs;
1933
1934 // Again, if the user explicitly says implicit_neighbor_dofs = false,
1935 // then we return here.
1936 if (!implicit_neighbor_dofs)
1937 return false;
1938 }
1939
1940 // Look at all the variables in this system. If every one is
1941 // discontinuous then the user must be doing DG/FVM, so be nice
1942 // and force implicit_neighbor_dofs=true.
1943 {
1944 bool all_discontinuous_dofs = true;
1945
1946 // We may call this method even without ever having initialized our data
1947 for (auto var : index_range(this->_variables))
1948 if (FEInterface::get_continuity(this->variable_type(var)) != DISCONTINUOUS)
1949 all_discontinuous_dofs = false;
1950
1951 if (all_discontinuous_dofs)
1952 implicit_neighbor_dofs = true;
1953 }
1954
1955 return implicit_neighbor_dofs;
1956}
T command_line_next(std::string name, T default_value)
Use GetPot's search()/next() functions to get following arguments from the command line.
Definition libmesh.C:1025

References libMesh::command_line_next(), libMesh::DISCONTINUOUS, libMesh::index_range(), and libMesh::on_command_line().

Referenced by build_sparsity(), and reinit().

◆ var_group_from_var_number()

unsigned int libMesh::DofMap::var_group_from_var_number ( unsigned int  var_num) const
inline
Returns
The variable group number that the provided variable number belongs to

Definition at line 2600 of file dof_map.h.

2601{
2602 libmesh_assert(var_num < n_variables());
2603 return libmesh_map_find(_var_to_vg, var_num);
2604}

References _var_to_vg, libMesh::libmesh_assert(), and n_variables().

Referenced by should_p_refine_var(), and EquationSystemsTest::testSelectivePRefine().

◆ variable()

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

Implements libMesh::DofMapBase.

Definition at line 2358 of file dof_map.h.

2359{
2360 libmesh_assert_less (c, _variables.size());
2361
2362 return _variables[c];
2363}

References _variables.

Referenced by libMesh::FEGenericBase< OutputType >::compute_proj_constraints(), DMlibMeshSetSystem_libMesh(), libMesh::BoundaryProjectSolution::operator()(), and libMesh::StaticCondensationDofMap::reinit().

◆ variable_group()

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

Definition at line 2348 of file dof_map.h.

2349{
2350 libmesh_assert_less (g, _variable_groups.size());
2351
2352 return _variable_groups[g];
2353}

References _variable_groups.

Referenced by _dof_indices(), dof_indices(), libMesh::StaticCondensationDofMap::reinit(), and should_p_refine().

◆ variable_group_order()

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

Definition at line 2378 of file dof_map.h.

2379{
2380 libmesh_assert_less (vg, _variable_groups.size());
2381
2382 return _variable_groups[vg].type().order;
2383}

References _variable_groups.

◆ variable_group_type()

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

Definition at line 2398 of file dof_map.h.

2399{
2400 libmesh_assert_less (vg, _variable_groups.size());
2401
2402 return _variable_groups[vg].type();
2403}

References _variable_groups.

◆ variable_name()

const std::string & libMesh::DofMap::variable_name ( const unsigned int  i) const
inline
Returns
The name of variable i.

Definition at line 2943 of file dof_map.h.

2944{
2945 libmesh_assert_less (i, _variables.size());
2946
2947 return _variables[i].name();
2948}

References _variables.

◆ variable_number()

unsigned int libMesh::DofMap::variable_number ( std::string_view  var) const
inline
Returns
The variable number associated with the user-specified variable named var.

Definition at line 2991 of file dof_map.h.

2992{
2993 auto var_num = libmesh_map_find(_variable_numbers, var);
2994 libmesh_assert_equal_to(_variables[var_num].name(), var);
2995 return var_num;
2996}

References _variable_numbers, and _variables.

Referenced by create_dof_constraints(), libMesh::System::variable_number(), and variable_type().

◆ variable_order()

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

Definition at line 2368 of file dof_map.h.

2369{
2370 libmesh_assert_less (c, _variables.size());
2371
2372 return _variables[c].type().order;
2373}

References _variables.

◆ variable_scalar_number()

unsigned int libMesh::DofMap::variable_scalar_number ( unsigned int  var_num,
unsigned int  component 
) const
inline
Returns
An index, starting from 0 for the first component of the first variable, and incrementing for each component of each (potentially vector-valued) variable in the system in order. For systems with only scalar-valued variables, this will be the same as var_num

Irony: currently our only non-scalar-valued variable type is SCALAR.

Definition at line 2974 of file dof_map.h.

2976{
2977 return _variables[var_num].first_scalar_number() + component;
2978}

References _variables.

◆ variable_type() [1/2]

const FEType & libMesh::DofMap::variable_type ( const unsigned int  i) const
inline
Returns
The finite element type for variable number i.

Definition at line 2388 of file dof_map.h.

2389{
2390 libmesh_assert_less (c, _variables.size());
2391
2392 return _variables[c].type();
2393}

References _variables.

Referenced by libMesh::ExactSolution::_compute_error(), libMesh::UniformRefinementEstimator::_estimate_error(), libMesh::MeshFunction::_gradient_on_elem(), LinearElasticity::assemble(), AssembleOptimization::assemble_A_and_F(), assemble_elasticity(), assemble_mass(), assemble_matrices(), assemble_poisson(), assemble_SchroedingerEquation(), Biharmonic::JR::bounds(), libMesh::FEGenericBase< OutputType >::coarsened_dof_values(), libMesh::FEInterface::compute_constraints(), compute_enriched_soln(), compute_jacobian(), libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), libMesh::FEInterface::compute_periodic_constraints(), compute_residual(), LinearElasticity::compute_stresses(), LargeDeformationElasticity::compute_stresses(), LinearElasticityWithContact::compute_stresses(), compute_stresses(), constrain_p_dofs(), libMesh::MeshFunction::discontinuous_value(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::MeshFunction::hessian(), libMesh::InfFE< Dim, T_radial, T_map >::inf_compute_constraints(), LargeDeformationElasticity::jacobian(), LinearElasticityWithContact::move_mesh(), libMesh::PatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::SmoothnessEstimator::EstimateSmoothness::operator()(), libMesh::WeightedPatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::MeshFunction::operator()(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), process_mesh_constraint_rows(), LargeDeformationElasticity::residual(), LinearElasticityWithContact::residual_and_jacobian(), Biharmonic::JR::residual_and_jacobian(), and libMesh::HPCoarsenTest::select_refinement().

◆ variable_type() [2/2]

const FEType & libMesh::DofMap::variable_type ( std::string_view  var) const
inline
Returns
The finite element type for variable var.

Definition at line 2981 of file dof_map.h.

2982{
2983 return _variables[this->variable_number(var)].type();
2984}

References _variables, and variable_number().

Friends And Related Symbol Documentation

◆ SparsityPattern::Build

friend class SparsityPattern::Build
friend

Definition at line 2311 of file dof_map.h.

Member Data Documentation

◆ _adjoint_constraint_values

AdjointDofConstraintValues libMesh::DofMap::_adjoint_constraint_values
private

◆ _adjoint_dirichlet_boundaries

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

Data structure containing Dirichlet functions.

The ith entry is the constraint matrix row for boundaryid i.

Definition at line 2308 of file dof_map.h.

Referenced by add_adjoint_dirichlet_boundary(), create_dof_constraints(), get_adjoint_dirichlet_boundaries(), get_adjoint_dirichlet_boundaries(), get_local_constraints(), has_adjoint_dirichlet_boundaries(), and remove_adjoint_dirichlet_boundary().

◆ _algebraic_ghosting_functors

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

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

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

Keep these in a vector so any parallel computation is done in the same order on all processors.

Definition at line 2220 of file dof_map.h.

Referenced by algebraic_ghosting_functors_begin(), and algebraic_ghosting_functors_end().

◆ _array_variables

std::vector<std::pair<unsigned int, unsigned int> > libMesh::DofMap::_array_variables
private

Array variable information storage.

For a given array "variable", the first member of the pair denotes the first variable number present in the array variable and the second member of the pair denotes the last variable number present in the array variables plus one

Definition at line 2124 of file dof_map.h.

Referenced by get_variable_array().

◆ _augment_send_list

AugmentSendList* libMesh::DofMap::_augment_send_list
private

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

Definition at line 2181 of file dof_map.h.

Referenced by attach_extra_send_list_object().

◆ _augment_sparsity_pattern

SparsityPattern::AugmentSparsityPattern* libMesh::DofMap::_augment_sparsity_pattern
private

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

Definition at line 2164 of file dof_map.h.

Referenced by attach_extra_sparsity_object(), and build_sparsity().

◆ _communicator

const Parallel::Communicator& libMesh::ParallelObject::_communicator
protectedinherited

◆ _constrained_sparsity_construction

bool libMesh::DofMap::_constrained_sparsity_construction
private

This flag indicates whether or not we explicitly take constraint equations into account when computing a sparsity pattern.

Definition at line 2091 of file dof_map.h.

Referenced by constrained_sparsity_construction(), and set_constrained_sparsity_construction().

◆ _counts

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

Actually holds the data.

Definition at line 124 of file reference_counter.h.

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

◆ _coupling_functors

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

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

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

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

Definition at line 2233 of file dof_map.h.

Referenced by build_sparsity(), coupling_functors_begin(), and coupling_functors_end().

◆ _default_coupling

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

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

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

Definition at line 2199 of file dof_map.h.

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

◆ _default_evaluating

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

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

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

Definition at line 2207 of file dof_map.h.

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

◆ _dirichlet_boundaries

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

Data structure containing Dirichlet functions.

The ith entry is the constraint matrix row for boundaryid i.

Definition at line 2302 of file dof_map.h.

Referenced by add_dirichlet_boundary(), create_dof_constraints(), get_dirichlet_boundaries(), get_dirichlet_boundaries(), and remove_dirichlet_boundary().

◆ _dof_constraints

DofConstraints libMesh::DofMap::_dof_constraints
private

◆ _dof_coupling

CouplingMatrix* libMesh::DofMap::_dof_coupling

Degree of freedom coupling.

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

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

Definition at line 1741 of file dof_map.h.

Referenced by libMesh::RBConstruction::add_scaled_matrix_and_vector(), build_sparsity(), main(), and reinit().

◆ _enable_print_counter

bool libMesh::ReferenceCounter::_enable_print_counter = true
staticprotectedinherited

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

Definition at line 143 of file reference_counter.h.

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

◆ _end_df

std::vector<dof_id_type> libMesh::DofMapBase::_end_df
protectedinherited

◆ _end_old_df

std::vector<dof_id_type> libMesh::DofMapBase::_end_old_df
protectedinherited

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

Definition at line 181 of file dof_map_base.h.

Referenced by libMesh::DofMapBase::end_old_dof().

◆ _error_on_constraint_loop

bool libMesh::DofMap::_error_on_constraint_loop
private

This flag indicates whether or not we do an opt-mode check for the presence of constraint loops, i.e.

cases where the constraint graph is cyclic.

Definition at line 2085 of file dof_map.h.

Referenced by process_constraints(), and set_error_on_constraint_loop().

◆ _extra_send_list_context

void* libMesh::DofMap::_extra_send_list_context
private

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

Definition at line 2191 of file dof_map.h.

Referenced by attach_extra_send_list_function().

◆ _extra_send_list_function

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

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

Definition at line 2186 of file dof_map.h.

Referenced by attach_extra_send_list_function().

◆ _extra_sparsity_context

void* libMesh::DofMap::_extra_sparsity_context
private

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

Definition at line 2176 of file dof_map.h.

Referenced by attach_extra_sparsity_function(), and build_sparsity().

◆ _extra_sparsity_function

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

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

Definition at line 2169 of file dof_map.h.

Referenced by attach_extra_sparsity_function(), and build_sparsity().

◆ _first_df

std::vector<dof_id_type> libMesh::DofMapBase::_first_df
protectedinherited

◆ _first_old_df

std::vector<dof_id_type> libMesh::DofMapBase::_first_old_df
protectedinherited

First old DOF index on processor p.

Definition at line 176 of file dof_map_base.h.

Referenced by libMesh::DofMapBase::first_old_dof().

◆ _first_old_scalar_df

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

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

Definition at line 2266 of file dof_map.h.

◆ _first_scalar_df

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

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

Definition at line 2153 of file dof_map.h.

◆ _identify_variable_groups

bool libMesh::DofMap::_identify_variable_groups = true
private

true when VariableGroup structures should be automatically identified, false otherwise.

Defaults to true.

Definition at line 2130 of file dof_map.h.

Referenced by identify_variable_groups(), and identify_variable_groups().

◆ _implicit_neighbor_dofs

bool libMesh::DofMap::_implicit_neighbor_dofs
private

Definition at line 2318 of file dof_map.h.

◆ _implicit_neighbor_dofs_initialized

bool libMesh::DofMap::_implicit_neighbor_dofs_initialized
private

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

Definition at line 2317 of file dof_map.h.

◆ _matrices

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

Additional matrices handled by this object.

These pointers do not handle the memory, instead, System, who told DofMap about them, owns them.

Definition at line 2147 of file dof_map.h.

Referenced by attach_matrix(), DofMap(), and is_attached().

◆ _mesh

MeshBase& libMesh::DofMap::_mesh
private

The mesh that system uses.

Definition at line 2140 of file dof_map.h.

Referenced by DofMap(), local_variable_indices(), n_local_dofs(), and ~DofMap().

◆ _mutex

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

Mutual exclusion object to enable thread-safe reference counting.

Definition at line 137 of file reference_counter.h.

◆ _n_dfs

dof_id_type libMesh::DofMapBase::_n_dfs
protectedinherited

Total number of degrees of freedom.

Definition at line 164 of file dof_map_base.h.

Referenced by libMesh::DofMapBase::clear(), and libMesh::DofMapBase::n_dofs().

◆ _n_objects

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

◆ _n_old_dfs

dof_id_type libMesh::DofMapBase::_n_old_dfs
protectedinherited

Total number of degrees of freedom on old dof objects.

Definition at line 171 of file dof_map_base.h.

Referenced by libMesh::DofMapBase::n_old_dofs().

◆ _n_SCALAR_dofs

dof_id_type libMesh::DofMap::_n_SCALAR_dofs
private

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

Definition at line 2258 of file dof_map.h.

Referenced by n_SCALAR_dofs().

◆ _node_constraints

NodeConstraints libMesh::DofMap::_node_constraints
private

◆ _periodic_boundaries

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

Data structure containing periodic boundaries.

The ith entry is the constraint matrix row for boundaryid i.

Definition at line 2294 of file dof_map.h.

Referenced by add_periodic_boundary(), create_dof_constraints(), DofMap(), get_periodic_boundaries(), get_periodic_boundaries(), is_periodic_boundary(), and process_mesh_constraint_rows().

◆ _primal_constraint_values

DofConstraintValueMap libMesh::DofMap::_primal_constraint_values
private

◆ _sc

std::unique_ptr<StaticCondensationDofMap> libMesh::DofMap::_sc
private

Static condensation class.

Definition at line 2333 of file dof_map.h.

Referenced by build_sparsity(), get_static_condensation(), get_static_condensation(), and has_static_condensation().

◆ _send_list

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

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

Definition at line 2159 of file dof_map.h.

Referenced by add_constraints_to_send_list(), clear_send_list(), and get_send_list().

◆ _shared_functors

std::map<GhostingFunctor *, std::shared_ptr<GhostingFunctor> > libMesh::DofMap::_shared_functors
private

Hang on to references to any GhostingFunctor objects we were passed in shared_ptr form.

Definition at line 2239 of file dof_map.h.

Referenced by add_algebraic_ghosting_functor(), and add_coupling_functor().

◆ _sp

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

The sparsity pattern of the global matrix.

If need_full_sparsity_pattern is true, we save the entire sparse graph here. Otherwise we save just the n_nz and n_oz vectors.

Definition at line 2252 of file dof_map.h.

Referenced by computed_sparsity_already(), get_n_nz(), get_n_oz(), get_sparsity_pattern(), and update_sparsity_pattern().

◆ _stashed_dof_constraints

DofConstraints libMesh::DofMap::_stashed_dof_constraints
private

◆ _sys_number

const unsigned int libMesh::DofMap::_sys_number
private

The number of the system we manage DOFs for.

Definition at line 2135 of file dof_map.h.

Referenced by sys_number().

◆ _var_to_vg

std::unordered_map<unsigned int, unsigned int> libMesh::DofMap::_var_to_vg
private

A map from variable number to variable group number.

Definition at line 2111 of file dof_map.h.

Referenced by array_dof_indices(), and var_group_from_var_number().

◆ _variable_group_numbers

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

The variable group number for each variable.

Definition at line 2106 of file dof_map.h.

Referenced by dof_indices().

◆ _variable_groups

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

The variable groups in this system/degree of freedom map.

Definition at line 2101 of file dof_map.h.

Referenced by array_dof_indices(), n_variable_groups(), should_p_refine(), variable_group(), variable_group_order(), and variable_group_type().

◆ _variable_numbers

std::map<std::string, unsigned int, std::less<> > libMesh::DofMap::_variable_numbers
private

The variable numbers corresponding to user-specified names, useful for name-based lookups.

Definition at line 2117 of file dof_map.h.

Referenced by has_variable(), and variable_number().

◆ _variables

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

The variables in this system/degree of freedom map.

Definition at line 2096 of file dof_map.h.

Referenced by n_components(), n_variables(), n_vars(), should_p_refine(), variable(), variable_name(), variable_number(), variable_order(), variable_scalar_number(), variable_type(), and variable_type().

◆ _verify_dirichlet_bc_consistency

bool libMesh::DofMap::_verify_dirichlet_bc_consistency
private

Flag which determines whether we should do some additional checking of the consistency of the DirichletBoundary objects added by the user.

Defaults to true, but can be disabled in cases where you only want to add DirichletBoundary objects "locally" and can guarantee that no repartitioning will be done, since repartitioning could cause processors to own new boundary sides for which they no longer have the proper DirichletBoundary objects stored.

Definition at line 2330 of file dof_map.h.

Referenced by create_dof_constraints().

◆ need_full_sparsity_pattern

bool libMesh::DofMap::need_full_sparsity_pattern
private

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

Definition at line 2245 of file dof_map.h.

Referenced by attach_matrix(), build_sparsity(), full_sparsity_pattern_needed(), and update_sparsity_pattern().


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