libmesh解析
本工作只是尝试解析原libmesh的代码,供学习使用
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 
| Public 成员函数 | 静态 Public 成员函数 | Public 属性 | Protected 类型 | Protected 成员函数 | 静态 Protected 属性 | Private 类型 | Private 成员函数 | 静态 Private 成员函数 | Private 属性 | 友元 | 所有成员列表
libMesh::DofMap类 参考

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

#include <dof_map.h>

类 libMesh::DofMap 继承关系图:
[图例]

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

Public 成员函数

 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. 更多...
 
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. 更多...
 
std::set< GhostingFunctor * >
::const_iterator 
coupling_functors_begin () const
 Beginning of range of coupling functors. 更多...
 
std::set< GhostingFunctor * >
::const_iterator 
coupling_functors_end () const
 End of range of coupling functors. 更多...
 
DefaultCoupling & default_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. 更多...
 
std::set< GhostingFunctor * >
::const_iterator 
algebraic_ghosting_functors_begin () const
 Beginning of range of algebraic ghosting functors. 更多...
 
std::set< GhostingFunctor * >
::const_iterator 
algebraic_ghosting_functors_end () const
 End of range of algebraic ghosting functors. 更多...
 
DefaultCoupling & default_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
 
void add_variable_group (VariableGroup var_group)
 Add an unknown of order order and finite element type type to the system of equations. 更多...
 
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
 
Order variable_order (const unsigned int c) const
 
Order variable_group_order (const unsigned int vg) const
 
const FEType & variable_type (const unsigned int c) const
 
const FEType & variable_group_type (const unsigned int vg) const
 
unsigned int n_variable_groups () const
 
unsigned int n_variables () const
 
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
 
dof_id_type n_SCALAR_dofs () const
 
dof_id_type n_local_dofs () const
 
dof_id_type n_dofs_on_processor (const processor_id_type proc) const
 
dof_id_type first_dof (const processor_id_type proc) const
 
dof_id_type first_dof () const
 
dof_id_type first_old_dof (const processor_id_type proc) const
 
dof_id_type first_old_dof () const
 
dof_id_type end_dof (const processor_id_type proc) const
 
dof_id_type end_dof () const
 
processor_id_type dof_owner (const dof_id_type dof) const
 
dof_id_type end_old_dof (const processor_id_type proc) const
 
dof_id_type end_old_dof () const
 
void dof_indices (const Elem *const elem, std::vector< dof_id_type > &di) const
 Fills the vector di with the global degree of freedom indices for the element. 更多...
 
void 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 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
 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. 更多...
 
void local_variable_indices (std::vector< dof_id_type > &idx, const MeshBase &mesh, unsigned int var_num) const
 Fills an array of those dof indices which belong to the given variable number and live on the current processor. 更多...
 
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. 更多...
 
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. 更多...
 
dof_id_type n_old_dofs () const
 
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)
 Reinitialize the underlying data structures conformal to the current mesh. 更多...
 
void clear ()
 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::Build
build_sparsity (const MeshBase &mesh, bool calculate_constrained=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)
 Describe whether the given variable group should be p-refined. 更多...
 
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
 

静态 Public 成员函数

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 属性

CouplingMatrix * _dof_coupling
 Degree of freedom coupling. 更多...
 

Protected 类型

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

Protected 成员函数

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 属性

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 类型

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::CompareUnderlying > 
CouplingMatricesSet
 

Private 成员函数

void _dof_indices (const Elem &elem, int p_level, std::vector< dof_id_type > &di, const unsigned int vg, const unsigned int vig, const Node *const *nodes, unsigned int n_nodes#ifdef DEBUG, const unsigned int v, std::size_t &tot_size#endif) const
 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. 更多...
 
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. 更多...
 
void distribute_local_dofs_var_major (dof_id_type &next_free_dof, MeshBase &mesh)
 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)
 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. 更多...
 

静态 Private 成员函数

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

Private 属性

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 finite element type for each variable. 更多...
 
std::vector< VariableGroup_variable_groups
 The finite element type for each variable group. 更多...
 
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. 更多...
 
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_df
 First DOF index on processor p. 更多...
 
std::vector< dof_id_type_end_df
 Last DOF index (plus 1) on processor p. 更多...
 
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::set< GhostingFunctor * > _algebraic_ghosting_functors
 The list of all GhostingFunctor objects to be used when distributing ghosted vectors. 更多...
 
std::set< 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_dfs
 Total number of degrees of freedom. 更多...
 
dof_id_type _n_SCALAR_dofs
 The total number of SCALAR dofs associated to all SCALAR variables. 更多...
 
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. 更多...
 
std::vector< dof_id_type_first_old_scalar_df
 First old DOF index for SCALAR variable v, or garbage for non-SCALAR variable v. 更多...
 
std::unordered_set< unsigned int > _dont_p_refine
 A container of variable groups that we should not p-refine. 更多...
 
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. 更多...
 

友元

class SparsityPattern::Build
 

详细描述

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.

作者
Benjamin S. Kirk
日期
2002-2007 Manages the degrees of freedom (DOFs) in a simulation.

在文件 dof_map.h169 行定义.

成员类型定义说明

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.

在文件 reference_counter.h119 行定义.

typedef std::set<std::unique_ptr<CouplingMatrix>, Utility::CompareUnderlying> libMesh::DofMap::CouplingMatricesSet
private

在文件 dof_map.h1742 行定义.

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().

在文件 dof_map.h1690 行定义.

构造及析构函数说明

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.

在文件 dof_map.C135 行定义.

参考 _default_coupling, _default_evaluating, _matrices, _mesh, _periodic_boundaries, add_algebraic_ghosting_functor() , 以及 add_coupling_functor().

136  :
137  ParallelObject (mesh.comm()),
138  _dof_coupling(nullptr),
141  _variables(),
144  _sys_number(number),
145  _mesh(mesh),
146  _matrices(),
147  _first_df(),
148  _end_df(),
150  _send_list(),
151  _augment_sparsity_pattern(nullptr),
152  _extra_sparsity_function(nullptr),
153  _extra_sparsity_context(nullptr),
154  _augment_send_list(nullptr),
155  _extra_send_list_function(nullptr),
156  _extra_send_list_context(nullptr),
157  _default_coupling(std::make_unique<DefaultCoupling>()),
158  _default_evaluating(std::make_unique<DefaultCoupling>()),
160  _n_dfs(0),
161  _n_SCALAR_dofs(0)
162 #ifdef LIBMESH_ENABLE_AMR
163  , _n_old_dfs(0),
164  _first_old_df(),
165  _end_old_df(),
167 #endif
168 #ifdef LIBMESH_ENABLE_CONSTRAINTS
169  , _dof_constraints()
173 #endif
174 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
176 #endif
177 #ifdef LIBMESH_ENABLE_PERIODIC
178  , _periodic_boundaries(std::make_unique<PeriodicBoundaries>())
179 #endif
180 #ifdef LIBMESH_ENABLE_DIRICHLET
181  , _dirichlet_boundaries(std::make_unique<DirichletBoundaries>())
183 #endif
187 {
188  _matrices.clear();
189 
190  _default_coupling->set_mesh(&_mesh);
191  _default_evaluating->set_mesh(&_mesh);
192  _default_evaluating->set_n_levels(1);
193 
194 #ifdef LIBMESH_ENABLE_PERIODIC
195  _default_coupling->set_periodic_boundaries(_periodic_boundaries.get());
196  _default_evaluating->set_periodic_boundaries(_periodic_boundaries.get());
197 #endif
198 
201 }
std::vector< VariableGroup > _variable_groups
The finite element type for each variable group.
Definition: dof_map.h:1844
bool _implicit_neighbor_dofs_initialized
Bools to indicate if we override the –implicit_neighbor_dofs commandline options. ...
Definition: dof_map.h:2073
const unsigned int _sys_number
The number of the system we manage DOFs for.
Definition: dof_map.h:1859
bool _implicit_neighbor_dofs
Definition: dof_map.h:2074
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:1828
void * _extra_sparsity_context
A pointer associated with the extra sparsity that can optionally be passed in.
Definition: dof_map.h:1910
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:1893
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition: dof_map.h:2058
std::vector< dof_id_type > _end_old_df
Last old DOF index (plus 1) on processor p.
Definition: dof_map.h:2011
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:1861
std::vector< dof_id_type > _first_old_df
First old DOF index on processor p.
Definition: dof_map.h:2006
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:1887
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:2034
bool _constrained_sparsity_construction
This flag indicates whether or not we explicitly take constraint equations into account when computin...
Definition: dof_map.h:1834
AugmentSendList * _augment_send_list
Function object to call to add extra entries to the send list.
Definition: dof_map.h:1915
bool need_full_sparsity_pattern
Default false; set to true if any attached matrix requires a full sparsity pattern.
Definition: dof_map.h:1976
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:2017
dof_id_type _n_SCALAR_dofs
The total number of SCALAR dofs associated to all SCALAR variables.
Definition: dof_map.h:1994
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
CouplingMatrix * _dof_coupling
Degree of freedom coupling.
Definition: dof_map.h:1589
void * _extra_send_list_context
A pointer associated with the extra send list that can optionally be passed in.
Definition: dof_map.h:1925
std::vector< SparseMatrix< Number > * > _matrices
Additional matrices handled by this object.
Definition: dof_map.h:1871
std::vector< std::unique_ptr< DirichletBoundaries > > _adjoint_dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition: dof_map.h:2064
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Data structure containing periodic boundaries.
Definition: dof_map.h:2050
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:2086
std::unique_ptr< DefaultCoupling > _default_coupling
The default coupling GhostingFunctor, used to implement standard libMesh sparsity pattern constructio...
Definition: dof_map.h:1933
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
std::vector< Variable > _variables
The finite element type for each variable.
Definition: dof_map.h:1839
DofConstraints _stashed_dof_constraints
Definition: dof_map.h:2030
SparsityPattern::AugmentSparsityPattern * _augment_sparsity_pattern
Function object to call to add extra entries to the sparsity pattern.
Definition: dof_map.h:1898
dof_id_type _n_old_dfs
Total number of degrees of freedom on old dof objects.
Definition: dof_map.h:2001
std::vector< dof_id_type > _end_df
Last DOF index (plus 1) on processor p.
Definition: dof_map.h:1881
std::vector< dof_id_type > _first_df
First DOF index on processor p.
Definition: dof_map.h:1876
MeshBase & _mesh
The mesh that system uses.
Definition: dof_map.h:1864
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:1903
std::unique_ptr< DefaultCoupling > _default_evaluating
The default algebraic GhostingFunctor, used to implement standard libMesh send_list construction...
Definition: dof_map.h:1941
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:1920
std::vector< unsigned int > _variable_group_numbers
The variable group number for each variable.
Definition: dof_map.h:1849
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:1886
dof_id_type _n_dfs
Total number of degrees of freedom.
Definition: dof_map.h:1988
NodeConstraints _node_constraints
Data structure containing DofObject constraints.
Definition: dof_map.h:2041
libMesh::DofMap::~DofMap ( )

Destructor.

在文件 dof_map.C206 行定义.

参考 _default_coupling, _default_evaluating, _mesh , 以及 clear().

207 {
208  this->clear();
209 
210  // clear() resets all but the default DofMap-based functors. We
211  // need to remove those from the mesh too before we die.
212  _mesh.remove_ghosting_functor(*_default_coupling);
213  _mesh.remove_ghosting_functor(*_default_evaluating);
214 }
void clear()
Free all new memory associated with the object, but restore its original state, with the mesh pointer...
Definition: dof_map.C:850
std::unique_ptr< DefaultCoupling > _default_coupling
The default coupling GhostingFunctor, used to implement standard libMesh sparsity pattern constructio...
Definition: dof_map.h:1933
MeshBase & _mesh
The mesh that system uses.
Definition: dof_map.h:1864
std::unique_ptr< DefaultCoupling > _default_evaluating
The default algebraic GhostingFunctor, used to implement standard libMesh send_list construction...
Definition: dof_map.h:1941

成员函数说明

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

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

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

在文件 dof_map.C2381 行定义.

参考 _dont_p_refine, libMesh::Variable::active_on_subdomain(), libMesh::DofObject::invalid_id, n_dofs(), sys_number(), libMesh::Variable::type() , 以及 variable_group().

参考自 dof_indices().

2394 {
2395  const VariableGroup & var = this->variable_group(vg);
2396 
2397  if (var.active_on_subdomain(elem.subdomain_id()))
2398  {
2399  const ElemType type = elem.type();
2400  const unsigned int sys_num = this->sys_number();
2401 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2402  const bool is_inf = elem.infinite();
2403 #endif
2404 
2405  const bool extra_hanging_dofs =
2406  FEInterface::extra_hanging_dofs(var.type());
2407 
2408  FEType fe_type = var.type();
2409 
2410  const bool add_p_level =
2411 #ifdef LIBMESH_ENABLE_AMR
2412  !_dont_p_refine.count(vg);
2413 #else
2414  false;
2415 #endif
2416 
2417 #ifdef DEBUG
2418  // The number of dofs per element is non-static for subdivision FE
2419  if (var.type().family == SUBDIVISION)
2420  tot_size += n_nodes;
2421  else
2422  // FIXME: Is the passed-in p_level just elem.p_level()? If so,
2423  // this seems redundant.
2424  tot_size += FEInterface::n_dofs(fe_type, add_p_level*p_level, &elem);
2425 #endif
2426 
2427  // The total Order is not required when getting the function
2428  // pointer, it is only needed when the function is called (see
2429  // below).
2430  const FEInterface::n_dofs_at_node_ptr ndan =
2431  FEInterface::n_dofs_at_node_function(fe_type, &elem);
2432 
2433  // Get the node-based DOF numbers
2434  for (unsigned int n=0; n != n_nodes; n++)
2435  {
2436  const Node & node = *nodes[n];
2437 
2438  // Cache the intermediate lookups that are common to every
2439  // component
2440 #ifdef DEBUG
2441  const std::pair<unsigned int, unsigned int>
2442  vg_and_offset = node.var_to_vg_and_offset(sys_num,v);
2443  libmesh_assert_equal_to (vg, vg_and_offset.first);
2444  libmesh_assert_equal_to (vig, vg_and_offset.second);
2445 #endif
2446  const unsigned int n_comp = node.n_comp_group(sys_num,vg);
2447 
2448  // There is a potential problem with h refinement. Imagine a
2449  // quad9 that has a linear FE on it. Then, on the hanging side,
2450  // it can falsely identify a DOF at the mid-edge node. This is why
2451  // we go through FEInterface instead of node.n_comp() directly.
2452  const unsigned int nc =
2453 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2454  is_inf ?
2455  FEInterface::n_dofs_at_node(fe_type, add_p_level*p_level, &elem, n) :
2456 #endif
2457  ndan (type, static_cast<Order>(fe_type.order + add_p_level*p_level), n);
2458 
2459  // If this is a non-vertex on a hanging node with extra
2460  // degrees of freedom, we use the non-vertex dofs (which
2461  // come in reverse order starting from the end, to
2462  // simplify p refinement)
2463  if (extra_hanging_dofs && !elem.is_vertex(n))
2464  {
2465  const int dof_offset = n_comp - nc;
2466 
2467  // We should never have fewer dofs than necessary on a
2468  // node unless we're getting indices on a parent element,
2469  // and we should never need the indices on such a node
2470  if (dof_offset < 0)
2471  {
2472  libmesh_assert(!elem.active());
2473  di.resize(di.size() + nc, DofObject::invalid_id);
2474  }
2475  else
2476  for (int i=int(n_comp)-1; i>=dof_offset; i--)
2477  {
2478  const dof_id_type d =
2479  node.dof_number(sys_num, vg, vig, i, n_comp);
2480  libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2481  di.push_back(d);
2482  }
2483  }
2484  // If this is a vertex or an element without extra hanging
2485  // dofs, our dofs come in forward order coming from the
2486  // beginning
2487  else
2488  {
2489  // We have a good component index only if it's being
2490  // used on this FE type (nc) *and* it's available on
2491  // this DofObject (n_comp).
2492  const unsigned int good_nc = std::min(n_comp, nc);
2493  for (unsigned int i=0; i!=good_nc; ++i)
2494  {
2495  const dof_id_type d =
2496  node.dof_number(sys_num, vg, vig, i, n_comp);
2497  libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2498  libmesh_assert_less (d, this->n_dofs());
2499  di.push_back(d);
2500  }
2501 
2502  // With fewer good component indices than we need, e.g.
2503  // due to subdomain expansion, the remaining expected
2504  // indices are marked invalid.
2505  if (n_comp < nc)
2506  for (unsigned int i=n_comp; i!=nc; ++i)
2507  di.push_back(DofObject::invalid_id);
2508  }
2509  }
2510 
2511  // If there are any element-based DOF numbers, get them
2512  const unsigned int nc = FEInterface::n_dofs_per_elem(fe_type, add_p_level*p_level, &elem);
2513 
2514  // We should never have fewer dofs than necessary on an
2515  // element unless we're getting indices on a parent element
2516  // (and we should never need those indices) or off-domain for a
2517  // subdomain-restricted variable (where invalid_id is the
2518  // correct thing to return)
2519  if (nc != 0)
2520  {
2521  const unsigned int n_comp = elem.n_comp_group(sys_num,vg);
2522  if (elem.n_systems() > sys_num && nc <= n_comp)
2523  {
2524  for (unsigned int i=0; i<nc; i++)
2525  {
2526  const dof_id_type d =
2527  elem.dof_number(sys_num, vg, vig, i, n_comp);
2528  libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2529 
2530  di.push_back(d);
2531  }
2532  }
2533  else
2534  {
2535  libmesh_assert(!elem.active() || fe_type.family == LAGRANGE || fe_type.family == SUBDIVISION);
2536  di.resize(di.size() + nc, DofObject::invalid_id);
2537  }
2538  }
2539  }
2540 }
dof_id_type n_dofs() const
Definition: dof_map.h:659
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:2101
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:477
unsigned int sys_number() const
Definition: dof_map.h:2093
std::unordered_set< unsigned int > _dont_p_refine
A container of variable groups that we should not p-refine.
Definition: dof_map.h:2022
uint8_t dof_id_type
Definition: id_types.h:67
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.

在文件 dof_map.C2296 行定义.

参考 _dont_p_refine, libMesh::DofObject::dof_number(), libMesh::DofObject::invalid_id, libMesh::DofObject::n_comp_group(), sys_number(), libMesh::Variable::type(), libMesh::DofObject::var_to_vg_and_offset() , 以及 variable_group().

参考自 dof_indices() , 以及 old_dof_indices().

2301 {
2302  // Half of this is a cut and paste of _dof_indices code below, but
2303  // duplication actually seems cleaner than creating a helper
2304  // function with a million arguments and hoping the compiler inlines
2305  // it properly into one of our most highly trafficked functions.
2306 
2307  LOG_SCOPE("_node_dof_indices()", "DofMap");
2308 
2309  const unsigned int sys_num = this->sys_number();
2310  const auto [vg, vig] =
2311  obj.var_to_vg_and_offset(sys_num,vn);
2312  const unsigned int n_comp = obj.n_comp_group(sys_num,vg);
2313 
2314  const VariableGroup & var = this->variable_group(vg);
2315  FEType fe_type = var.type();
2316  const bool extra_hanging_dofs =
2317  FEInterface::extra_hanging_dofs(fe_type);
2318 
2319  const bool add_p_level =
2320 #ifdef LIBMESH_ENABLE_AMR
2321  !_dont_p_refine.count(vg);
2322 #else
2323  false;
2324 #endif
2325 
2326  // There is a potential problem with h refinement. Imagine a
2327  // quad9 that has a linear FE on it. Then, on the hanging side,
2328  // it can falsely identify a DOF at the mid-edge node. This is why
2329  // we go through FEInterface instead of obj->n_comp() directly.
2330  const unsigned int nc =
2331  FEInterface::n_dofs_at_node(fe_type, &elem, n, add_p_level);
2332 
2333  // If this is a non-vertex on a hanging node with extra
2334  // degrees of freedom, we use the non-vertex dofs (which
2335  // come in reverse order starting from the end, to
2336  // simplify p refinement)
2337  if (extra_hanging_dofs && nc && !elem.is_vertex(n))
2338  {
2339  const int dof_offset = n_comp - nc;
2340 
2341  // We should never have fewer dofs than necessary on a
2342  // node unless we're getting indices on a parent element,
2343  // and we should never need the indices on such a node
2344  if (dof_offset < 0)
2345  {
2346  libmesh_assert(!elem.active());
2347  di.resize(di.size() + nc, DofObject::invalid_id);
2348  }
2349  else
2350  for (unsigned int i = dof_offset; i != n_comp; ++i)
2351  {
2352  const dof_id_type d =
2353  obj.dof_number(sys_num, vg, vig, i, n_comp);
2354  libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2355  di.push_back(d);
2356  }
2357  }
2358  // If this is a vertex or an element without extra hanging
2359  // dofs, our dofs come in forward order coming from the
2360  // beginning. But we still might not have all those dofs, in cases
2361  // where a subdomain-restricted variable just had its subdomain
2362  // expanded.
2363  else
2364  {
2365  const unsigned int good_nc =
2366  std::min(static_cast<unsigned int>(n_comp), nc);
2367  for (unsigned int i=0; i != good_nc; ++i)
2368  {
2369  const dof_id_type d =
2370  obj.dof_number(sys_num, vg, vig, i, n_comp);
2371  libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2372  di.push_back(d);
2373  }
2374  for (unsigned int i=good_nc; i != nc; ++i)
2375  di.push_back(DofObject::invalid_id);
2376  }
2377 }
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:2101
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:477
unsigned int sys_number() const
Definition: dof_map.h:2093
std::unordered_set< unsigned int > _dont_p_refine
A container of variable groups that we should not p-refine.
Definition: dof_map.h:2022
uint8_t dof_id_type
Definition: id_types.h:67
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.

在文件 dof_map_constraints.C2218 行定义.

参考 _adjoint_constraint_values , 以及 is_constrained_dof().

2223 {
2224  // Optionally allow the user to overwrite constraints. Defaults to false.
2225  if (forbid_constraint_overwrite)
2226  {
2227  libmesh_error_msg_if(!this->is_constrained_dof(dof_number),
2228  "ERROR: DOF " << dof_number << " has no corresponding primal constraint!");
2229 #ifndef NDEBUG
2230  // No way to do this without a non-normalized tolerance?
2231 
2232  // // If the user passed in more than just the rhs, let's check the
2233  // // coefficients for consistency
2234  // if (!constraint_row.empty())
2235  // {
2236  // DofConstraintRow row = _dof_constraints[dof_number];
2237  // for (const auto & [dof, val] : row)
2238  // libmesh_assert(constraint_row.find(dof)->second == val);
2239  // }
2240  //
2241  // if (_adjoint_constraint_values[qoi_index].find(dof_number) !=
2242  // _adjoint_constraint_values[qoi_index].end())
2243  // libmesh_assert_equal_to(_adjoint_constraint_values[qoi_index][dof_number],
2244  // constraint_rhs);
2245 
2246 #endif
2247  }
2248 
2249  // Creates the map of rhs values if it doesn't already exist; then
2250  // adds the current value to that map
2251 
2252  // We don't get insert_or_assign until C++17 so we make do.
2253  std::pair<DofConstraintValueMap::iterator, bool> rhs_it =
2254  _adjoint_constraint_values[qoi_index].emplace(dof_number, constraint_rhs);
2255  if (!rhs_it.second)
2256  rhs_it.first->second = constraint_rhs;
2257 }
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:2034
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
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.

在文件 dof_map_constraints.C5456 行定义.

参考 _adjoint_dirichlet_boundaries.

5458 {
5459  unsigned int old_size = cast_int<unsigned int>
5461  for (unsigned int i = old_size; i <= qoi_index; ++i)
5462  _adjoint_dirichlet_boundaries.push_back(std::make_unique<DirichletBoundaries>());
5463 
5464  // Make copy of DirichletBoundary, owned by _adjoint_dirichlet_boundaries
5465  _adjoint_dirichlet_boundaries[qoi_index]->push_back
5466  (std::make_unique<DirichletBoundary>(dirichlet_boundary));
5467 }
std::vector< std::unique_ptr< DirichletBoundaries > > _adjoint_dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition: dof_map.h:2064
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.

在文件 dof_map.C1886 行定义.

参考 _algebraic_ghosting_functors , 以及 _mesh.

参考自 add_algebraic_ghosting_functor(), add_default_ghosting(), clear() , 以及 DofMap().

1888 {
1889  _algebraic_ghosting_functors.insert(&evaluable_functor);
1890  evaluable_functor.set_mesh(&_mesh);
1891  if (to_mesh)
1892  _mesh.add_ghosting_functor(evaluable_functor);
1893 }
std::set< GhostingFunctor * > _algebraic_ghosting_functors
The list of all GhostingFunctor objects to be used when distributing ghosted vectors.
Definition: dof_map.h:1951
MeshBase & _mesh
The mesh that system uses.
Definition: dof_map.h:1864
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.

在文件 dof_map.h391 行定义.

参考 _shared_functors , 以及 add_algebraic_ghosting_functor().

393  { _shared_functors[evaluable_functor.get()] = evaluable_functor;
394  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:1970
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:1886
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.

在文件 dof_map_constraints.C2183 行定义.

参考 _dof_constraints, _primal_constraint_values, is_constrained_dof() , 以及 n_dofs().

参考自 add_constraint_row() , 以及 process_mesh_constraint_rows().

2187 {
2188  // Optionally allow the user to overwrite constraints. Defaults to false.
2189  libmesh_error_msg_if(forbid_constraint_overwrite && this->is_constrained_dof(dof_number),
2190  "ERROR: DOF " << dof_number << " was already constrained!");
2191 
2192  libmesh_assert_less(dof_number, this->n_dofs());
2193 
2194  // There is an implied "1" on the diagonal of the constraint row, and the user
2195  // should not try to manually set _any_ value on the diagonal.
2196  libmesh_assert_msg(!constraint_row.count(dof_number),
2197  "Error: constraint_row for dof " << dof_number <<
2198  " should not contain an entry for dof " << dof_number);
2199 
2200 #ifndef NDEBUG
2201  for (const auto & pr : constraint_row)
2202  libmesh_assert_less(pr.first, this->n_dofs());
2203 #endif
2204 
2205  // We don't get insert_or_assign until C++17 so we make do.
2206  std::pair<DofConstraints::iterator, bool> it =
2207  _dof_constraints.emplace(dof_number, constraint_row);
2208  if (!it.second)
2209  it.first->second = constraint_row;
2210 
2211  std::pair<DofConstraintValueMap::iterator, bool> rhs_it =
2212  _primal_constraint_values.emplace(dof_number, constraint_rhs);
2213  if (!rhs_it.second)
2214  rhs_it.first->second = constraint_rhs;
2215 }
dof_id_type n_dofs() const
Definition: dof_map.h:659
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
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.

在文件 dof_map.h1002 行定义.

参考 add_constraint_row().

1005  { 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 ...
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.

在文件 dof_map_constraints.C5349 行定义.

参考 _dof_constraints, _send_list , 以及 local_index().

参考自 process_constraints().

5350 {
5351  // This function must be run on all processors at once
5352  parallel_object_only();
5353 
5354  // Return immediately if there's nothing to gather
5355  if (this->n_processors() == 1)
5356  return;
5357 
5358  // We might get to return immediately if none of the processors
5359  // found any constraints
5360  unsigned int has_constraints = !_dof_constraints.empty();
5361  this->comm().max(has_constraints);
5362  if (!has_constraints)
5363  return;
5364 
5365  for (const auto & [constrained_dof, constraint_row] : _dof_constraints)
5366  {
5367  // We only need the dependencies of our own constrained dofs
5368  if (!this->local_index(constrained_dof))
5369  continue;
5370 
5371  for (const auto & j : constraint_row)
5372  {
5373  dof_id_type constraint_dependency = j.first;
5374 
5375  // No point in adding one of our own dofs to the send_list
5376  if (this->local_index(constraint_dependency))
5377  continue;
5378 
5379  _send_list.push_back(constraint_dependency);
5380  }
5381  }
5382 }
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:1893
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:831
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
uint8_t dof_id_type
Definition: id_types.h:67
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.

在文件 dof_map.C1861 行定义.

参考 _coupling_functors , 以及 _mesh.

参考自 add_coupling_functor(), add_default_ghosting(), clear() , 以及 DofMap().

1863 {
1864  _coupling_functors.insert(&coupling_functor);
1865  coupling_functor.set_mesh(&_mesh);
1866  if (to_mesh)
1867  _mesh.add_ghosting_functor(coupling_functor);
1868 }
std::set< GhostingFunctor * > _coupling_functors
The list of all GhostingFunctor objects to be used when coupling degrees of freedom in matrix sparsit...
Definition: dof_map.h:1964
MeshBase & _mesh
The mesh that system uses.
Definition: dof_map.h:1864
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.

在文件 dof_map.h329 行定义.

参考 _shared_functors , 以及 add_coupling_functor().

331  { _shared_functors[coupling_functor.get()] = coupling_functor;
332  this->add_coupling_functor(*coupling_functor, to_mesh); }
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:1861
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:1970
void libMesh::DofMap::add_default_ghosting ( )

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

User-added ghosting functors will be unaffected.

在文件 dof_map.C1852 行定义.

参考 add_algebraic_ghosting_functor(), add_coupling_functor(), default_algebraic_ghosting() , 以及 default_coupling().

1853 {
1854  this->add_coupling_functor(this->default_coupling());
1856 }
DefaultCoupling & default_coupling()
Default coupling functor.
Definition: dof_map.h:356
DefaultCoupling & default_algebraic_ghosting()
Default algebraic ghosting functor.
Definition: dof_map.h:418
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:1861
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:1886
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.

在文件 dof_map_constraints.C5450 行定义.

参考 _dirichlet_boundaries.

5451 {
5452  _dirichlet_boundaries->push_back(std::make_unique<DirichletBoundary>(dirichlet_boundary));
5453 }
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition: dof_map.h:2058
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.

在文件 dof_map.C1544 行定义.

参考 _send_list, algebraic_ghosting_functors_begin(), algebraic_ghosting_functors_end(), coupling_functors_begin(), coupling_functors_end(), dof_indices(), libMesh::DofObject::invalid_id, local_index(), merge_ghost_functor_outputs(), n_dofs() , 以及 n_variables().

参考自 distribute_dofs() , 以及 reinit_send_list().

1545 {
1546  LOG_SCOPE("add_neighbors_to_send_list()", "DofMap");
1547 
1548  // Return immediately if there's no ghost data
1549  if (this->n_processors() == 1)
1550  return;
1551 
1552  const unsigned int n_var = this->n_variables();
1553 
1554  MeshBase::const_element_iterator local_elem_it
1555  = mesh.active_local_elements_begin();
1556  const MeshBase::const_element_iterator local_elem_end
1557  = mesh.active_local_elements_end();
1558 
1559  GhostingFunctor::map_type elements_to_send;
1560  DofMap::CouplingMatricesSet temporary_coupling_matrices;
1561 
1562  // We need to add dofs to the send list if they've been directly
1563  // requested by an algebraic ghosting functor or they've been
1564  // indirectly requested by a coupling functor.
1565  this->merge_ghost_functor_outputs(elements_to_send,
1566  temporary_coupling_matrices,
1569  local_elem_it, local_elem_end, mesh.processor_id());
1570 
1571  this->merge_ghost_functor_outputs(elements_to_send,
1572  temporary_coupling_matrices,
1573  this->coupling_functors_begin(),
1574  this->coupling_functors_end(),
1575  local_elem_it, local_elem_end, mesh.processor_id());
1576 
1577  // Making a list of non-zero coupling matrix columns is an
1578  // O(N_var^2) operation. We cache it so we only have to do it once
1579  // per CouplingMatrix and not once per element.
1580  std::map<const CouplingMatrix *, std::vector<unsigned int>>
1581  column_variable_lists;
1582 
1583  for (const auto & [partner, ghost_coupling] : elements_to_send)
1584  {
1585  // We asked ghosting functors not to give us local elements
1586  libmesh_assert_not_equal_to
1587  (partner->processor_id(), this->processor_id());
1588 
1589  // Loop over any present coupling matrix column variables if we
1590  // have a coupling matrix, or just add all variables to
1591  // send_list if not.
1592  if (ghost_coupling)
1593  {
1594  libmesh_assert_equal_to (ghost_coupling->size(), n_var);
1595 
1596  // Try to find a cached list of column variables.
1597  std::map<const CouplingMatrix *, std::vector<unsigned int>>::const_iterator
1598  column_variable_list = column_variable_lists.find(ghost_coupling);
1599 
1600  // If we didn't find it, then we need to create it.
1601  if (column_variable_list == column_variable_lists.end())
1602  {
1603  auto inserted_variable_list_pair =
1604  column_variable_lists.emplace(ghost_coupling, std::vector<unsigned int>());
1605  column_variable_list = inserted_variable_list_pair.first;
1606 
1607  std::vector<unsigned int> & new_variable_list =
1608  inserted_variable_list_pair.first->second;
1609 
1610  std::vector<unsigned char> has_variable(n_var, false);
1611 
1612  for (unsigned int vi = 0; vi != n_var; ++vi)
1613  {
1614  ConstCouplingRow ccr(vi, *ghost_coupling);
1615 
1616  for (const auto & vj : ccr)
1617  has_variable[vj] = true;
1618  }
1619  for (unsigned int vj = 0; vj != n_var; ++vj)
1620  {
1621  if (has_variable[vj])
1622  new_variable_list.push_back(vj);
1623  }
1624  }
1625 
1626  const std::vector<unsigned int> & variable_list =
1627  column_variable_list->second;
1628 
1629  for (const auto & vj : variable_list)
1630  {
1631  std::vector<dof_id_type> di;
1632  this->dof_indices (partner, di, vj);
1633 
1634  // Insert the remote DOF indices into the send list
1635  for (auto d : di)
1636  if (d != DofObject::invalid_id &&
1637  !this->local_index(d))
1638  {
1639  libmesh_assert_less(d, this->n_dofs());
1640  _send_list.push_back(d);
1641  }
1642  }
1643  }
1644  else
1645  {
1646  std::vector<dof_id_type> di;
1647  this->dof_indices (partner, di);
1648 
1649  // Insert the remote DOF indices into the send list
1650  for (const auto & dof : di)
1651  if (dof != DofObject::invalid_id &&
1652  !this->local_index(dof))
1653  {
1654  libmesh_assert_less(dof, this->n_dofs());
1655  _send_list.push_back(dof);
1656  }
1657  }
1658 
1659  }
1660 
1661  // We're now done with any merged coupling matrices we had to create.
1662  temporary_coupling_matrices.clear();
1663 
1664  //-------------------------------------------------------------------------
1665  // Our coupling functors added dofs from neighboring elements to the
1666  // send list, but we may still need to add non-local dofs from local
1667  // elements.
1668  //-------------------------------------------------------------------------
1669 
1670  // Loop over the active local elements, adding all active elements
1671  // that neighbor an active local element to the send list.
1672  for ( ; local_elem_it != local_elem_end; ++local_elem_it)
1673  {
1674  const Elem * elem = *local_elem_it;
1675 
1676  std::vector<dof_id_type> di;
1677  this->dof_indices (elem, di);
1678 
1679  // Insert the remote DOF indices into the send list
1680  for (const auto & dof : di)
1681  if (dof != DofObject::invalid_id &&
1682  !this->local_index(dof))
1683  {
1684  libmesh_assert_less(dof, this->n_dofs());
1685  _send_list.push_back(dof);
1686  }
1687  }
1688 }
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_begin() const
Beginning of range of algebraic ghosting functors.
Definition: dof_map.h:406
std::set< GhostingFunctor * >::const_iterator coupling_functors_begin() const
Beginning of range of coupling functors.
Definition: dof_map.h:344
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:1893
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:831
dof_id_type n_dofs() const
Definition: dof_map.h:659
std::set< std::unique_ptr< CouplingMatrix >, Utility::CompareUnderlying > CouplingMatricesSet
Definition: dof_map.h:1742
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:477
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_end() const
End of range of algebraic ghosting functors.
Definition: dof_map.h:412
unsigned int n_variables() const
Definition: dof_map.h:621
static void merge_ghost_functor_outputs(GhostingFunctor::map_type &elements_to_ghost, CouplingMatricesSet &temporary_coupling_matrices, const std::set< GhostingFunctor * >::iterator &gf_begin, const std::set< GhostingFunctor * >::iterator &gf_end, const MeshBase::const_element_iterator &elems_begin, const MeshBase::const_element_iterator &elems_end, processor_id_type p)
Definition: dof_map.C:1440
std::set< GhostingFunctor * >::const_iterator coupling_functors_end() const
End of range of coupling functors.
Definition: dof_map.h:350
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Fills the vector di with the global degree of freedom indices for the element.
Definition: dof_map.C:1992
void libMesh::DofMap::add_periodic_boundary ( const PeriodicBoundaryBase periodic_boundary)

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

在文件 dof_map_constraints.C5570 行定义.

参考 _periodic_boundaries, libMesh::PeriodicBoundaryBase::clone(), libMesh::PeriodicBoundaryBase::INVERSE, libMesh::PeriodicBoundaryBase::merge(), libMesh::PeriodicBoundaryBase::myboundary , 以及 libMesh::PeriodicBoundaryBase::pairedboundary.

5571 {
5572  // See if we already have a periodic boundary associated myboundary...
5573  PeriodicBoundaryBase * existing_boundary = _periodic_boundaries->boundary(periodic_boundary.myboundary);
5574 
5575  if (!existing_boundary)
5576  {
5577  // ...if not, clone the input (and its inverse) and add them to the PeriodicBoundaries object
5578  // Pass the pairedboundary of the original as the boundary id of the inverse clone.
5579  _periodic_boundaries->emplace(periodic_boundary.myboundary, periodic_boundary.clone());
5580  _periodic_boundaries->emplace(periodic_boundary.pairedboundary, periodic_boundary.clone(PeriodicBoundaryBase::INVERSE));
5581  }
5582  else
5583  {
5584  // ...otherwise, merge this object's variable IDs with the existing boundary object's.
5585  existing_boundary->merge(periodic_boundary);
5586 
5587  // Do the same merging process for the inverse boundary. Note: the inverse better already exist!
5588  PeriodicBoundaryBase * inverse_boundary = _periodic_boundaries->boundary(periodic_boundary.pairedboundary);
5589  libmesh_assert(inverse_boundary);
5590  inverse_boundary->merge(periodic_boundary);
5591  }
5592 }
void merge(const PeriodicBoundaryBase &pb)
boundary_id_type myboundary
The boundary ID of this boundary and its counterpart.
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...
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Data structure containing periodic boundaries.
Definition: dof_map.h:2050
The base class for defining periodic boundaries.
void libMesh::DofMap::add_periodic_boundary ( const PeriodicBoundaryBase boundary,
const PeriodicBoundaryBase inverse_boundary 
)

Add a periodic boundary pair.

参数
boundary- primary boundary
inverse_boundary- inverse boundary

在文件 dof_map_constraints.C5597 行定义.

参考 _periodic_boundaries, libMesh::PeriodicBoundaryBase::clone(), libMesh::PeriodicBoundaryBase::myboundary , 以及 libMesh::PeriodicBoundaryBase::pairedboundary.

5599 {
5600  libmesh_assert_equal_to (boundary.myboundary, inverse_boundary.pairedboundary);
5601  libmesh_assert_equal_to (boundary.pairedboundary, inverse_boundary.myboundary);
5602 
5603  // Store clones of the passed-in objects. These will be cleaned up
5604  // automatically in the _periodic_boundaries destructor.
5605  _periodic_boundaries->emplace(boundary.myboundary, boundary.clone());
5606  _periodic_boundaries->emplace(inverse_boundary.myboundary, inverse_boundary.clone());
5607 }
boundary_id_type myboundary
The boundary ID of this boundary and its counterpart.
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...
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Data structure containing periodic boundaries.
Definition: dof_map.h:2050
void libMesh::DofMap::add_variable_group ( VariableGroup  var_group)

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

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

在文件 dof_map.C252 行定义.

参考 _var_to_vg, _variable_group_numbers, _variable_groups, _variables , 以及 libMesh::VariableGroup::n_variables().

253 {
254  // Ensure that we are not duplicating an existing entry in _variable_groups
255  if (std::find(_variable_groups.begin(), _variable_groups.end(), var_group) == _variable_groups.end())
256  {
257  const unsigned int vg = cast_int<unsigned int>(_variable_groups.size());
258 
259  _variable_groups.push_back(std::move(var_group));
260 
261  VariableGroup & new_var_group = _variable_groups.back();
262 
263  for (auto var : make_range(new_var_group.n_variables()))
264  {
265  auto var_instance = new_var_group(var);
266  const auto vn = var_instance.number();
267  _variables.push_back (std::move(var_instance));
268  _variable_group_numbers.push_back (vg);
269  _var_to_vg.emplace(vn, vg);
270  }
271  }
272  // End if check for var_group in _variable_groups
273 
274 }
std::vector< VariableGroup > _variable_groups
The finite element type for each variable group.
Definition: dof_map.h:1844
std::unordered_map< unsigned int, unsigned int > _var_to_vg
A map from variable number to variable group number.
Definition: dof_map.h:1854
std::vector< Variable > _variables
The finite element type for each variable.
Definition: dof_map.h:1839
std::vector< unsigned int > _variable_group_numbers
The variable group number for each variable.
Definition: dof_map.h:1849
std::set<GhostingFunctor *>::const_iterator libMesh::DofMap::algebraic_ghosting_functors_begin ( ) const
inline

Beginning of range of algebraic ghosting functors.

在文件 dof_map.h406 行定义.

参考 _algebraic_ghosting_functors.

参考自 add_neighbors_to_send_list().

407  { return _algebraic_ghosting_functors.begin(); }
std::set< GhostingFunctor * > _algebraic_ghosting_functors
The list of all GhostingFunctor objects to be used when distributing ghosted vectors.
Definition: dof_map.h:1951
std::set<GhostingFunctor *>::const_iterator libMesh::DofMap::algebraic_ghosting_functors_end ( ) const
inline

End of range of algebraic ghosting functors.

在文件 dof_map.h412 行定义.

参考 _algebraic_ghosting_functors.

参考自 add_neighbors_to_send_list().

413  { return _algebraic_ghosting_functors.end(); }
std::set< GhostingFunctor * > _algebraic_ghosting_functors
The list of all GhostingFunctor objects to be used when distributing ghosted vectors.
Definition: dof_map.h:1951
bool libMesh::DofMap::all_semilocal_indices ( const std::vector< dof_id_type > &  dof_indices) const
返回
true if all degree of freedom indices in dof_indices are either local indices or in the send_list.
注解
This is an O(logN) operation for a send_list of size N; we don't cache enough information for O(1) right now.

在文件 dof_map.C2596 行定义.

参考 semilocal_index().

参考自 is_evaluable().

2597 {
2598  // We're all semilocal unless we find a counterexample
2599  for (const auto & di : dof_indices_in)
2600  if (!this->semilocal_index(di))
2601  return false;
2602 
2603  return true;
2604 }
bool semilocal_index(dof_id_type dof_index) const
Definition: dof_map.C:2580
void libMesh::DofMap::allgather_recursive_constraints ( MeshBase &  mesh)

Gathers constraint equation dependencies from other processors.

在文件 dof_map_constraints.C3708 行定义.

参考 _adjoint_constraint_values, _dof_constraints, _node_constraints, _primal_constraint_values, gather_constraints(), libMesh::DofObject::invalid_id, is_constrained_dof(), is_constrained_node(), libMesh::libmesh_isnan(), libMesh::Real , 以及 sys_number().

参考自 process_constraints().

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

在文件 dof_map.C1418 行定义.

参考 libMesh::DofObject::invalid_id , 以及 sys_number().

参考自 distribute_local_dofs_node_major() , 以及 distribute_local_dofs_var_major().

1419 {
1420  MeshTools::libmesh_assert_valid_procids<Node>(mesh);
1421 
1422  for (auto & node : mesh.local_node_ptr_range())
1423  {
1424  unsigned int n_var_g = node->n_var_groups(this->sys_number());
1425  for (unsigned int vg=0; vg != n_var_g; ++vg)
1426  {
1427  unsigned int n_comp_g =
1428  node->n_comp_group(this->sys_number(), vg);
1429  dof_id_type my_first_dof = n_comp_g ?
1430  node->vg_dof_base(this->sys_number(), vg) : 0;
1431  libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
1432  }
1433  }
1434 }
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:477
unsigned int sys_number() const
Definition: dof_map.h:2093
uint8_t dof_id_type
Definition: id_types.h:67
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.

在文件 dof_map.h468 行定义.

参考 _extra_send_list_context , 以及 _extra_send_list_function.

void * _extra_send_list_context
A pointer associated with the extra send list that can optionally be passed in.
Definition: dof_map.h:1925
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:1920
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!

在文件 dof_map.h459 行定义.

参考 _augment_send_list.

460  {
461  _augment_send_list = &asl;
462  }
AugmentSendList * _augment_send_list
Function object to call to add extra entries to the send list.
Definition: dof_map.h:1915
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!

在文件 dof_map.h445 行定义.

参考 _extra_sparsity_context , 以及 _extra_sparsity_function.

void * _extra_sparsity_context
A pointer associated with the extra sparsity that can optionally be passed in.
Definition: dof_map.h:1910
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:1903
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!

在文件 dof_map.h430 行定义.

参考 _augment_sparsity_pattern.

431  {
433  }
SparsityPattern::AugmentSparsityPattern * _augment_sparsity_pattern
Function object to call to add extra entries to the sparsity pattern.
Definition: dof_map.h:1898
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.

在文件 dof_map.C278 行定义.

参考 _matrices, libMesh::SparseMatrix< T >::need_full_sparsity_pattern(), need_full_sparsity_pattern , 以及 update_sparsity_pattern().

279 {
280  parallel_object_only();
281 
282  // We shouldn't be trying to re-attach the same matrices repeatedly
283  libmesh_assert (std::find(_matrices.begin(), _matrices.end(),
284  &matrix) == _matrices.end());
285 
286  _matrices.push_back(&matrix);
287 
288  this->update_sparsity_pattern(matrix);
289 
290  if (matrix.need_full_sparsity_pattern())
292 }
bool need_full_sparsity_pattern
Default false; set to true if any attached matrix requires a full sparsity pattern.
Definition: dof_map.h:1976
void update_sparsity_pattern(SparseMatrix< Number > &matrix) const
Additional matrices may be be temporarily initialized by this DofMap.
Definition: dof_map.C:307
std::vector< SparseMatrix< Number > * > _matrices
Additional matrices handled by this object.
Definition: dof_map.h:1871
unsigned int libMesh::DofMap::block_size ( ) const
inline
返回
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.

在文件 dof_map.h651 行定义.

参考 has_blocked_representation() , 以及 n_variables().

652  {
653  return (this->has_blocked_representation() ? this->n_variables() : 1);
654  }
unsigned int n_variables() const
Definition: dof_map.h:621
bool has_blocked_representation() const
Definition: dof_map.h:634
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.

在文件 dof_map_constraints.C3459 行定义.

参考 _dof_constraints, is_constrained_dof(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::resize() , 以及 libMesh::DenseMatrix< T >::right_multiply().

参考自 constrain_element_dyad_matrix(), constrain_element_matrix(), constrain_element_matrix_and_vector(), constrain_element_vector(), constrain_nothing() , 以及 max_constraint_error().

3462 {
3463  LOG_SCOPE_IF("build_constraint_matrix()", "DofMap", !called_recursively);
3464 
3465  // Create a set containing the DOFs we already depend on
3466  typedef std::set<dof_id_type> RCSet;
3467  RCSet dof_set;
3468 
3469  bool we_have_constraints = false;
3470 
3471  // Next insert any other dofs the current dofs might be constrained
3472  // in terms of. Note that in this case we may not be done: Those
3473  // may in turn depend on others. So, we need to repeat this process
3474  // in that case until the system depends only on unconstrained
3475  // degrees of freedom.
3476  for (const auto & dof : elem_dofs)
3477  if (this->is_constrained_dof(dof))
3478  {
3479  we_have_constraints = true;
3480 
3481  // If the DOF is constrained
3482  DofConstraints::const_iterator
3483  pos = _dof_constraints.find(dof);
3484 
3485  libmesh_assert (pos != _dof_constraints.end());
3486 
3487  const DofConstraintRow & constraint_row = pos->second;
3488 
3489  // Constraint rows in p refinement may be empty
3490  //libmesh_assert (!constraint_row.empty());
3491 
3492  for (const auto & item : constraint_row)
3493  dof_set.insert (item.first);
3494  }
3495 
3496  // May be safe to return at this point
3497  // (but remember to stop the perflog)
3498  if (!we_have_constraints)
3499  return;
3500 
3501  for (const auto & dof : elem_dofs)
3502  dof_set.erase (dof);
3503 
3504  // If we added any DOFS then we need to do this recursively.
3505  // It is possible that we just added a DOF that is also
3506  // constrained!
3507  //
3508  // Also, we need to handle the special case of an element having DOFs
3509  // constrained in terms of other, local DOFs
3510  if (!dof_set.empty() || // case 1: constrained in terms of other DOFs
3511  !called_recursively) // case 2: constrained in terms of our own DOFs
3512  {
3513  const unsigned int old_size =
3514  cast_int<unsigned int>(elem_dofs.size());
3515 
3516  // Add new dependency dofs to the end of the current dof set
3517  elem_dofs.insert(elem_dofs.end(),
3518  dof_set.begin(), dof_set.end());
3519 
3520  // Now we can build the constraint matrix.
3521  // Note that resize also zeros for a DenseMatrix<Number>.
3522  C.resize (old_size,
3523  cast_int<unsigned int>(elem_dofs.size()));
3524 
3525  // Create the C constraint matrix.
3526  for (unsigned int i=0; i != old_size; i++)
3527  if (this->is_constrained_dof(elem_dofs[i]))
3528  {
3529  // If the DOF is constrained
3530  DofConstraints::const_iterator
3531  pos = _dof_constraints.find(elem_dofs[i]);
3532 
3533  libmesh_assert (pos != _dof_constraints.end());
3534 
3535  const DofConstraintRow & constraint_row = pos->second;
3536 
3537  // p refinement creates empty constraint rows
3538  // libmesh_assert (!constraint_row.empty());
3539 
3540  for (const auto & item : constraint_row)
3541  for (unsigned int j=0,
3542  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
3543  j != n_elem_dofs; j++)
3544  if (elem_dofs[j] == item.first)
3545  C(i,j) = item.second;
3546  }
3547  else
3548  {
3549  C(i,i) = 1.;
3550  }
3551 
3552  // May need to do this recursively. It is possible
3553  // that we just replaced a constrained DOF with another
3554  // constrained DOF.
3555  DenseMatrix<Number> Cnew;
3556 
3557  this->build_constraint_matrix (Cnew, elem_dofs, true);
3558 
3559  if ((C.n() == Cnew.m()) &&
3560  (Cnew.n() == elem_dofs.size())) // If the constraint matrix
3561  C.right_multiply(Cnew); // is constrained...
3562 
3563  libmesh_assert_equal_to (C.n(), elem_dofs.size());
3564  }
3565 }
unsigned int n() const
返回矩阵的列维度。
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
unsigned int m() const
返回矩阵的行维度。
virtual void right_multiply(const DenseMatrixBase< T > &M2) overridefinal
右乘以矩阵 M2。
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
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 resize(const unsigned int new_m, const unsigned int new_n)
调整矩阵的大小,并调用 zero() 方法。
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:90
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
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.

在文件 dof_map_constraints.C3569 行定义.

参考 _adjoint_constraint_values, _dof_constraints, _primal_constraint_values, is_constrained_dof(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::resize(), libMesh::DenseMatrix< T >::resize(), libMesh::DenseMatrix< T >::right_multiply() , 以及 libMesh::DenseMatrix< T >::vector_mult_add().

参考自 extract_local_vector(), heterogeneously_constrain_element_matrix_and_vector() , 以及 heterogeneously_constrain_element_vector().

3574 {
3575  LOG_SCOPE_IF("build_constraint_matrix_and_vector()", "DofMap", !called_recursively);
3576 
3577  // Create a set containing the DOFs we already depend on
3578  typedef std::set<dof_id_type> RCSet;
3579  RCSet dof_set;
3580 
3581  bool we_have_constraints = false;
3582 
3583  // Next insert any other dofs the current dofs might be constrained
3584  // in terms of. Note that in this case we may not be done: Those
3585  // may in turn depend on others. So, we need to repeat this process
3586  // in that case until the system depends only on unconstrained
3587  // degrees of freedom.
3588  for (const auto & dof : elem_dofs)
3589  if (this->is_constrained_dof(dof))
3590  {
3591  we_have_constraints = true;
3592 
3593  // If the DOF is constrained
3594  DofConstraints::const_iterator
3595  pos = _dof_constraints.find(dof);
3596 
3597  libmesh_assert (pos != _dof_constraints.end());
3598 
3599  const DofConstraintRow & constraint_row = pos->second;
3600 
3601  // Constraint rows in p refinement may be empty
3602  //libmesh_assert (!constraint_row.empty());
3603 
3604  for (const auto & item : constraint_row)
3605  dof_set.insert (item.first);
3606  }
3607 
3608  // May be safe to return at this point
3609  // (but remember to stop the perflog)
3610  if (!we_have_constraints)
3611  return;
3612 
3613  for (const auto & dof : elem_dofs)
3614  dof_set.erase (dof);
3615 
3616  // If we added any DOFS then we need to do this recursively.
3617  // It is possible that we just added a DOF that is also
3618  // constrained!
3619  //
3620  // Also, we need to handle the special case of an element having DOFs
3621  // constrained in terms of other, local DOFs
3622  if (!dof_set.empty() || // case 1: constrained in terms of other DOFs
3623  !called_recursively) // case 2: constrained in terms of our own DOFs
3624  {
3625  const DofConstraintValueMap * rhs_values = nullptr;
3626  if (qoi_index < 0)
3627  rhs_values = &_primal_constraint_values;
3628  else
3629  {
3630  const AdjointDofConstraintValues::const_iterator
3631  it = _adjoint_constraint_values.find(qoi_index);
3632  if (it != _adjoint_constraint_values.end())
3633  rhs_values = &it->second;
3634  }
3635 
3636  const unsigned int old_size =
3637  cast_int<unsigned int>(elem_dofs.size());
3638 
3639  // Add new dependency dofs to the end of the current dof set
3640  elem_dofs.insert(elem_dofs.end(),
3641  dof_set.begin(), dof_set.end());
3642 
3643  // Now we can build the constraint matrix and vector.
3644  // Note that resize also zeros for a DenseMatrix and DenseVector
3645  C.resize (old_size,
3646  cast_int<unsigned int>(elem_dofs.size()));
3647  H.resize (old_size);
3648 
3649  // Create the C constraint matrix.
3650  for (unsigned int i=0; i != old_size; i++)
3651  if (this->is_constrained_dof(elem_dofs[i]))
3652  {
3653  // If the DOF is constrained
3654  DofConstraints::const_iterator
3655  pos = _dof_constraints.find(elem_dofs[i]);
3656 
3657  libmesh_assert (pos != _dof_constraints.end());
3658 
3659  const DofConstraintRow & constraint_row = pos->second;
3660 
3661  // p refinement creates empty constraint rows
3662  // libmesh_assert (!constraint_row.empty());
3663 
3664  for (const auto & item : constraint_row)
3665  for (unsigned int j=0,
3666  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
3667  j != n_elem_dofs; j++)
3668  if (elem_dofs[j] == item.first)
3669  C(i,j) = item.second;
3670 
3671  if (rhs_values)
3672  {
3673  DofConstraintValueMap::const_iterator rhsit =
3674  rhs_values->find(elem_dofs[i]);
3675  if (rhsit != rhs_values->end())
3676  H(i) = rhsit->second;
3677  }
3678  }
3679  else
3680  {
3681  C(i,i) = 1.;
3682  }
3683 
3684  // May need to do this recursively. It is possible
3685  // that we just replaced a constrained DOF with another
3686  // constrained DOF.
3687  DenseMatrix<Number> Cnew;
3688  DenseVector<Number> Hnew;
3689 
3690  this->build_constraint_matrix_and_vector (Cnew, Hnew, elem_dofs,
3691  qoi_index, true);
3692 
3693  if ((C.n() == Cnew.m()) && // If the constraint matrix
3694  (Cnew.n() == elem_dofs.size())) // is constrained...
3695  {
3696  // If x = Cy + h and y = Dz + g
3697  // Then x = (CD)z + (Cg + h)
3698  C.vector_mult_add(H, 1, Hnew);
3699 
3700  C.right_multiply(Cnew);
3701  }
3702 
3703  libmesh_assert_equal_to (C.n(), elem_dofs.size());
3704  }
3705 }
unsigned int n() const
返回矩阵的列维度。
void build_constraint_matrix_and_vector(DenseMatrix< Number > &C, DenseVector< Number > &H, std::vector< dof_id_type > &elem_dofs, int qoi_index=-1, const bool called_recursively=false) const
Build the constraint matrix C and the forcing vector H associated with the element degree of freedom ...
void resize(const unsigned int n)
调整向量的大小。将所有元素设置为0。
Definition: dense_vector.h:404
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:2034
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
unsigned int m() const
返回矩阵的行维度。
void vector_mult_add(DenseVector< T > &dest, const T factor, const DenseVector< T > &arg) const
执行缩放矩阵-向量乘法,结果存储在 dest 中。 dest += factor * (*this) * arg.
virtual void right_multiply(const DenseMatrixBase< T > &M2) overridefinal
右乘以矩阵 M2。
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
Storage for DofConstraint right hand sides for a particular problem.
Definition: dof_map.h:110
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
void resize(const unsigned int new_m, const unsigned int new_n)
调整矩阵的大小,并调用 zero() 方法。
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:90
定义用于有限元计算的稠密向量类。该类基本上是为了补充 DenseMatrix 类而设计的。 它相对于 std::vector 具有额外的功能,使其在有限元中特别有用,特别是对于方程组。 所有重写的虚拟函...
Definition: dof_map.h:64
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
std::unique_ptr< SparsityPattern::Build > libMesh::DofMap::build_sparsity ( const MeshBase &  mesh,
bool  calculate_constrained = 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.

在文件 dof_map.C64 行定义.

参考 _augment_sparsity_pattern, _coupling_functors, _dof_coupling, _extra_sparsity_context, _extra_sparsity_function, n_dofs_on_processor(), need_full_sparsity_pattern, libMesh::out , 以及 use_coupled_neighbor_dofs().

参考自 compute_sparsity() , 以及 process_mesh_constraint_rows().

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 PetscMatrix 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  // We can compute the sparsity pattern in parallel on multiple
85  // threads. The goal is for each thread to compute the full sparsity
86  // pattern for a subset of elements. These sparsity patterns can
87  // be efficiently merged in the SparsityPattern::Build::join()
88  // method, especially if there is not too much overlap between them.
89  // Even better, if the full sparsity pattern is not needed then
90  // the number of nonzeros per row can be estimated from the
91  // sparsity patterns created on each thread.
92  auto sp = std::make_unique<SparsityPattern::Build>
93  (*this,
94  this->_dof_coupling,
95  this->_coupling_functors,
96  implicit_neighbor_dofs,
98  calculate_constrained);
99 
100  Threads::parallel_reduce (ConstElemRange (mesh.active_local_elements_begin(),
101  mesh.active_local_elements_end()), *sp);
102 
103  sp->parallel_sync();
104 
105 #ifndef NDEBUG
106  // Avoid declaring these variables unless asserts are enabled.
107  const processor_id_type proc_id = mesh.processor_id();
108  const dof_id_type n_dofs_on_proc = this->n_dofs_on_processor(proc_id);
109 #endif
110  libmesh_assert_equal_to (sp->get_sparsity_pattern().size(), n_dofs_on_proc);
111 
112  // Check to see if we have any extra stuff to add to the sparsity_pattern
114  {
116  {
117  libmesh_here();
118  libMesh::out << "WARNING: You have specified both an extra sparsity function and object.\n"
119  << " Are you sure this is what you meant to do??"
120  << std::endl;
121  }
122 
123  sp->apply_extra_sparsity_function(_extra_sparsity_function,
125  }
126 
128  sp->apply_extra_sparsity_object(*_augment_sparsity_pattern);
129 
130  return sp;
131 }
void * _extra_sparsity_context
A pointer associated with the extra sparsity that can optionally be passed in.
Definition: dof_map.h:1910
uint8_t processor_id_type
Definition: id_types.h:104
dof_id_type n_dofs_on_processor(const processor_id_type proc) const
Definition: dof_map.h:675
bool need_full_sparsity_pattern
Default false; set to true if any attached matrix requires a full sparsity pattern.
Definition: dof_map.h:1976
OStreamProxy out
CouplingMatrix * _dof_coupling
Degree of freedom coupling.
Definition: dof_map.h:1589
SparsityPattern::AugmentSparsityPattern * _augment_sparsity_pattern
Function object to call to add extra entries to the sparsity pattern.
Definition: dof_map.h:1898
std::set< GhostingFunctor * > _coupling_functors
The list of all GhostingFunctor objects to be used when coupling degrees of freedom in matrix sparsit...
Definition: dof_map.h:1964
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:1903
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:1760
uint8_t dof_id_type
Definition: id_types.h:67
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.

在文件 dof_map_constraints.C5532 行定义.

参考 libMesh::DirichletBoundary::b.

参考自 create_dof_constraints().

5534 {
5535  const std::set<boundary_id_type>& mesh_side_bcids =
5536  mesh.get_boundary_info().get_boundary_ids();
5537  const std::set<boundary_id_type>& mesh_edge_bcids =
5538  mesh.get_boundary_info().get_edge_boundary_ids();
5539  const std::set<boundary_id_type>& mesh_node_bcids =
5540  mesh.get_boundary_info().get_node_boundary_ids();
5541  const std::set<boundary_id_type>& dbc_bcids = boundary.b;
5542 
5543  // DirichletBoundary id sets should be consistent across all ranks
5544  libmesh_assert(mesh.comm().verify(dbc_bcids.size()));
5545 
5546  for (const auto & bc_id : dbc_bcids)
5547  {
5548  // DirichletBoundary id sets should be consistent across all ranks
5549  libmesh_assert(mesh.comm().verify(bc_id));
5550 
5551  bool found_bcid = (mesh_side_bcids.find(bc_id) != mesh_side_bcids.end() ||
5552  mesh_edge_bcids.find(bc_id) != mesh_edge_bcids.end() ||
5553  mesh_node_bcids.find(bc_id) != mesh_node_bcids.end());
5554 
5555  // On a distributed mesh, boundary id sets may *not* be
5556  // consistent across all ranks, since not all ranks see all
5557  // boundaries
5558  mesh.comm().max(found_bcid);
5559 
5560  libmesh_error_msg_if(!found_bcid,
5561  "Could not find Dirichlet boundary id " << bc_id << " in mesh!");
5562  }
5563 }
std::set< boundary_id_type > b
void libMesh::DofMap::check_for_constraint_loops ( )

在文件 dof_map_constraints.C4545 行定义.

参考 _dof_constraints , 以及 libMesh::Real.

参考自 check_for_cyclic_constraints() , 以及 process_constraints().

4546 {
4547  // Create a set containing the DOFs we already depend on
4548  typedef std::set<dof_id_type> RCSet;
4549  RCSet unexpanded_set;
4550 
4551  // Use dof_constraints_copy in this method so that we don't
4552  // mess with _dof_constraints.
4553  DofConstraints dof_constraints_copy = _dof_constraints;
4554 
4555  for (const auto & i : dof_constraints_copy)
4556  unexpanded_set.insert(i.first);
4557 
4558  while (!unexpanded_set.empty())
4559  for (RCSet::iterator i = unexpanded_set.begin();
4560  i != unexpanded_set.end(); /* nothing */)
4561  {
4562  // If the DOF is constrained
4563  DofConstraints::iterator
4564  pos = dof_constraints_copy.find(*i);
4565 
4566  libmesh_assert (pos != dof_constraints_copy.end());
4567 
4568  DofConstraintRow & constraint_row = pos->second;
4569 
4570  // Comment out "rhs" parts of this method copied from process_constraints
4571  // DofConstraintValueMap::iterator rhsit =
4572  // _primal_constraint_values.find(*i);
4573  // Number constraint_rhs = (rhsit == _primal_constraint_values.end()) ?
4574  // 0 : rhsit->second;
4575 
4576  std::vector<dof_id_type> constraints_to_expand;
4577 
4578  for (const auto & item : constraint_row)
4579  if (item.first != *i && this->is_constrained_dof(item.first))
4580  {
4581  unexpanded_set.insert(item.first);
4582  constraints_to_expand.push_back(item.first);
4583  }
4584 
4585  for (const auto & expandable : constraints_to_expand)
4586  {
4587  const Real this_coef = constraint_row[expandable];
4588 
4589  DofConstraints::const_iterator
4590  subpos = dof_constraints_copy.find(expandable);
4591 
4592  libmesh_assert (subpos != dof_constraints_copy.end());
4593 
4594  const DofConstraintRow & subconstraint_row = subpos->second;
4595 
4596  for (const auto & item : subconstraint_row)
4597  {
4598  libmesh_error_msg_if(item.first == expandable, "Constraint loop detected");
4599 
4600  constraint_row[item.first] += item.second * this_coef;
4601  }
4602 
4603  // Comment out "rhs" parts of this method copied from process_constraints
4604  // DofConstraintValueMap::const_iterator subrhsit =
4605  // _primal_constraint_values.find(expandable);
4606  // if (subrhsit != _primal_constraint_values.end())
4607  // constraint_rhs += subrhsit->second * this_coef;
4608 
4609  constraint_row.erase(expandable);
4610  }
4611 
4612  // Comment out "rhs" parts of this method copied from process_constraints
4613  // if (rhsit == _primal_constraint_values.end())
4614  // {
4615  // if (constraint_rhs != Number(0))
4616  // _primal_constraint_values[*i] = constraint_rhs;
4617  // else
4618  // _primal_constraint_values.erase(*i);
4619  // }
4620  // else
4621  // {
4622  // if (constraint_rhs != Number(0))
4623  // rhsit->second = constraint_rhs;
4624  // else
4625  // _primal_constraint_values.erase(rhsit);
4626  // }
4627 
4628  if (constraints_to_expand.empty())
4629  i = unexpanded_set.erase(i);
4630  else
4631  ++i;
4632  }
4633 }
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
A row of the Dof constraint matrix.
Definition: dof_map.h:90
The constraint matrix storage format.
Definition: dof_map.h:98
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.

注解
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".

在文件 dof_map_constraints.C4539 行定义.

参考 check_for_constraint_loops().

4540 {
4541  // Eventually make this officially libmesh_deprecated();
4543 }
void libMesh::DofMap::clear ( )

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

在文件 dof_map.C850 行定义.

参考 _adjoint_constraint_values, _algebraic_ghosting_functors, _coupling_functors, _default_coupling, _default_evaluating, _dof_constraints, _dof_coupling, _end_df, _end_old_df, _first_df, _first_old_df, _first_old_scalar_df, _first_scalar_df, _matrices, _mesh, _n_dfs, _n_old_dfs, _primal_constraint_values, _shared_functors, _stashed_dof_constraints, _var_to_vg, _variable_group_numbers, _variable_groups, _variables, add_algebraic_ghosting_functor(), add_coupling_functor(), clear_send_list(), clear_sparsity(), need_full_sparsity_pattern , 以及 use_coupled_neighbor_dofs().

参考自 ~DofMap().

851 {
852  // we don't want to clear
853  // the coupling matrix!
854  // It should not change...
855  //_dof_coupling->clear();
856  //
857  // But it would be inconsistent to leave our coupling settings
858  // through a clear()...
859  _dof_coupling = nullptr;
860 
861  // Reset ghosting functor statuses
862  {
863  for (const auto & gf : _coupling_functors)
864  {
865  libmesh_assert(gf);
866  _mesh.remove_ghosting_functor(*gf);
867  }
868  this->_coupling_functors.clear();
869 
870  // Go back to default coupling
871 
872  _default_coupling->set_dof_coupling(this->_dof_coupling);
873  _default_coupling->set_n_levels(this->use_coupled_neighbor_dofs(this->_mesh));
874 
876  }
877 
878 
879  {
880  for (const auto & gf : _algebraic_ghosting_functors)
881  {
882  libmesh_assert(gf);
883  _mesh.remove_ghosting_functor(*gf);
884  }
885  this->_algebraic_ghosting_functors.clear();
886 
887  // Go back to default send_list generation
888 
889  // _default_evaluating->set_dof_coupling(this->_dof_coupling);
890  _default_evaluating->set_n_levels(1);
892  }
893 
894  this->_shared_functors.clear();
895 
896  _variables.clear();
897  _variable_groups.clear();
898  _var_to_vg.clear();
899  _variable_group_numbers.clear();
900  _first_df.clear();
901  _end_df.clear();
902  _first_scalar_df.clear();
903  this->clear_send_list();
904  this->clear_sparsity();
906 
907 #ifdef LIBMESH_ENABLE_AMR
908 
909  _dof_constraints.clear();
910  _stashed_dof_constraints.clear();
913  _n_old_dfs = 0;
914  _first_old_df.clear();
915  _end_old_df.clear();
916  _first_old_scalar_df.clear();
917 
918 #endif
919 
920  _matrices.clear();
921 
922  _n_dfs = 0;
923 }
std::vector< VariableGroup > _variable_groups
The finite element type for each variable group.
Definition: dof_map.h:1844
void clear_send_list()
Clears the _send_list vector.
Definition: dof_map.h:485
std::set< GhostingFunctor * > _algebraic_ghosting_functors
The list of all GhostingFunctor objects to be used when distributing ghosted vectors.
Definition: dof_map.h:1951
std::vector< dof_id_type > _end_old_df
Last old DOF index (plus 1) on processor p.
Definition: dof_map.h:2011
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:1861
std::vector< dof_id_type > _first_old_df
First old DOF index on processor p.
Definition: dof_map.h:2006
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:1887
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:2034
bool need_full_sparsity_pattern
Default false; set to true if any attached matrix requires a full sparsity pattern.
Definition: dof_map.h:1976
std::unordered_map< unsigned int, unsigned int > _var_to_vg
A map from variable number to variable group number.
Definition: dof_map.h:1854
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:2017
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
CouplingMatrix * _dof_coupling
Degree of freedom coupling.
Definition: dof_map.h:1589
std::vector< SparseMatrix< Number > * > _matrices
Additional matrices handled by this object.
Definition: dof_map.h:1871
std::unique_ptr< DefaultCoupling > _default_coupling
The default coupling GhostingFunctor, used to implement standard libMesh sparsity pattern constructio...
Definition: dof_map.h:1933
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
std::vector< Variable > _variables
The finite element type for each variable.
Definition: dof_map.h:1839
DofConstraints _stashed_dof_constraints
Definition: dof_map.h:2030
dof_id_type _n_old_dfs
Total number of degrees of freedom on old dof objects.
Definition: dof_map.h:2001
void clear_sparsity()
Clears the sparsity pattern.
Definition: dof_map.C:1837
std::set< GhostingFunctor * > _coupling_functors
The list of all GhostingFunctor objects to be used when coupling degrees of freedom in matrix sparsit...
Definition: dof_map.h:1964
std::vector< dof_id_type > _end_df
Last DOF index (plus 1) on processor p.
Definition: dof_map.h:1881
std::vector< dof_id_type > _first_df
First DOF index on processor p.
Definition: dof_map.h:1876
MeshBase & _mesh
The mesh that system uses.
Definition: dof_map.h:1864
std::unique_ptr< DefaultCoupling > _default_evaluating
The default algebraic GhostingFunctor, used to implement standard libMesh send_list construction...
Definition: dof_map.h:1941
std::vector< unsigned int > _variable_group_numbers
The variable group number for each variable.
Definition: dof_map.h:1849
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:1970
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:1886
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:1760
dof_id_type _n_dfs
Total number of degrees of freedom.
Definition: dof_map.h:1988
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.

在文件 dof_map.h485 行定义.

参考 _send_list.

参考自 clear(), distribute_dofs() , 以及 reinit_send_list().

486  {
487  _send_list.clear();
488  }
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:1893
void libMesh::DofMap::clear_sparsity ( )

Clears the sparsity pattern.

在文件 dof_map.C1837 行定义.

参考 _sp.

参考自 clear().

1838 {
1839  _sp.reset();
1840 }
std::unique_ptr< SparsityPattern::Build > _sp
The sparsity pattern of the global matrix.
Definition: dof_map.h:1983
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.

在文件 dof_map.C1816 行定义.

参考 _constrained_sparsity_construction, _matrices, _sp, build_sparsity() , 以及 need_full_sparsity_pattern.

1817 {
1819 
1820  // It is possible that some \p SparseMatrix implementations want to
1821  // see the sparsity pattern before we throw it away. If so, we
1822  // share a view of its arrays, and we pass it in to the matrices.
1823  for (const auto & mat : _matrices)
1824  {
1825  mat->attach_sparsity_pattern (*_sp);
1827  mat->update_sparsity_pattern (_sp->get_sparsity_pattern());
1828  }
1829  // If we don't need the full sparsity pattern anymore, free the
1830  // parts of it we don't need.
1832  _sp->clear_full_sparsity();
1833 }
std::unique_ptr< SparsityPattern::Build > _sp
The sparsity pattern of the global matrix.
Definition: dof_map.h:1983
bool _constrained_sparsity_construction
This flag indicates whether or not we explicitly take constraint equations into account when computin...
Definition: dof_map.h:1834
bool need_full_sparsity_pattern
Default false; set to true if any attached matrix requires a full sparsity pattern.
Definition: dof_map.h:1976
std::unique_ptr< SparsityPattern::Build > build_sparsity(const MeshBase &mesh, bool calculate_constrained=false) const
Builds a sparsity pattern for matrices using the current degree-of-freedom numbering and coupling...
Definition: dof_map.C:64
std::vector< SparseMatrix< Number > * > _matrices
Additional matrices handled by this object.
Definition: dof_map.h:1871
bool libMesh::DofMap::computed_sparsity_already ( ) const

Returns true iff a sparsity pattern has already been computed.

在文件 dof_map.C296 行定义.

参考 _sp.

参考自 update_sparsity_pattern().

297 {
299  (!_sp->get_n_nz().empty() ||
300  !_sp->get_n_oz().empty());
301  this->comm().max(computed_sparsity_already);
303 }
std::unique_ptr< SparsityPattern::Build > _sp
The sparsity pattern of the global matrix.
Definition: dof_map.h:1983
bool computed_sparsity_already() const
Returns true iff a sparsity pattern has already been computed.
Definition: dof_map.C:296
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.

在文件 dof_map_constraints.C3048 行定义.

参考 _dof_constraints, build_constraint_matrix(), is_constrained_dof(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::size() , 以及 libMesh::DenseMatrix< T >::vector_mult_transpose().

3052 {
3053  libmesh_assert_equal_to (v.size(), row_dofs.size());
3054  libmesh_assert_equal_to (w.size(), row_dofs.size());
3055 
3056  // check for easy return
3057  if (this->_dof_constraints.empty())
3058  return;
3059 
3060  // The constrained RHS is built up as R^T F.
3062 
3063  this->build_constraint_matrix (R, row_dofs);
3064 
3065  LOG_SCOPE("cnstrn_elem_dyad_mat()", "DofMap");
3066 
3067  // It is possible that the vector is not constrained at all.
3068  if ((R.m() == v.size()) &&
3069  (R.n() == row_dofs.size())) // if the RHS is constrained
3070  {
3071  // Compute the matrix-vector products
3072  DenseVector<Number> old_v(v);
3073  DenseVector<Number> old_w(w);
3074 
3075  // compute matrix/vector product
3076  R.vector_mult_transpose(v, old_v);
3077  R.vector_mult_transpose(w, old_w);
3078 
3079  libmesh_assert_equal_to (row_dofs.size(), v.size());
3080  libmesh_assert_equal_to (row_dofs.size(), w.size());
3081 
3082  /* Constrain only v, not w. */
3083 
3084  for (unsigned int i=0,
3085  n_row_dofs = cast_int<unsigned int>(row_dofs.size());
3086  i != n_row_dofs; i++)
3087  if (this->is_constrained_dof(row_dofs[i]))
3088  {
3089  // If the DOF is constrained
3090  libmesh_assert (_dof_constraints.find(row_dofs[i]) != _dof_constraints.end());
3091 
3092  v(i) = 0;
3093  }
3094  } // end if the RHS is constrained.
3095 }
unsigned int n() const
返回矩阵的列维度。
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this)^T * arg。
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
unsigned int m() const
返回矩阵的行维度。
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
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...
定义用于有限元计算的稠密向量类。该类基本上是为了补充 DenseMatrix 类而设计的。 它相对于 std::vector 具有额外的功能,使其在有限元中特别有用,特别是对于方程组。 所有重写的虚拟函...
Definition: dof_map.h:64
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
virtual unsigned int size() const overridefinal
Definition: dense_vector.h:111
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.

在文件 dof_map_constraints.C2380 行定义.

参考 _dof_constraints, build_constraint_matrix(), is_constrained_dof(), libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n() , 以及 libMesh::DenseMatrix< T >::right_multiply().

2383 {
2384  libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
2385  libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
2386 
2387  // check for easy return
2388  if (this->_dof_constraints.empty())
2389  return;
2390 
2391  // The constrained matrix is built up as C^T K C.
2393 
2394 
2395  this->build_constraint_matrix (C, elem_dofs);
2396 
2397  LOG_SCOPE("constrain_elem_matrix()", "DofMap");
2398 
2399  // It is possible that the matrix is not constrained at all.
2400  if ((C.m() == matrix.m()) &&
2401  (C.n() == elem_dofs.size())) // It the matrix is constrained
2402  {
2403  // Compute the matrix-matrix-matrix product C^T K C
2404  matrix.left_multiply_transpose (C);
2405  matrix.right_multiply (C);
2406 
2407 
2408  libmesh_assert_equal_to (matrix.m(), matrix.n());
2409  libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
2410  libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
2411 
2412 
2413  for (unsigned int i=0,
2414  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2415  i != n_elem_dofs; i++)
2416  // If the DOF is constrained
2417  if (this->is_constrained_dof(elem_dofs[i]))
2418  {
2419  for (auto j : make_range(matrix.n()))
2420  matrix(i,j) = 0.;
2421 
2422  matrix(i,i) = 1.;
2423 
2424  if (asymmetric_constraint_rows)
2425  {
2426  DofConstraints::const_iterator
2427  pos = _dof_constraints.find(elem_dofs[i]);
2428 
2429  libmesh_assert (pos != _dof_constraints.end());
2430 
2431  const DofConstraintRow & constraint_row = pos->second;
2432 
2433  // This is an overzealous assertion in the presence of
2434  // heterogeneous constraints: we now can constrain "u_i = c"
2435  // with no other u_j terms involved.
2436  //
2437  // libmesh_assert (!constraint_row.empty());
2438 
2439  for (const auto & item : constraint_row)
2440  for (unsigned int j=0; j != n_elem_dofs; j++)
2441  if (elem_dofs[j] == item.first)
2442  matrix(i,j) = -item.second;
2443  }
2444  }
2445  } // end if is constrained...
2446 }
unsigned int n() const
返回矩阵的列维度。
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
unsigned int m() const
返回矩阵的行维度。
virtual void right_multiply(const DenseMatrixBase< T > &M2) overridefinal
右乘以矩阵 M2。
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
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 left_multiply_transpose(const DenseMatrix< T > &A)
用矩阵 A 的转置左乘。
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:90
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
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.

在文件 dof_map_constraints.C2914 行定义.

参考 _dof_constraints, build_constraint_matrix(), is_constrained_dof(), libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n() , 以及 libMesh::DenseMatrix< T >::right_multiply().

2918 {
2919  libmesh_assert_equal_to (row_dofs.size(), matrix.m());
2920  libmesh_assert_equal_to (col_dofs.size(), matrix.n());
2921 
2922  // check for easy return
2923  if (this->_dof_constraints.empty())
2924  return;
2925 
2926  // The constrained matrix is built up as R^T K C.
2929 
2930  // Safeguard against the user passing us the same
2931  // object for row_dofs and col_dofs. If that is done
2932  // the calls to build_matrix would fail
2933  std::vector<dof_id_type> orig_row_dofs(row_dofs);
2934  std::vector<dof_id_type> orig_col_dofs(col_dofs);
2935 
2936  this->build_constraint_matrix (R, orig_row_dofs);
2937  this->build_constraint_matrix (C, orig_col_dofs);
2938 
2939  LOG_SCOPE("constrain_elem_matrix()", "DofMap");
2940 
2941  row_dofs = orig_row_dofs;
2942  col_dofs = orig_col_dofs;
2943 
2944  bool constraint_found = false;
2945 
2946  // K_constrained = R^T K C
2947 
2948  if ((R.m() == matrix.m()) &&
2949  (R.n() == row_dofs.size()))
2950  {
2951  matrix.left_multiply_transpose (R);
2952  constraint_found = true;
2953  }
2954 
2955  if ((C.m() == matrix.n()) &&
2956  (C.n() == col_dofs.size()))
2957  {
2958  matrix.right_multiply (C);
2959  constraint_found = true;
2960  }
2961 
2962  // It is possible that the matrix is not constrained at all.
2963  if (constraint_found)
2964  {
2965  libmesh_assert_equal_to (matrix.m(), row_dofs.size());
2966  libmesh_assert_equal_to (matrix.n(), col_dofs.size());
2967 
2968 
2969  for (unsigned int i=0,
2970  n_row_dofs = cast_int<unsigned int>(row_dofs.size());
2971  i != n_row_dofs; i++)
2972  if (this->is_constrained_dof(row_dofs[i]))
2973  {
2974  for (auto j : make_range(matrix.n()))
2975  {
2976  if (row_dofs[i] != col_dofs[j])
2977  matrix(i,j) = 0.;
2978  else // If the DOF is constrained
2979  matrix(i,j) = 1.;
2980  }
2981 
2982  if (asymmetric_constraint_rows)
2983  {
2984  DofConstraints::const_iterator
2985  pos = _dof_constraints.find(row_dofs[i]);
2986 
2987  libmesh_assert (pos != _dof_constraints.end());
2988 
2989  const DofConstraintRow & constraint_row = pos->second;
2990 
2991  libmesh_assert (!constraint_row.empty());
2992 
2993  for (const auto & item : constraint_row)
2994  for (unsigned int j=0,
2995  n_col_dofs = cast_int<unsigned int>(col_dofs.size());
2996  j != n_col_dofs; j++)
2997  if (col_dofs[j] == item.first)
2998  matrix(i,j) = -item.second;
2999  }
3000  }
3001  } // end if is constrained...
3002 }
unsigned int n() const
返回矩阵的列维度。
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
unsigned int m() const
返回矩阵的行维度。
virtual void right_multiply(const DenseMatrixBase< T > &M2) overridefinal
右乘以矩阵 M2。
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
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 left_multiply_transpose(const DenseMatrix< T > &A)
用矩阵 A 的转置左乘。
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:90
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
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.

在文件 dof_map_constraints.C2450 行定义.

参考 _dof_constraints, build_constraint_matrix(), is_constrained_dof(), libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::right_multiply(), libMesh::DenseVector< T >::size() , 以及 libMesh::DenseMatrix< T >::vector_mult_transpose().

2454 {
2455  libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
2456  libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
2457  libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
2458 
2459  // check for easy return
2460  if (this->_dof_constraints.empty())
2461  return;
2462 
2463  // The constrained matrix is built up as C^T K C.
2464  // The constrained RHS is built up as C^T F
2466 
2467  this->build_constraint_matrix (C, elem_dofs);
2468 
2469  LOG_SCOPE("cnstrn_elem_mat_vec()", "DofMap");
2470 
2471  // It is possible that the matrix is not constrained at all.
2472  if ((C.m() == matrix.m()) &&
2473  (C.n() == elem_dofs.size())) // It the matrix is constrained
2474  {
2475  // Compute the matrix-matrix-matrix product C^T K C
2476  matrix.left_multiply_transpose (C);
2477  matrix.right_multiply (C);
2478 
2479 
2480  libmesh_assert_equal_to (matrix.m(), matrix.n());
2481  libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
2482  libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
2483 
2484 
2485  for (unsigned int i=0,
2486  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2487  i != n_elem_dofs; i++)
2488  if (this->is_constrained_dof(elem_dofs[i]))
2489  {
2490  for (auto j : make_range(matrix.n()))
2491  matrix(i,j) = 0.;
2492 
2493  // If the DOF is constrained
2494  matrix(i,i) = 1.;
2495 
2496  // This will put a nonsymmetric entry in the constraint
2497  // row to ensure that the linear system produces the
2498  // correct value for the constrained DOF.
2499  if (asymmetric_constraint_rows)
2500  {
2501  DofConstraints::const_iterator
2502  pos = _dof_constraints.find(elem_dofs[i]);
2503 
2504  libmesh_assert (pos != _dof_constraints.end());
2505 
2506  const DofConstraintRow & constraint_row = pos->second;
2507 
2508  // p refinement creates empty constraint rows
2509  // libmesh_assert (!constraint_row.empty());
2510 
2511  for (const auto & item : constraint_row)
2512  for (unsigned int j=0; j != n_elem_dofs; j++)
2513  if (elem_dofs[j] == item.first)
2514  matrix(i,j) = -item.second;
2515  }
2516  }
2517 
2518 
2519  // Compute the matrix-vector product C^T F
2520  DenseVector<Number> old_rhs(rhs);
2521 
2522  // compute matrix/vector product
2523  C.vector_mult_transpose(rhs, old_rhs);
2524  } // end if is constrained...
2525 }
unsigned int n() const
返回矩阵的列维度。
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this)^T * arg。
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
unsigned int m() const
返回矩阵的行维度。
virtual void right_multiply(const DenseMatrixBase< T > &M2) overridefinal
右乘以矩阵 M2。
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
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 left_multiply_transpose(const DenseMatrix< T > &A)
用矩阵 A 的转置左乘。
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:90
定义用于有限元计算的稠密向量类。该类基本上是为了补充 DenseMatrix 类而设计的。 它相对于 std::vector 具有额外的功能,使其在有限元中特别有用,特别是对于方程组。 所有重写的虚拟函...
Definition: dof_map.h:64
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
virtual unsigned int size() const overridefinal
Definition: dense_vector.h:111
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

在文件 dof_map_constraints.C2782 行定义.

参考 libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::size(), libMesh::NumericVector< T >::type() , 以及 libMesh::DenseMatrix< T >::vector_mult_transpose().

2785 {
2786  libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
2787 
2788  libmesh_assert (solution_local.type() == SERIAL ||
2789  solution_local.type() == GHOSTED);
2790 
2791  // check for easy return
2792  if (this->_dof_constraints.empty())
2793  return;
2794 
2795  // The constrained RHS is built up as C^T F
2797 
2798  this->build_constraint_matrix (C, elem_dofs);
2799 
2800  LOG_SCOPE("cnstrn_elem_residual()", "DofMap");
2801 
2802  // It is possible that the matrix is not constrained at all.
2803  if (C.n() != elem_dofs.size())
2804  return;
2805 
2806  // Compute the matrix-vector product C^T F
2807  DenseVector<Number> old_rhs(rhs);
2808  C.vector_mult_transpose(rhs, old_rhs);
2809 
2810  for (unsigned int i=0,
2811  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2812  i != n_elem_dofs; i++)
2813  {
2814  const dof_id_type dof_id = elem_dofs[i];
2815 
2816  const DofConstraints::const_iterator
2817  pos = _dof_constraints.find(dof_id);
2818 
2819  if (pos != _dof_constraints.end())
2820  {
2821  // This will put a nonsymmetric entry in the constraint
2822  // row to ensure that the linear system produces the
2823  // correct value for the constrained DOF.
2824  const DofConstraintRow & constraint_row = pos->second;
2825 
2826  Number & rhs_val = rhs(i);
2827  rhs_val = 0;
2828  for (const auto & [constraining_dof, coef] : constraint_row)
2829  rhs_val -= coef * solution_local(constraining_dof);
2830  rhs_val += solution_local(dof_id);
2831  }
2832  }
2833 }
unsigned int n() const
返回矩阵的列维度。
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this)^T * arg。
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
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...
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:90
ParallelType type() const
获取向量的类型。
定义用于有限元计算的稠密向量类。该类基本上是为了补充 DenseMatrix 类而设计的。 它相对于 std::vector 具有额外的功能,使其在有限元中特别有用,特别是对于方程组。 所有重写的虚拟函...
Definition: dof_map.h:64
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
virtual unsigned int size() const overridefinal
Definition: dense_vector.h:111
uint8_t dof_id_type
Definition: id_types.h:67
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.

在文件 dof_map_constraints.C3006 行定义.

参考 _dof_constraints, build_constraint_matrix(), is_constrained_dof(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::size() , 以及 libMesh::DenseMatrix< T >::vector_mult_transpose().

3009 {
3010  libmesh_assert_equal_to (rhs.size(), row_dofs.size());
3011 
3012  // check for easy return
3013  if (this->_dof_constraints.empty())
3014  return;
3015 
3016  // The constrained RHS is built up as R^T F.
3018 
3019  this->build_constraint_matrix (R, row_dofs);
3020 
3021  LOG_SCOPE("constrain_elem_vector()", "DofMap");
3022 
3023  // It is possible that the vector is not constrained at all.
3024  if ((R.m() == rhs.size()) &&
3025  (R.n() == row_dofs.size())) // if the RHS is constrained
3026  {
3027  // Compute the matrix-vector product
3028  DenseVector<Number> old_rhs(rhs);
3029  R.vector_mult_transpose(rhs, old_rhs);
3030 
3031  libmesh_assert_equal_to (row_dofs.size(), rhs.size());
3032 
3033  for (unsigned int i=0,
3034  n_row_dofs = cast_int<unsigned int>(row_dofs.size());
3035  i != n_row_dofs; i++)
3036  if (this->is_constrained_dof(row_dofs[i]))
3037  {
3038  // If the DOF is constrained
3039  libmesh_assert (_dof_constraints.find(row_dofs[i]) != _dof_constraints.end());
3040 
3041  rhs(i) = 0;
3042  }
3043  } // end if the RHS is constrained.
3044 }
unsigned int n() const
返回矩阵的列维度。
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this)^T * arg。
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
unsigned int m() const
返回矩阵的行维度。
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
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...
定义用于有限元计算的稠密向量类。该类基本上是为了补充 DenseMatrix 类而设计的。 它相对于 std::vector 具有额外的功能,使其在有限元中特别有用,特别是对于方程组。 所有重写的虚拟函...
Definition: dof_map.h:64
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
virtual unsigned int size() const overridefinal
Definition: dense_vector.h:111
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.

在文件 dof_map_constraints.C3099 行定义.

参考 _dof_constraints , 以及 build_constraint_matrix().

3100 {
3101  // check for easy return
3102  if (this->_dof_constraints.empty())
3103  return;
3104 
3105  // All the work is done by \p build_constraint_matrix. We just need
3106  // a dummy matrix.
3108  this->build_constraint_matrix (R, dofs);
3109 }
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
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...
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
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.

在文件 dof_map_constraints.C5391 行定义.

参考 _dof_constraints, _primal_constraint_values, sys_number() , 以及 variable_type().

5395 {
5396  // We're constraining dofs on elem which correspond to p refinement
5397  // levels above p - this only makes sense if elem's p refinement
5398  // level is above p.
5399  libmesh_assert_greater (elem->p_level(), p);
5400  libmesh_assert_less (s, elem->n_sides());
5401 
5402  const unsigned int sys_num = this->sys_number();
5403  FEType fe_type = this->variable_type(var);
5404 
5405  const unsigned int n_nodes = elem->n_nodes();
5406  for (unsigned int n = 0; n != n_nodes; ++n)
5407  if (elem->is_node_on_side(n, s))
5408  {
5409  const Node & node = elem->node_ref(n);
5410  const unsigned int low_nc =
5411  FEInterface::n_dofs_at_node (fe_type, p, elem, n);
5412  const unsigned int high_nc =
5413  FEInterface::n_dofs_at_node (fe_type, elem, n);
5414 
5415  // since we may be running this method concurrently
5416  // on multiple threads we need to acquire a lock
5417  // before modifying the _dof_constraints object.
5418  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
5419 
5420  if (elem->is_vertex(n))
5421  {
5422  // Add "this is zero" constraint rows for high p vertex
5423  // dofs
5424  for (unsigned int i = low_nc; i != high_nc; ++i)
5425  {
5426  _dof_constraints[node.dof_number(sys_num,var,i)].clear();
5427  _primal_constraint_values.erase(node.dof_number(sys_num,var,i));
5428  }
5429  }
5430  else
5431  {
5432  const unsigned int total_dofs = node.n_comp(sys_num, var);
5433  libmesh_assert_greater_equal (total_dofs, high_nc);
5434  // Add "this is zero" constraint rows for high p
5435  // non-vertex dofs, which are numbered in reverse
5436  for (unsigned int j = low_nc; j != high_nc; ++j)
5437  {
5438  const unsigned int i = total_dofs - j - 1;
5439  _dof_constraints[node.dof_number(sys_num,var,i)].clear();
5440  _primal_constraint_values.erase(node.dof_number(sys_num,var,i));
5441  }
5442  }
5443  }
5444 }
const FEType & variable_type(const unsigned int c) const
Definition: dof_map.h:2141
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
unsigned int sys_number() const
Definition: dof_map.h:2093
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
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.

在文件 dof_map.h2309 行定义.

参考 _constrained_sparsity_construction.

2310 {
2311 #ifdef LIBMESH_ENABLE_CONSTRAINTS
2313 #else
2314  return true;
2315 #endif
2316 }
bool _constrained_sparsity_construction
This flag indicates whether or not we explicitly take constraint equations into account when computin...
Definition: dof_map.h:1834
DofConstraints::const_iterator libMesh::DofMap::constraint_rows_begin ( ) const
inline
返回
An iterator pointing to the first DoF constraint row.

在文件 dof_map.h1010 行定义.

参考 _dof_constraints.

1011  { return _dof_constraints.begin(); }
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
DofConstraints::const_iterator libMesh::DofMap::constraint_rows_end ( ) const
inline
返回
An iterator pointing just past the last DoF constraint row.

在文件 dof_map.h1016 行定义.

参考 _dof_constraints.

1017  { return _dof_constraints.end(); }
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
std::set<GhostingFunctor *>::const_iterator libMesh::DofMap::coupling_functors_begin ( ) const
inline

Beginning of range of coupling functors.

在文件 dof_map.h344 行定义.

参考 _coupling_functors.

参考自 add_neighbors_to_send_list(), libMesh::SparsityPattern::Build::operator()() , 以及 scatter_constraints().

345  { return _coupling_functors.begin(); }
std::set< GhostingFunctor * > _coupling_functors
The list of all GhostingFunctor objects to be used when coupling degrees of freedom in matrix sparsit...
Definition: dof_map.h:1964
std::set<GhostingFunctor *>::const_iterator libMesh::DofMap::coupling_functors_end ( ) const
inline

End of range of coupling functors.

在文件 dof_map.h350 行定义.

参考 _coupling_functors.

参考自 add_neighbors_to_send_list(), libMesh::SparsityPattern::Build::operator()() , 以及 scatter_constraints().

351  { return _coupling_functors.end(); }
std::set< GhostingFunctor * > _coupling_functors
The list of all GhostingFunctor objects to be used when coupling degrees of freedom in matrix sparsit...
Definition: dof_map.h:1964
void libMesh::DofMap::create_dof_constraints ( const MeshBase &  mesh,
Real  time = 0 
)

Rebuilds the raw degree of freedom and DofObject constraints.

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

在文件 dof_map_constraints.C1736 行定义.

参考 _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(), n_variables() , 以及 process_mesh_constraint_rows().

1737 {
1738  parallel_object_only();
1739 
1740  LOG_SCOPE("create_dof_constraints()", "DofMap");
1741 
1742  libmesh_assert (mesh.is_prepared());
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
1748  MeshTools::libmesh_assert_valid_boundary_ids(mesh);
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();
1789  _primal_constraint_values.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)
1823  mesh.sub_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,
1848  variable_number));
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
1866  Threads::parallel_for
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())
1881  Threads::parallel_for
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 process_mesh_constraint_rows(const MeshBase &mesh)
Adds any spline constraints from the Mesh to our DoF constraints.
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.
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition: dof_map.h:2058
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:2034
We&#39;re using a class instead of a typedef to allow forward declarations and future flexibility...
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
std::vector< std::unique_ptr< DirichletBoundaries > > _adjoint_dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition: dof_map.h:2064
unsigned int n_variables() const
Definition: dof_map.h:621
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Data structure containing periodic boundaries.
Definition: dof_map.h:2050
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:2086
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
NodeConstraints _node_constraints
Data structure containing DofObject constraints.
Definition: dof_map.h:2041
DefaultCoupling& libMesh::DofMap::default_algebraic_ghosting ( )
inline

Default algebraic ghosting functor.

在文件 dof_map.h418 行定义.

参考 _default_evaluating.

参考自 add_default_ghosting() , 以及 remove_default_ghosting().

418 { return *_default_evaluating; }
std::unique_ptr< DefaultCoupling > _default_evaluating
The default algebraic GhostingFunctor, used to implement standard libMesh send_list construction...
Definition: dof_map.h:1941
DefaultCoupling& libMesh::DofMap::default_coupling ( )
inline

Default coupling functor.

在文件 dof_map.h356 行定义.

参考 _default_coupling.

参考自 add_default_ghosting() , 以及 remove_default_ghosting().

356 { return *_default_coupling; }
std::unique_ptr< DefaultCoupling > _default_coupling
The default coupling GhostingFunctor, used to implement standard libMesh sparsity pattern constructio...
Definition: dof_map.h:1933
void libMesh::ReferenceCounter::disable_print_counter_info ( )
staticinherited

在文件 reference_counter.C100 行定义.

参考 libMesh::ReferenceCounter::_enable_print_counter.

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...
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.

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

在文件 dof_map.C927 行定义.

参考 _algebraic_ghosting_functors, _coupling_functors, _end_df, _end_old_df, _first_df, _first_old_df, _first_old_scalar_df, _first_scalar_df, _n_dfs, _n_old_dfs, add_neighbors_to_send_list(), clear_send_list(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), libMesh::DofObject::dof_number(), elem_ptr(), end_dof(), first_dof(), libMesh::DofObject::invalid_id, invalidate_dofs(), libMesh::DofObject::n_comp(), n_dofs(), n_SCALAR_dofs(), n_variables(), libMesh::DofObject::n_vars(), node_ptr(), libMesh::on_command_line(), libMesh::DofObject::processor_id(), reinit(), set_nonlocal_dof_objects(), sys_number(), libMesh::Variable::type() , 以及 variable().

928 {
929  // This function must be run on all processors at once
930  parallel_object_only();
931 
932  // Log how long it takes to distribute the degrees of freedom
933  LOG_SCOPE("distribute_dofs()", "DofMap");
934 
935  libmesh_assert (mesh.is_prepared());
936 
937  const processor_id_type proc_id = this->processor_id();
938  const processor_id_type n_proc = this->n_processors();
939 
940  // libmesh_assert_greater (this->n_variables(), 0);
941  libmesh_assert_less (proc_id, n_proc);
942 
943  // re-init in case the mesh has changed
944  this->reinit(mesh);
945 
946  // By default distribute variables in a
947  // var-major fashion, but allow run-time
948  // specification
949  bool node_major_dofs = libMesh::on_command_line ("--node-major-dofs");
950 
951  // The DOF counter, will be incremented as we encounter
952  // new degrees of freedom
953  dof_id_type next_free_dof = 0;
954 
955  // Clear the send list before we rebuild it
956  this->clear_send_list();
957 
958  // Set temporary DOF indices on this processor
959  if (node_major_dofs)
960  this->distribute_local_dofs_node_major (next_free_dof, mesh);
961  else
962  this->distribute_local_dofs_var_major (next_free_dof, mesh);
963 
964  // Get DOF counts on all processors
965  std::vector<dof_id_type> dofs_on_proc(n_proc, 0);
966  this->comm().allgather(next_free_dof, dofs_on_proc);
967 
968  // Resize and fill the _first_df and _end_df arrays
969 #ifdef LIBMESH_ENABLE_AMR
972 #endif
973 
974  _first_df.resize(n_proc);
975  _end_df.resize (n_proc);
976 
977  // Get DOF offsets
978  _first_df[0] = 0;
979  for (processor_id_type i=1; i < n_proc; ++i)
980  _first_df[i] = _end_df[i-1] = _first_df[i-1] + dofs_on_proc[i-1];
981  _end_df[n_proc-1] = _first_df[n_proc-1] + dofs_on_proc[n_proc-1];
982 
983  // Clear all the current DOF indices
984  // (distribute_dofs expects them cleared!)
985  this->invalidate_dofs(mesh);
986 
987  next_free_dof = _first_df[proc_id];
988 
989  // Set permanent DOF indices on this processor
990  if (node_major_dofs)
991  this->distribute_local_dofs_node_major (next_free_dof, mesh);
992  else
993  this->distribute_local_dofs_var_major (next_free_dof, mesh);
994 
995  libmesh_assert_equal_to (next_free_dof, _end_df[proc_id]);
996 
997  //------------------------------------------------------------
998  // At this point, all n_comp and dof_number values on local
999  // DofObjects should be correct, but a DistributedMesh might have
1000  // incorrect values on non-local DofObjects. Let's request the
1001  // correct values from each other processor.
1002 
1003  if (this->n_processors() > 1)
1004  {
1005  this->set_nonlocal_dof_objects(mesh.nodes_begin(),
1006  mesh.nodes_end(),
1007  mesh, &DofMap::node_ptr);
1008 
1009  this->set_nonlocal_dof_objects(mesh.elements_begin(),
1010  mesh.elements_end(),
1011  mesh, &DofMap::elem_ptr);
1012  }
1013 
1014 #ifdef DEBUG
1015  {
1016  const unsigned int
1017  sys_num = this->sys_number();
1018 
1019  // Processors should all agree on DoF ids for the newly numbered
1020  // system.
1021  MeshTools::libmesh_assert_valid_dof_ids(mesh, sys_num);
1022 
1023  // DoF processor ids should match DofObject processor ids
1024  for (auto & node : mesh.node_ptr_range())
1025  {
1026  DofObject const * const dofobj = node;
1027  const processor_id_type obj_proc_id = dofobj->processor_id();
1028 
1029  for (auto v : make_range(dofobj->n_vars(sys_num)))
1030  for (auto c : make_range(dofobj->n_comp(sys_num,v)))
1031  {
1032  const dof_id_type dofid = dofobj->dof_number(sys_num,v,c);
1033  libmesh_assert_greater_equal (dofid, this->first_dof(obj_proc_id));
1034  libmesh_assert_less (dofid, this->end_dof(obj_proc_id));
1035  }
1036  }
1037 
1038  for (auto & elem : mesh.element_ptr_range())
1039  {
1040  DofObject const * const dofobj = elem;
1041  const processor_id_type obj_proc_id = dofobj->processor_id();
1042 
1043  for (auto v : make_range(dofobj->n_vars(sys_num)))
1044  for (auto c : make_range(dofobj->n_comp(sys_num,v)))
1045  {
1046  const dof_id_type dofid = dofobj->dof_number(sys_num,v,c);
1047  libmesh_assert_greater_equal (dofid, this->first_dof(obj_proc_id));
1048  libmesh_assert_less (dofid, this->end_dof(obj_proc_id));
1049  }
1050  }
1051  }
1052 #endif
1053 
1054  // Set the total number of degrees of freedom, then start finding
1055  // SCALAR degrees of freedom
1056 #ifdef LIBMESH_ENABLE_AMR
1057  _n_old_dfs = _n_dfs;
1059 #endif
1060  _n_dfs = _end_df[n_proc-1];
1061  _first_scalar_df.clear();
1063  dof_id_type current_SCALAR_dof_index = n_dofs() - n_SCALAR_dofs();
1064 
1065  // Calculate and cache the initial DoF indices for SCALAR variables.
1066  // This is an O(N_vars) calculation so we want to do it once per
1067  // renumbering rather than once per SCALAR_dof_indices() call
1068 
1069  for (auto v : make_range(this->n_variables()))
1070  if (this->variable(v).type().family == SCALAR)
1071  {
1072  _first_scalar_df[v] = current_SCALAR_dof_index;
1073  current_SCALAR_dof_index += this->variable(v).type().order.get_order();
1074  }
1075 
1076  // Allow our GhostingFunctor objects to reinit if necessary
1077  for (const auto & gf : _algebraic_ghosting_functors)
1078  {
1079  libmesh_assert(gf);
1080  gf->dofmap_reinit();
1081  }
1082 
1083  for (const auto & gf : _coupling_functors)
1084  {
1085  libmesh_assert(gf);
1086  gf->dofmap_reinit();
1087  }
1088 
1089  // Note that in the add_neighbors_to_send_list nodes on processor
1090  // boundaries that are shared by multiple elements are added for
1091  // each element.
1092  this->add_neighbors_to_send_list(mesh);
1093 
1094  // Here we used to clean up that data structure; now System and
1095  // EquationSystems call that for us, after we've added constraint
1096  // dependencies to the send_list too.
1097  // this->sort_send_list ();
1098 
1099  // Return total number of DOFs across all procs. We compute and
1100  // return this as a std::size_t so that we can detect situations in
1101  // which the total number of DOFs across all procs would exceed the
1102  // capability of the underlying NumericVector representation to
1103  // index into it correctly (std::size_t is the largest unsigned
1104  // type, so no NumericVector representation can exceed it).
1105  return std::accumulate(dofs_on_proc.begin(), dofs_on_proc.end(), static_cast<std::size_t>(0));
1106 }
DofObject * elem_ptr(MeshBase &mesh, dof_id_type i) const
Definition: dof_map.C:348
void distribute_local_dofs_node_major(dof_id_type &next_free_dof, MeshBase &mesh)
Distributes the global degrees of freedom for dofs on this processor.
Definition: dof_map.C:1196
const FEType & type() const
Definition: variable.h:140
DofObject * node_ptr(MeshBase &mesh, dof_id_type i) const
Definition: dof_map.C:341
void clear_send_list()
Clears the _send_list vector.
Definition: dof_map.h:485
std::set< GhostingFunctor * > _algebraic_ghosting_functors
The list of all GhostingFunctor objects to be used when distributing ghosted vectors.
Definition: dof_map.h:1951
std::vector< dof_id_type > _end_old_df
Last old DOF index (plus 1) on processor p.
Definition: dof_map.h:2011
void invalidate_dofs(MeshBase &mesh) const
Invalidates all active DofObject dofs for this system.
Definition: dof_map.C:835
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:2111
dof_id_type n_dofs() const
Definition: dof_map.h:659
std::vector< dof_id_type > _first_old_df
First old DOF index on processor p.
Definition: dof_map.h:2006
uint8_t processor_id_type
Definition: id_types.h:104
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:1887
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:1544
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:2017
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:356
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:477
void reinit(MeshBase &mesh)
Reinitialize the underlying data structures conformal to the current mesh.
Definition: dof_map.C:506
unsigned int sys_number() const
Definition: dof_map.h:2093
dof_id_type end_dof() const
Definition: dof_map.h:711
unsigned int n_variables() const
Definition: dof_map.h:621
dof_id_type _n_old_dfs
Total number of degrees of freedom on old dof objects.
Definition: dof_map.h:2001
std::set< GhostingFunctor * > _coupling_functors
The list of all GhostingFunctor objects to be used when coupling degrees of freedom in matrix sparsit...
Definition: dof_map.h:1964
std::vector< dof_id_type > _end_df
Last DOF index (plus 1) on processor p.
Definition: dof_map.h:1881
dof_id_type n_SCALAR_dofs() const
Definition: dof_map.h:664
std::vector< dof_id_type > _first_df
First DOF index on processor p.
Definition: dof_map.h:1876
bool on_command_line(std::string arg)
Definition: libmesh.C:872
void distribute_local_dofs_var_major(dof_id_type &next_free_dof, MeshBase &mesh)
Distributes the global degrees of freedom, for dofs on this processor.
Definition: dof_map.C:1299
dof_id_type first_dof() const
Definition: dof_map.h:687
uint8_t dof_id_type
Definition: id_types.h:67
dof_id_type _n_dfs
Total number of degrees of freedom.
Definition: dof_map.h:1988
void libMesh::DofMap::distribute_local_dofs_node_major ( dof_id_type next_free_dof,
MeshBase &  mesh 
)
private

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

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

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

在文件 dof_map.C1196 行定义.

参考 libMesh::Variable::active_on_subdomain(), assert_no_nodes_missed(), distribute_scalar_dofs(), libMesh::DofObject::invalid_id, n_variable_groups(), libMesh::VariableGroup::n_variables(), sys_number(), libMesh::Variable::type() , 以及 variable_group().

参考自 distribute_dofs().

1198 {
1199  const unsigned int sys_num = this->sys_number();
1200  const unsigned int n_var_groups = this->n_variable_groups();
1201 
1202  // Our numbering here must be kept consistent with the numbering
1203  // scheme assumed by DofMap::local_variable_indices!
1204 
1205  //-------------------------------------------------------------------------
1206  // First count and assign temporary numbers to local dofs
1207  for (auto & elem : mesh.active_local_element_ptr_range())
1208  {
1209  // Only number dofs connected to active
1210  // elements on this processor.
1211  const unsigned int n_nodes = elem->n_nodes();
1212 
1213  // First number the nodal DOFS
1214  for (unsigned int n=0; n<n_nodes; n++)
1215  {
1216  Node & node = elem->node_ref(n);
1217 
1218  for (unsigned vg=0; vg<n_var_groups; vg++)
1219  {
1220  const VariableGroup & vg_description(this->variable_group(vg));
1221 
1222  if ((vg_description.type().family != SCALAR) &&
1223  (vg_description.active_on_subdomain(elem->subdomain_id())))
1224  {
1225  // assign dof numbers (all at once) if this is
1226  // our node and if they aren't already there
1227  if ((node.n_comp_group(sys_num,vg) > 0) &&
1228  (node.processor_id() == this->processor_id()) &&
1229  (node.vg_dof_base(sys_num,vg) ==
1231  {
1232  node.set_vg_dof_base(sys_num, vg,
1233  next_free_dof);
1234  next_free_dof += (vg_description.n_variables()*
1235  node.n_comp_group(sys_num,vg));
1236  //node.debug_buffer();
1237  }
1238  }
1239  }
1240  }
1241 
1242  // Now number the element DOFS
1243  for (unsigned vg=0; vg<n_var_groups; vg++)
1244  {
1245  const VariableGroup & vg_description(this->variable_group(vg));
1246 
1247  if ((vg_description.type().family != SCALAR) &&
1248  (vg_description.active_on_subdomain(elem->subdomain_id())))
1249  if (elem->n_comp_group(sys_num,vg) > 0)
1250  {
1251  libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg),
1253 
1254  elem->set_vg_dof_base(sys_num,
1255  vg,
1256  next_free_dof);
1257 
1258  next_free_dof += (vg_description.n_variables()*
1259  elem->n_comp(sys_num,vg));
1260  }
1261  }
1262  } // done looping over elements
1263 
1264 
1265  // we may have missed assigning DOFs to nodes that we own
1266  // but to which we have no connected elements matching our
1267  // variable restriction criterion. this will happen, for example,
1268  // if variable V is restricted to subdomain S. We may not own
1269  // any elements which live in S, but we may own nodes which are
1270  // *connected* to elements which do. in this scenario these nodes
1271  // will presently have unnumbered DOFs. we need to take care of
1272  // them here since we own them and no other processor will touch them.
1273  for (auto & node : mesh.local_node_ptr_range())
1274  for (unsigned vg=0; vg<n_var_groups; vg++)
1275  {
1276  const VariableGroup & vg_description(this->variable_group(vg));
1277 
1278  if (node->n_comp_group(sys_num,vg))
1279  if (node->vg_dof_base(sys_num,vg) == DofObject::invalid_id)
1280  {
1281  node->set_vg_dof_base (sys_num,
1282  vg,
1283  next_free_dof);
1284 
1285  next_free_dof += (vg_description.n_variables()*
1286  node->n_comp(sys_num,vg));
1287  }
1288  }
1289 
1290  this->distribute_scalar_dofs(next_free_dof);
1291 
1292 #ifdef DEBUG
1293  this->assert_no_nodes_missed(mesh);
1294 #endif // DEBUG
1295 }
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:2101
void assert_no_nodes_missed(MeshBase &mesh)
Definition: dof_map.C:1418
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:477
unsigned int n_variable_groups() const
Definition: dof_map.h:613
unsigned int sys_number() const
Definition: dof_map.h:2093
void distribute_scalar_dofs(dof_id_type &next_free_dof)
Definition: dof_map.C:1394
void libMesh::DofMap::distribute_local_dofs_var_major ( dof_id_type next_free_dof,
MeshBase &  mesh 
)
private

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

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

在文件 dof_map.C1299 行定义.

参考 libMesh::Variable::active_on_subdomain(), assert_no_nodes_missed(), distribute_scalar_dofs(), libMesh::DofObject::invalid_id, n_variable_groups(), libMesh::VariableGroup::n_variables(), sys_number(), libMesh::Variable::type() , 以及 variable_group().

参考自 distribute_dofs().

1301 {
1302  const unsigned int sys_num = this->sys_number();
1303  const unsigned int n_var_groups = this->n_variable_groups();
1304 
1305  // Our numbering here must be kept consistent with the numbering
1306  // scheme assumed by DofMap::local_variable_indices!
1307 
1308  //-------------------------------------------------------------------------
1309  // First count and assign temporary numbers to local dofs
1310  for (unsigned vg=0; vg<n_var_groups; vg++)
1311  {
1312  const VariableGroup & vg_description(this->variable_group(vg));
1313 
1314  const unsigned int n_vars_in_group = vg_description.n_variables();
1315 
1316  // Skip the SCALAR dofs
1317  if (vg_description.type().family == SCALAR)
1318  continue;
1319 
1320  for (auto & elem : mesh.active_local_element_ptr_range())
1321  {
1322  // Only number dofs connected to active elements on this
1323  // processor and only variables which are active on on this
1324  // element's subdomain.
1325  if (!vg_description.active_on_subdomain(elem->subdomain_id()))
1326  continue;
1327 
1328  const unsigned int n_nodes = elem->n_nodes();
1329 
1330  // First number the nodal DOFS
1331  for (unsigned int n=0; n<n_nodes; n++)
1332  {
1333  Node & node = elem->node_ref(n);
1334 
1335  // assign dof numbers (all at once) if this is
1336  // our node and if they aren't already there
1337  if ((node.n_comp_group(sys_num,vg) > 0) &&
1338  (node.processor_id() == this->processor_id()) &&
1339  (node.vg_dof_base(sys_num,vg) ==
1341  {
1342  node.set_vg_dof_base(sys_num, vg, next_free_dof);
1343 
1344  next_free_dof += (n_vars_in_group*
1345  node.n_comp_group(sys_num,vg));
1346  }
1347  }
1348 
1349  // Now number the element DOFS
1350  if (elem->n_comp_group(sys_num,vg) > 0)
1351  {
1352  libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg),
1354 
1355  elem->set_vg_dof_base(sys_num,
1356  vg,
1357  next_free_dof);
1358 
1359  next_free_dof += (n_vars_in_group*
1360  elem->n_comp_group(sys_num,vg));
1361  }
1362  } // end loop on elements
1363 
1364  // we may have missed assigning DOFs to nodes that we own
1365  // but to which we have no connected elements matching our
1366  // variable restriction criterion. this will happen, for example,
1367  // if variable V is restricted to subdomain S. We may not own
1368  // any elements which live in S, but we may own nodes which are
1369  // *connected* to elements which do. in this scenario these nodes
1370  // will presently have unnumbered DOFs. we need to take care of
1371  // them here since we own them and no other processor will touch them.
1372  for (auto & node : mesh.local_node_ptr_range())
1373  if (node->n_comp_group(sys_num,vg))
1374  if (node->vg_dof_base(sys_num,vg) == DofObject::invalid_id)
1375  {
1376  node->set_vg_dof_base (sys_num,
1377  vg,
1378  next_free_dof);
1379 
1380  next_free_dof += (n_vars_in_group*
1381  node->n_comp_group(sys_num,vg));
1382  }
1383  } // end loop on variable groups
1384 
1385  this->distribute_scalar_dofs(next_free_dof);
1386 
1387 #ifdef DEBUG
1388  this->assert_no_nodes_missed(mesh);
1389 #endif
1390 }
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:2101
void assert_no_nodes_missed(MeshBase &mesh)
Definition: dof_map.C:1418
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:477
unsigned int n_variable_groups() const
Definition: dof_map.h:613
unsigned int sys_number() const
Definition: dof_map.h:2093
void distribute_scalar_dofs(dof_id_type &next_free_dof)
Definition: dof_map.C:1394
void libMesh::DofMap::distribute_scalar_dofs ( dof_id_type next_free_dof)
private

在文件 dof_map.C1394 行定义.

参考 _n_SCALAR_dofs, n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::Variable::type() , 以及 variable_group().

参考自 distribute_local_dofs_node_major() , 以及 distribute_local_dofs_var_major().

1395 {
1396  this->_n_SCALAR_dofs = 0;
1397  for (auto vg : make_range(this->n_variable_groups()))
1398  {
1399  const VariableGroup & vg_description(this->variable_group(vg));
1400 
1401  if (vg_description.type().family == SCALAR)
1402  {
1403  this->_n_SCALAR_dofs += (vg_description.n_variables()*
1404  vg_description.type().order.get_order());
1405  continue;
1406  }
1407  }
1408 
1409  // Only increment next_free_dof if we're on the processor
1410  // that holds this SCALAR variable
1411  if (this->processor_id() == (this->n_processors()-1))
1412  next_free_dof += _n_SCALAR_dofs;
1413 }
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:2101
dof_id_type _n_SCALAR_dofs
The total number of SCALAR dofs associated to all SCALAR variables.
Definition: dof_map.h:1994
unsigned int n_variable_groups() const
Definition: dof_map.h:613
void libMesh::DofMap::dof_indices ( const Elem *const  elem,
std::vector< dof_id_type > &  di 
) const

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

在文件 dof_map.C1992 行定义.

参考 _dof_indices(), libMesh::Variable::active_on_subdomain(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::VariableGroup::number(), SCALAR_dof_indices(), libMesh::Variable::type() , 以及 variable_group().

参考自 add_neighbors_to_send_list(), dof_indices(), is_evaluable(), max_constraint_error(), process_mesh_constraint_rows(), scatter_constraints() , 以及 libMesh::SparsityPattern::Build::sorted_connected_dofs().

1994 {
1995  // We now allow elem==nullptr to request just SCALAR dofs
1996  // libmesh_assert(elem);
1997 
1998  // If we are asking for current indices on an element, it ought to
1999  // be an active element (or a Side proxy, which also thinks it's
2000  // active)
2001  libmesh_assert(!elem || elem->active());
2002 
2003  LOG_SCOPE("dof_indices()", "DofMap");
2004 
2005  // Clear the DOF indices vector
2006  di.clear();
2007 
2008  const unsigned int n_var_groups = this->n_variable_groups();
2009 
2010 #ifdef DEBUG
2011  // Check that sizes match in DEBUG mode
2012  std::size_t tot_size = 0;
2013 #endif
2014 
2015  if (elem && elem->type() == TRI3SUBDIVISION)
2016  {
2017  // Subdivision surface FE require the 1-ring around elem
2018  const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
2019 
2020  // Ghost subdivision elements have no real dofs
2021  if (!sd_elem->is_ghost())
2022  {
2023  // Determine the nodes contributing to element elem
2024  std::vector<const Node *> elem_nodes;
2025  MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
2026 
2027  // Get the dof numbers
2028  for (unsigned int vg=0; vg<n_var_groups; vg++)
2029  {
2030  const VariableGroup & var = this->variable_group(vg);
2031  const unsigned int vars_in_group = var.n_variables();
2032 
2033  if (var.type().family == SCALAR &&
2034  var.active_on_subdomain(elem->subdomain_id()))
2035  {
2036  for (unsigned int vig=0; vig != vars_in_group; ++vig)
2037  {
2038 #ifdef DEBUG
2039  tot_size += var.type().order;
2040 #endif
2041  std::vector<dof_id_type> di_new;
2042  this->SCALAR_dof_indices(di_new,var.number(vig));
2043  di.insert( di.end(), di_new.begin(), di_new.end());
2044  }
2045  }
2046  else
2047  for (unsigned int vig=0; vig != vars_in_group; ++vig)
2048  {
2049  _dof_indices(*elem, elem->p_level(), di, vg, vig,
2050  elem_nodes.data(),
2051  cast_int<unsigned int>(elem_nodes.size())
2052 #ifdef DEBUG
2053  , var.number(vig), tot_size
2054 #endif
2055  );
2056  }
2057  }
2058  }
2059 
2060  return;
2061  }
2062 
2063  // Get the dof numbers for each variable
2064  const unsigned int n_nodes = elem ? elem->n_nodes() : 0;
2065  for (unsigned int vg=0; vg<n_var_groups; vg++)
2066  {
2067  const VariableGroup & var = this->variable_group(vg);
2068  const unsigned int vars_in_group = var.n_variables();
2069 
2070  if (var.type().family == SCALAR &&
2071  (!elem ||
2072  var.active_on_subdomain(elem->subdomain_id())))
2073  {
2074  for (unsigned int vig=0; vig != vars_in_group; ++vig)
2075  {
2076 #ifdef DEBUG
2077  tot_size += var.type().order;
2078 #endif
2079  std::vector<dof_id_type> di_new;
2080  this->SCALAR_dof_indices(di_new,var.number(vig));
2081  di.insert( di.end(), di_new.begin(), di_new.end());
2082  }
2083  }
2084  else if (elem)
2085  for (unsigned int vig=0; vig != vars_in_group; ++vig)
2086  {
2087  _dof_indices(*elem, elem->p_level(), di, vg, vig,
2088  elem->get_nodes(), n_nodes
2089 #ifdef DEBUG
2090  , var.number(vig), tot_size
2091 #endif
2092  );
2093  }
2094  }
2095 
2096 #ifdef DEBUG
2097  libmesh_assert_equal_to (tot_size, di.size());
2098 #endif
2099 }
void _dof_indices(const Elem &elem, int p_level, std::vector< dof_id_type > &di, const unsigned int vg, const unsigned int vig, const Node *const *nodes, unsigned int n_nodes#ifdef DEBUG, const unsigned int v, std::size_t &tot_size#endif) const
Helper function that gets the dof indices on the current element for a non-SCALAR type variable...
Definition: dof_map.C:2381
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:2101
unsigned int n_variable_groups() const
Definition: dof_map.h:613
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:2544
void libMesh::DofMap::dof_indices ( const Elem *const  elem,
std::vector< dof_id_type > &  di,
const unsigned int  vn,
int  p_level = -12345 
) const

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

For one variable, and potentially for a non-default element p refinement level

在文件 dof_map.C2102 行定义.

参考 _dof_indices(), _variable_group_numbers, libMesh::Variable::active_on_subdomain(), libMesh::VariableGroup::number(), SCALAR_dof_indices(), libMesh::Variable::type() , 以及 variable_group().

2106 {
2107  // We now allow elem==nullptr to request just SCALAR dofs
2108  // libmesh_assert(elem);
2109 
2110  LOG_SCOPE("dof_indices()", "DofMap");
2111 
2112  // Clear the DOF indices vector
2113  di.clear();
2114 
2115  // Use the default p refinement level?
2116  if (p_level == -12345)
2117  p_level = elem ? elem->p_level() : 0;
2118 
2119  const unsigned int vg = this->_variable_group_numbers[vn];
2120  const VariableGroup & var = this->variable_group(vg);
2121  const unsigned int vig = vn - var.number();
2122 
2123 #ifdef DEBUG
2124  // Check that sizes match in DEBUG mode
2125  std::size_t tot_size = 0;
2126 #endif
2127 
2128  if (elem && elem->type() == TRI3SUBDIVISION)
2129  {
2130  // Subdivision surface FE require the 1-ring around elem
2131  const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
2132 
2133  // Ghost subdivision elements have no real dofs
2134  if (!sd_elem->is_ghost())
2135  {
2136  // Determine the nodes contributing to element elem
2137  std::vector<const Node *> elem_nodes;
2138  MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
2139 
2140  _dof_indices(*elem, p_level, di, vg, vig, elem_nodes.data(),
2141  cast_int<unsigned int>(elem_nodes.size())
2142 #ifdef DEBUG
2143  , vn, tot_size
2144 #endif
2145  );
2146  }
2147 
2148  return;
2149  }
2150 
2151  // Get the dof numbers
2152  if (var.type().family == SCALAR &&
2153  (!elem ||
2154  var.active_on_subdomain(elem->subdomain_id())))
2155  {
2156 #ifdef DEBUG
2157  tot_size += var.type().order;
2158 #endif
2159  std::vector<dof_id_type> di_new;
2160  this->SCALAR_dof_indices(di_new,vn);
2161  di.insert( di.end(), di_new.begin(), di_new.end());
2162  }
2163  else if (elem)
2164  _dof_indices(*elem, p_level, di, vg, vig, elem->get_nodes(),
2165  elem->n_nodes()
2166 #ifdef DEBUG
2167  , vn, tot_size
2168 #endif
2169  );
2170 
2171 #ifdef DEBUG
2172  libmesh_assert_equal_to (tot_size, di.size());
2173 #endif
2174 }
void _dof_indices(const Elem &elem, int p_level, std::vector< dof_id_type > &di, const unsigned int vg, const unsigned int vig, const Node *const *nodes, unsigned int n_nodes#ifdef DEBUG, const unsigned int v, std::size_t &tot_size#endif) const
Helper function that gets the dof indices on the current element for a non-SCALAR type variable...
Definition: dof_map.C:2381
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:2101
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:2544
std::vector< unsigned int > _variable_group_numbers
The variable group number for each variable.
Definition: dof_map.h:1849
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.

在文件 dof_map.C2177 行定义.

参考 libMesh::DofObject::invalid_id, n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::VariableGroup::number(), SCALAR_dof_indices(), sys_number(), libMesh::Variable::type() , 以及 variable_group().

2179 {
2180  // We allow node==nullptr to request just SCALAR dofs
2181  // libmesh_assert(elem);
2182 
2183  LOG_SCOPE("dof_indices(Node)", "DofMap");
2184 
2185  // Clear the DOF indices vector
2186  di.clear();
2187 
2188  const unsigned int n_var_groups = this->n_variable_groups();
2189  const unsigned int sys_num = this->sys_number();
2190 
2191  // Get the dof numbers
2192  for (unsigned int vg=0; vg<n_var_groups; vg++)
2193  {
2194  const VariableGroup & var = this->variable_group(vg);
2195  const unsigned int vars_in_group = var.n_variables();
2196 
2197  if (var.type().family == SCALAR)
2198  {
2199  for (unsigned int vig=0; vig != vars_in_group; ++vig)
2200  {
2201  std::vector<dof_id_type> di_new;
2202  this->SCALAR_dof_indices(di_new,var.number(vig));
2203  di.insert( di.end(), di_new.begin(), di_new.end());
2204  }
2205  }
2206  else
2207  {
2208  const int n_comp = node->n_comp_group(sys_num,vg);
2209  for (unsigned int vig=0; vig != vars_in_group; ++vig)
2210  {
2211  for (int i=0; i != n_comp; ++i)
2212  {
2213  const dof_id_type d =
2214  node->dof_number(sys_num, vg, vig, i, n_comp);
2215  libmesh_assert_not_equal_to
2216  (d, DofObject::invalid_id);
2217  di.push_back(d);
2218  }
2219  }
2220  }
2221  }
2222 }
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:2101
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:477
unsigned int n_variable_groups() const
Definition: dof_map.h:613
unsigned int sys_number() const
Definition: dof_map.h:2093
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:2544
uint8_t dof_id_type
Definition: id_types.h:67
void libMesh::DofMap::dof_indices ( const Node *const  node,
std::vector< dof_id_type > &  di,
const unsigned int  vn 
) const

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

在文件 dof_map.C2225 行定义.

参考 _variable_group_numbers, dof_indices(), libMesh::DofObject::invalid_id, libMesh::invalid_uint, libMesh::VariableGroup::number(), SCALAR_dof_indices(), sys_number(), libMesh::Variable::type() , 以及 variable_group().

2228 {
2229  if (vn == libMesh::invalid_uint)
2230  {
2231  this->dof_indices(node, di);
2232  return;
2233  }
2234 
2235  // We allow node==nullptr to request just SCALAR dofs
2236  // libmesh_assert(elem);
2237 
2238  LOG_SCOPE("dof_indices(Node)", "DofMap");
2239 
2240  // Clear the DOF indices vector
2241  di.clear();
2242 
2243  const unsigned int sys_num = this->sys_number();
2244 
2245  // Get the dof numbers
2246  const unsigned int vg = this->_variable_group_numbers[vn];
2247  const VariableGroup & var = this->variable_group(vg);
2248 
2249  if (var.type().family == SCALAR)
2250  {
2251  std::vector<dof_id_type> di_new;
2252  this->SCALAR_dof_indices(di_new,vn);
2253  di.insert( di.end(), di_new.begin(), di_new.end());
2254  }
2255  else
2256  {
2257  const unsigned int vig = vn - var.number();
2258  const int n_comp = node->n_comp_group(sys_num,vg);
2259  for (int i=0; i != n_comp; ++i)
2260  {
2261  const dof_id_type d =
2262  node->dof_number(sys_num, vg, vig, i, n_comp);
2263  libmesh_assert_not_equal_to
2264  (d, DofObject::invalid_id);
2265  di.push_back(d);
2266  }
2267  }
2268 }
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:254
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:2101
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:477
unsigned int sys_number() const
Definition: dof_map.h:2093
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:2544
std::vector< unsigned int > _variable_group_numbers
The variable group number for each variable.
Definition: dof_map.h:1849
uint8_t dof_id_type
Definition: id_types.h:67
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Fills the vector di with the global degree of freedom indices for the element.
Definition: dof_map.C:1992
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.

在文件 dof_map.C2271 行定义.

参考 _node_dof_indices().

2275 {
2276  this->_node_dof_indices(elem, n, elem.node_ref(n), di, vn);
2277 }
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:2296
processor_id_type libMesh::DofMap::dof_owner ( const dof_id_type  dof) const
inline
返回
The processor id that owns the dof index dof

在文件 dof_map.h717 行定义.

参考 _end_df.

718  { std::vector<dof_id_type>::const_iterator ub =
719  std::upper_bound(_end_df.begin(), _end_df.end(), dof);
720  libmesh_assert (ub != _end_df.end());
721  return cast_int<processor_id_type>(ub - _end_df.begin());
722  }
std::vector< dof_id_type > _end_df
Last DOF index (plus 1) on processor p.
Definition: dof_map.h:1881
DofObject * libMesh::DofMap::elem_ptr ( MeshBase &  mesh,
dof_id_type  i 
) const
private
返回
The Elem pointer with index i from the mesh.

在文件 dof_map.C348 行定义.

参考自 distribute_dofs().

349 {
350  return mesh.elem_ptr(i);
351 }
void libMesh::ReferenceCounter::enable_print_counter_info ( )
staticinherited

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

在文件 reference_counter.C94 行定义.

参考 libMesh::ReferenceCounter::_enable_print_counter.

95 {
96  _enable_print_counter = true;
97  return;
98 }
static bool _enable_print_counter
Flag to control whether reference count information is printed when print_info is called...
dof_id_type libMesh::DofMap::end_dof ( const processor_id_type  proc) const
inline
返回
The first dof index that is after all indices local to processor proc.

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

在文件 dof_map.h708 行定义.

参考 _end_df.

参考自 libMesh::SparsityPattern::Build::handle_vi_vj(), libMesh::SparsityPattern::Build::join(), libMesh::SparsityPattern::Build::operator()() , 以及 libMesh::SparsityPattern::Build::parallel_sync().

709  { libmesh_assert_less (proc, _end_df.size()); return _end_df[proc]; }
std::vector< dof_id_type > _end_df
Last DOF index (plus 1) on processor p.
Definition: dof_map.h:1881
dof_id_type libMesh::DofMap::end_dof ( ) const
inline

在文件 dof_map.h711 行定义.

参考自 distribute_dofs(), local_index(), n_local_constrained_dofs() , 以及 process_mesh_constraint_rows().

712  { return this->end_dof(this->processor_id()); }
dof_id_type end_dof() const
Definition: dof_map.h:711
dof_id_type libMesh::DofMap::end_old_dof ( const processor_id_type  proc) const
inline
返回
The first old dof index that is after all indices local to processor proc.

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

在文件 dof_map.h731 行定义.

参考 _end_old_df.

732  { libmesh_assert_less (proc, _end_old_df.size()); return _end_old_df[proc]; }
std::vector< dof_id_type > _end_old_df
Last old DOF index (plus 1) on processor p.
Definition: dof_map.h:2011
dof_id_type libMesh::DofMap::end_old_dof ( ) const
inline

在文件 dof_map.h734 行定义.

735  { return this->end_old_dof(this->processor_id()); }
dof_id_type end_old_dof() const
Definition: dof_map.h:734
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

在文件 dof_map_constraints.C3285 行定义.

参考 _adjoint_constraint_values, _dof_constraints, libMesh::NumericVector< T >::build(), libMesh::NumericVector< T >::close(), libMesh::NumericVector< T >::closed(), libMesh::NumericVector< T >::get(), get_send_list(), local_index(), libMesh::NumericVector< T >::local_size(), libMesh::NumericVector< T >::localize(), n_constrained_dofs(), n_dofs(), n_local_dofs(), libMesh::NumericVector< T >::set(), libMesh::NumericVector< T >::size() , 以及 libMesh::NumericVector< T >::type().

3287 {
3288  parallel_object_only();
3289 
3290  if (!this->n_constrained_dofs())
3291  return;
3292 
3293  LOG_SCOPE("enforce_adjoint_constraints_exactly()", "DofMap");
3294 
3295  NumericVector<Number> * v_local = nullptr; // will be initialized below
3296  NumericVector<Number> * v_global = nullptr; // will be initialized below
3297  std::unique_ptr<NumericVector<Number>> v_built;
3298  if (v.type() == SERIAL)
3299  {
3300  v_built = NumericVector<Number>::build(this->comm());
3301  v_built->init(this->n_dofs(), this->n_local_dofs(), true, PARALLEL);
3302  v_built->close();
3303 
3304  for (dof_id_type i=v_built->first_local_index();
3305  i<v_built->last_local_index(); i++)
3306  v_built->set(i, v(i));
3307  v_built->close();
3308  v_global = v_built.get();
3309 
3310  v_local = &v;
3311  libmesh_assert (v_local->closed());
3312  }
3313  else if (v.type() == PARALLEL)
3314  {
3315  v_built = NumericVector<Number>::build(this->comm());
3316  v_built->init (v.size(), v.local_size(),
3317  this->get_send_list(), true, GHOSTED);
3318  v.localize(*v_built, this->get_send_list());
3319  v_built->close();
3320  v_local = v_built.get();
3321 
3322  v_global = &v;
3323  }
3324  else if (v.type() == GHOSTED)
3325  {
3326  v_local = &v;
3327  v_global = &v;
3328  }
3329  else // unknown v.type()
3330  libmesh_error_msg("ERROR: Unknown v.type() == " << v.type());
3331 
3332  // We should never hit these asserts because we should error-out in
3333  // else clause above. Just to be sure we don't try to use v_local
3334  // and v_global uninitialized...
3335  libmesh_assert(v_local);
3336  libmesh_assert(v_global);
3337 
3338  // Do we have any non_homogeneous constraints?
3339  const AdjointDofConstraintValues::const_iterator
3340  adjoint_constraint_map_it = _adjoint_constraint_values.find(q);
3341  const DofConstraintValueMap * constraint_map =
3342  (adjoint_constraint_map_it == _adjoint_constraint_values.end()) ?
3343  nullptr : &adjoint_constraint_map_it->second;
3344 
3345  for (const auto & [constrained_dof, constraint_row] : _dof_constraints)
3346  {
3347  if (!this->local_index(constrained_dof))
3348  continue;
3349 
3350  Number exact_value = 0;
3351  if (constraint_map)
3352  {
3353  const DofConstraintValueMap::const_iterator
3354  adjoint_constraint_it =
3355  constraint_map->find(constrained_dof);
3356  if (adjoint_constraint_it != constraint_map->end())
3357  exact_value = adjoint_constraint_it->second;
3358  }
3359 
3360  for (const auto & j : constraint_row)
3361  exact_value += j.second * (*v_local)(j.first);
3362 
3363  v_global->set(constrained_dof, exact_value);
3364  }
3365 
3366  // If the old vector was serial, we probably need to send our values
3367  // to other processors
3368  if (v.type() == SERIAL)
3369  {
3370 #ifndef NDEBUG
3371  v_global->close();
3372 #endif
3373  v_global->localize (v);
3374  }
3375  v.close();
3376 }
virtual bool closed() const
检查向量是否已经关闭并准备好进行计算。
dof_id_type n_constrained_dofs() const
virtual numeric_index_type size() const =0
获取向量的大小。
提供了不同线性代数库的向量存储方案的统一接口。
Definition: dof_map.h:67
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:831
dof_id_type n_dofs() const
Definition: dof_map.h:659
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:2034
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
virtual void close()=0
调用 NumericVector 的内部组装函数,确保值在处理器之间一致。
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package())
构建一个 NumericVector 对象。
Storage for DofConstraint right hand sides for a particular problem.
Definition: dof_map.h:110
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
一次访问多个组件。 values 将 *不会* 重新分配空间;它应该已经具有足够的空间。 默认实现对每个索引调用 operator() ,但某些实现可能在此处提供更快的方法。 ...
virtual numeric_index_type local_size() const =0
获取向量的本地大小,即 index_stop - index_start。
dof_id_type n_local_dofs() const
Definition: dof_map.h:669
ParallelType type() const
获取向量的类型。
virtual void set(const numeric_index_type i, const T value)=0
设置 v(i) = value 。 请注意,此方法的库实现是线程安全的, 例如,将在写入向量之前锁定 _numeric_vector_mutex 。
const std::vector< dof_id_type > & get_send_list() const
Definition: dof_map.h:511
uint8_t dof_id_type
Definition: id_types.h:67
virtual void localize(std::vector< T > &v_local) const =0
创建全局向量的副本并存储在本地向量 v_local 中。
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.

在文件 dof_map_constraints.C3113 行定义.

参考 _dof_constraints, _primal_constraint_values, libMesh::NumericVector< T >::build(), libMesh::NumericVector< T >::close(), libMesh::NumericVector< T >::closed(), libMesh::NumericVector< T >::get(), get_send_list(), local_index(), libMesh::NumericVector< T >::local_size(), libMesh::NumericVector< T >::localize(), n_constrained_dofs(), n_dofs(), n_local_dofs(), libMesh::NumericVector< T >::set(), libMesh::NumericVector< T >::size() , 以及 libMesh::NumericVector< T >::type().

3116 {
3117  parallel_object_only();
3118 
3119  if (!this->n_constrained_dofs())
3120  return;
3121 
3122  LOG_SCOPE("enforce_constraints_exactly()","DofMap");
3123 
3124  if (!v)
3125  v = system.solution.get();
3126 
3127  NumericVector<Number> * v_local = nullptr; // will be initialized below
3128  NumericVector<Number> * v_global = nullptr; // will be initialized below
3129  std::unique_ptr<NumericVector<Number>> v_built;
3130  if (v->type() == SERIAL)
3131  {
3132  v_built = NumericVector<Number>::build(this->comm());
3133  v_built->init(this->n_dofs(), this->n_local_dofs(), true, PARALLEL);
3134  v_built->close();
3135 
3136  for (dof_id_type i=v_built->first_local_index();
3137  i<v_built->last_local_index(); i++)
3138  v_built->set(i, (*v)(i));
3139  v_built->close();
3140  v_global = v_built.get();
3141 
3142  v_local = v;
3143  libmesh_assert (v_local->closed());
3144  }
3145  else if (v->type() == PARALLEL)
3146  {
3147  v_built = NumericVector<Number>::build(this->comm());
3148  v_built->init (v->size(), v->local_size(),
3149  this->get_send_list(), true,
3150  GHOSTED);
3151  v->localize(*v_built, this->get_send_list());
3152  v_built->close();
3153  v_local = v_built.get();
3154 
3155  v_global = v;
3156  }
3157  else if (v->type() == GHOSTED)
3158  {
3159  v_local = v;
3160  v_global = v;
3161  }
3162  else // unknown v->type()
3163  libmesh_error_msg("ERROR: Unsupported NumericVector type == " << Utility::enum_to_string(v->type()));
3164 
3165  // We should never hit these asserts because we should error-out in
3166  // else clause above. Just to be sure we don't try to use v_local
3167  // and v_global uninitialized...
3168  libmesh_assert(v_local);
3169  libmesh_assert(v_global);
3170  libmesh_assert_equal_to (this, &(system.get_dof_map()));
3171 
3172  for (const auto & [constrained_dof, constraint_row] : _dof_constraints)
3173  {
3174  if (!this->local_index(constrained_dof))
3175  continue;
3176 
3177  Number exact_value = 0;
3178  if (!homogeneous)
3179  {
3180  DofConstraintValueMap::const_iterator rhsit =
3181  _primal_constraint_values.find(constrained_dof);
3182  if (rhsit != _primal_constraint_values.end())
3183  exact_value = rhsit->second;
3184  }
3185  for (const auto & [dof, val] : constraint_row)
3186  exact_value += val * (*v_local)(dof);
3187 
3188  v_global->set(constrained_dof, exact_value);
3189  }
3190 
3191  // If the old vector was serial, we probably need to send our values
3192  // to other processors
3193  if (v->type() == SERIAL)
3194  {
3195 #ifndef NDEBUG
3196  v_global->close();
3197 #endif
3198  v_global->localize (*v);
3199  }
3200  v->close();
3201 }
virtual bool closed() const
检查向量是否已经关闭并准备好进行计算。
dof_id_type n_constrained_dofs() const
virtual numeric_index_type size() const =0
获取向量的大小。
提供了不同线性代数库的向量存储方案的统一接口。
Definition: dof_map.h:67
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:831
dof_id_type n_dofs() const
Definition: dof_map.h:659
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
virtual void close()=0
调用 NumericVector 的内部组装函数,确保值在处理器之间一致。
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package())
构建一个 NumericVector 对象。
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
一次访问多个组件。 values 将 *不会* 重新分配空间;它应该已经具有足够的空间。 默认实现对每个索引调用 operator() ,但某些实现可能在此处提供更快的方法。 ...
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
virtual numeric_index_type local_size() const =0
获取向量的本地大小,即 index_stop - index_start。
dof_id_type n_local_dofs() const
Definition: dof_map.h:669
ParallelType type() const
获取向量的类型。
virtual void set(const numeric_index_type i, const T value)=0
设置 v(i) = value 。 请注意,此方法的库实现是线程安全的, 例如,将在写入向量之前锁定 _numeric_vector_mutex 。
const std::vector< dof_id_type > & get_send_list() const
Definition: dof_map.h:511
uint8_t dof_id_type
Definition: id_types.h:67
virtual void localize(std::vector< T > &v_local) const =0
创建全局向量的副本并存储在本地向量 v_local 中。
void libMesh::DofMap::enforce_constraints_on_jacobian ( const NonlinearImplicitSystem &  system,
SparseMatrix< Number > *  jac 
) const
inline

在文件 dof_map_constraints.C3260 行定义.

参考 _dof_constraints, local_index(), n_constrained_dofs() , 以及 libMesh::SparseMatrix< T >::set().

3262 {
3263  parallel_object_only();
3264 
3265  if (!this->n_constrained_dofs())
3266  return;
3267 
3268  if (!jac)
3269  jac = system.matrix;
3270 
3271  libmesh_assert_equal_to (this, &(system.get_dof_map()));
3272 
3273  for (const auto & [constrained_dof, constraint_row] : _dof_constraints)
3274  {
3275  if (!this->local_index(constrained_dof))
3276  continue;
3277 
3278  for (const auto & j : constraint_row)
3279  jac->set(constrained_dof, j.first, -j.second);
3280  jac->set(constrained_dof, constrained_dof, 1);
3281  }
3282 }
dof_id_type n_constrained_dofs() const
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:831
virtual void set(const numeric_index_type i, const numeric_index_type j, const T value)=0
设置元素 (i,j) 为 value .
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
void libMesh::DofMap::enforce_constraints_on_residual ( const NonlinearImplicitSystem &  system,
NumericVector< Number > *  rhs,
NumericVector< Number > const *  solution,
bool  homogeneous = true 
) const
inline

在文件 dof_map_constraints.C3203 行定义.

参考 _dof_constraints, _primal_constraint_values, libMesh::NumericVector< T >::build(), libMesh::NumericVector< T >::get(), get_send_list(), local_index(), libMesh::NumericVector< T >::local_size(), libMesh::NumericVector< T >::localize(), n_constrained_dofs(), libMesh::NumericVector< T >::set(), libMesh::NumericVector< T >::size() , 以及 libMesh::NumericVector< T >::type().

3207 {
3208  parallel_object_only();
3209 
3210  if (!this->n_constrained_dofs())
3211  return;
3212 
3213  if (!rhs)
3214  rhs = system.rhs;
3215  if (!solution)
3216  solution = system.solution.get();
3217 
3218  NumericVector<Number> const * solution_local = nullptr; // will be initialized below
3219  std::unique_ptr<NumericVector<Number>> solution_built;
3220  if (solution->type() == SERIAL || solution->type() == GHOSTED)
3221  solution_local = solution;
3222  else if (solution->type() == PARALLEL)
3223  {
3224  solution_built = NumericVector<Number>::build(this->comm());
3225  solution_built->init (solution->size(), solution->local_size(),
3226  this->get_send_list(), true, GHOSTED);
3227  solution->localize(*solution_built, this->get_send_list());
3228  solution_built->close();
3229  solution_local = solution_built.get();
3230  }
3231  else // unknown solution->type()
3232  libmesh_error_msg("ERROR: Unsupported NumericVector type == " << Utility::enum_to_string(solution->type()));
3233 
3234  // We should never hit these asserts because we should error-out in
3235  // else clause above. Just to be sure we don't try to use solution_local
3236  libmesh_assert(solution_local);
3237  libmesh_assert_equal_to (this, &(system.get_dof_map()));
3238 
3239  for (const auto & [constrained_dof, constraint_row] : _dof_constraints)
3240  {
3241  if (!this->local_index(constrained_dof))
3242  continue;
3243 
3244  Number exact_value = 0;
3245  for (const auto & [dof, val] : constraint_row)
3246  exact_value -= val * (*solution_local)(dof);
3247  exact_value += (*solution_local)(constrained_dof);
3248  if (!homogeneous)
3249  {
3250  DofConstraintValueMap::const_iterator rhsit =
3251  _primal_constraint_values.find(constrained_dof);
3252  if (rhsit != _primal_constraint_values.end())
3253  exact_value += rhsit->second;
3254  }
3255 
3256  rhs->set(constrained_dof, exact_value);
3257  }
3258 }
dof_id_type n_constrained_dofs() const
virtual numeric_index_type size() const =0
获取向量的大小。
提供了不同线性代数库的向量存储方案的统一接口。
Definition: dof_map.h:67
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:831
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package())
构建一个 NumericVector 对象。
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
一次访问多个组件。 values 将 *不会* 重新分配空间;它应该已经具有足够的空间。 默认实现对每个索引调用 operator() ,但某些实现可能在此处提供更快的方法。 ...
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
virtual numeric_index_type local_size() const =0
获取向量的本地大小,即 index_stop - index_start。
ParallelType type() const
获取向量的类型。
virtual void set(const numeric_index_type i, const T value)=0
设置 v(i) = value 。 请注意,此方法的库实现是线程安全的, 例如,将在写入向量之前锁定 _numeric_vector_mutex 。
const std::vector< dof_id_type > & get_send_list() const
Definition: dof_map.h:511
virtual void localize(std::vector< T > &v_local) const =0
创建全局向量的副本并存储在本地向量 v_local 中。
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]] $

注解
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.

在文件 dof_map.C1910 行定义.

参考 build_constraint_matrix_and_vector(), libMesh::DenseVectorBase< T >::el(), libMesh::NumericVector< T >::first_local_index(), is_constrained_dof(), libMesh::NumericVector< T >::last_local_index(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVectorBase< T >::size(), libMesh::NumericVector< T >::size() , 以及 libMesh::DenseVectorBase< T >::zero().

1913 {
1914  const unsigned int n_original_dofs = dof_indices_in.size();
1915 
1916 #ifdef LIBMESH_ENABLE_AMR
1917 
1918  // Trivial mapping
1919  libmesh_assert_equal_to (dof_indices_in.size(), Ue.size());
1920  bool has_constrained_dofs = false;
1921 
1922  for (unsigned int il=0; il != n_original_dofs; ++il)
1923  {
1924  const dof_id_type ig = dof_indices_in[il];
1925 
1926  if (this->is_constrained_dof (ig)) has_constrained_dofs = true;
1927 
1928  libmesh_assert_less (ig, Ug.size());
1929 
1930  Ue.el(il) = Ug(ig);
1931  }
1932 
1933  // If the element has any constrained DOFs then we need
1934  // to account for them in the mapping. This will handle
1935  // the case that the input vector is not constrained.
1936  if (has_constrained_dofs)
1937  {
1938  // Copy the input DOF indices.
1939  std::vector<dof_id_type> constrained_dof_indices(dof_indices_in);
1940 
1941  DenseMatrix<Number> C;
1942  DenseVector<Number> H;
1943 
1944  this->build_constraint_matrix_and_vector (C, H, constrained_dof_indices);
1945 
1946  libmesh_assert_equal_to (dof_indices_in.size(), C.m());
1947  libmesh_assert_equal_to (constrained_dof_indices.size(), C.n());
1948 
1949  // zero-out Ue
1950  Ue.zero();
1951 
1952  // compute Ue = C Ug, with proper mapping.
1953  for (unsigned int i=0; i != n_original_dofs; i++)
1954  {
1955  Ue.el(i) = H(i);
1956 
1957  const unsigned int n_constrained =
1958  cast_int<unsigned int>(constrained_dof_indices.size());
1959  for (unsigned int j=0; j<n_constrained; j++)
1960  {
1961  const dof_id_type jg = constrained_dof_indices[j];
1962 
1963  // If Ug is a serial or ghosted vector, then this assert is
1964  // overzealous. If Ug is a parallel vector, then this assert
1965  // is redundant.
1966  // libmesh_assert ((jg >= Ug.first_local_index()) &&
1967  // (jg < Ug.last_local_index()));
1968 
1969  Ue.el(i) += C(i,j)*Ug(jg);
1970  }
1971  }
1972  }
1973 
1974 #else
1975 
1976  // Trivial mapping
1977 
1978  libmesh_assert_equal_to (n_original_dofs, Ue.size());
1979 
1980  for (unsigned int il=0; il<n_original_dofs; il++)
1981  {
1982  const dof_id_type ig = dof_indices_in[il];
1983 
1984  libmesh_assert ((ig >= Ug.first_local_index()) && (ig < Ug.last_local_index()));
1985 
1986  Ue.el(il) = Ug(ig);
1987  }
1988 
1989 #endif
1990 }
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 ...
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
uint8_t dof_id_type
Definition: id_types.h:67
void libMesh::DofMap::find_connected_dof_objects ( std::vector< const DofObject * > &  objs) const
private

Finds all the DofObjects associated with the set in objs.

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

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

Finds all the DOFS associated with the element DOFs elem_dofs.

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

在文件 dof_map.C2852 行定义.

参考 _dof_constraints , 以及 is_constrained_dof().

参考自 libMesh::SparsityPattern::Build::sorted_connected_dofs().

2853 {
2854  typedef std::set<dof_id_type> RCSet;
2855 
2856  // First insert the DOFS we already depend on into the set.
2857  RCSet dof_set (elem_dofs.begin(), elem_dofs.end());
2858 
2859  bool done = true;
2860 
2861  // Next insert any dofs those might be constrained in terms
2862  // of. Note that in this case we may not be done: Those may
2863  // in turn depend on others. So, we need to repeat this process
2864  // in that case until the system depends only on unconstrained
2865  // degrees of freedom.
2866  for (const auto & dof : elem_dofs)
2867  if (this->is_constrained_dof(dof))
2868  {
2869  // If the DOF is constrained
2870  DofConstraints::const_iterator
2871  pos = _dof_constraints.find(dof);
2872 
2873  libmesh_assert (pos != _dof_constraints.end());
2874 
2875  const DofConstraintRow & constraint_row = pos->second;
2876 
2877  // adaptive p refinement currently gives us lots of empty constraint
2878  // rows - we should optimize those DoFs away in the future. [RHS]
2879  //libmesh_assert (!constraint_row.empty());
2880 
2881  // Add the DOFs this dof is constrained in terms of.
2882  // note that these dofs might also be constrained, so
2883  // we will need to call this function recursively.
2884  for (const auto & pr : constraint_row)
2885  if (!dof_set.count (pr.first))
2886  {
2887  dof_set.insert (pr.first);
2888  done = false;
2889  }
2890  }
2891 
2892 
2893  // If not done then we need to do more work
2894  // (obviously :-) )!
2895  if (!done)
2896  {
2897  // Fill the vector with the contents of the set
2898  elem_dofs.clear();
2899  elem_dofs.insert (elem_dofs.end(),
2900  dof_set.begin(), dof_set.end());
2901 
2902 
2903  // May need to do this recursively. It is possible
2904  // that we just replaced a constrained DOF with another
2905  // constrained DOF.
2906  this->find_connected_dofs (elem_dofs);
2907 
2908  } // end if (!done)
2909 }
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
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:90
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:2852
dof_id_type libMesh::DofMap::first_dof ( const processor_id_type  proc) const
inline
返回
The first dof index that is local to partition proc.

在文件 dof_map.h684 行定义.

参考 _first_df.

参考自 libMesh::SparsityPattern::Build::handle_vi_vj(), libMesh::SparsityPattern::Build::join(), libMesh::SparsityPattern::Build::operator()() , 以及 libMesh::SparsityPattern::Build::parallel_sync().

685  { libmesh_assert_less (proc, _first_df.size()); return _first_df[proc]; }
std::vector< dof_id_type > _first_df
First DOF index on processor p.
Definition: dof_map.h:1876
dof_id_type libMesh::DofMap::first_dof ( ) const
inline

在文件 dof_map.h687 行定义.

参考自 distribute_dofs(), local_index(), n_local_constrained_dofs() , 以及 process_mesh_constraint_rows().

688  { return this->first_dof(this->processor_id()); }
dof_id_type first_dof() const
Definition: dof_map.h:687
dof_id_type libMesh::DofMap::first_old_dof ( const processor_id_type  proc) const
inline
返回
The first old dof index that is local to partition proc.

在文件 dof_map.h694 行定义.

参考 _first_old_df.

695  { libmesh_assert_less (proc, _first_old_df.size()); return _first_old_df[proc]; }
std::vector< dof_id_type > _first_old_df
First old DOF index on processor p.
Definition: dof_map.h:2006
dof_id_type libMesh::DofMap::first_old_dof ( ) const
inline

在文件 dof_map.h697 行定义.

698  { return this->first_old_dof(this->processor_id()); }
dof_id_type first_old_dof() const
Definition: dof_map.h:697
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.

在文件 dof_map_constraints.C5055 行定义.

参考 _adjoint_constraint_values, _dof_constraints, _end_df, _primal_constraint_values, libMesh::DofObject::invalid_id, local_index() , 以及 libMesh::Real.

参考自 allgather_recursive_constraints() , 以及 scatter_constraints().

5058 {
5059  typedef std::set<dof_id_type> DoF_RCSet;
5060 
5061  // If we have heterogeneous adjoint constraints we need to
5062  // communicate those too.
5063  const unsigned int max_qoi_num =
5064  _adjoint_constraint_values.empty() ?
5065  0 : _adjoint_constraint_values.rbegin()->first+1;
5066 
5067  // We have to keep recursing while the unexpanded set is
5068  // nonempty on *any* processor
5069  bool unexpanded_set_nonempty = !unexpanded_dofs.empty();
5070  this->comm().max(unexpanded_set_nonempty);
5071 
5072  while (unexpanded_set_nonempty)
5073  {
5074  // Let's make sure we don't lose sync in this loop.
5075  parallel_object_only();
5076 
5077  // Request sets
5078  DoF_RCSet dof_request_set;
5079 
5080  // Request sets to send to each processor
5081  std::map<processor_id_type, std::vector<dof_id_type>>
5082  requested_dof_ids;
5083 
5084  // And the sizes of each
5085  std::map<processor_id_type, dof_id_type>
5086  dof_ids_on_proc;
5087 
5088  // Fill (and thereby sort and uniq!) the main request sets
5089  for (const auto & unexpanded_dof : unexpanded_dofs)
5090  {
5091  DofConstraints::const_iterator
5092  pos = _dof_constraints.find(unexpanded_dof);
5093 
5094  // If we were asked for a DoF and we don't already have a
5095  // constraint for it, then we need to check for one.
5096  if (pos == _dof_constraints.end())
5097  {
5098  if (!this->local_index(unexpanded_dof) &&
5099  !_dof_constraints.count(unexpanded_dof) )
5100  dof_request_set.insert(unexpanded_dof);
5101  }
5102  // If we were asked for a DoF and we already have a
5103  // constraint for it, then we need to check if the
5104  // constraint is recursive.
5105  else
5106  {
5107  const DofConstraintRow & row = pos->second;
5108  for (const auto & j : row)
5109  {
5110  const dof_id_type constraining_dof = j.first;
5111 
5112  // If it's non-local and we haven't already got a
5113  // constraint for it, we might need to ask for one
5114  if (!this->local_index(constraining_dof) &&
5115  !_dof_constraints.count(constraining_dof))
5116  dof_request_set.insert(constraining_dof);
5117  }
5118  }
5119  }
5120 
5121  // Clear the unexpanded constraint set; we're about to expand it
5122  unexpanded_dofs.clear();
5123 
5124  // Count requests by processor
5125  processor_id_type proc_id = 0;
5126  for (const auto & i : dof_request_set)
5127  {
5128  while (i >= _end_df[proc_id])
5129  proc_id++;
5130  dof_ids_on_proc[proc_id]++;
5131  }
5132 
5133  for (auto & pair : dof_ids_on_proc)
5134  {
5135  requested_dof_ids[pair.first].reserve(pair.second);
5136  }
5137 
5138  // Prepare each processor's request set
5139  proc_id = 0;
5140  for (const auto & i : dof_request_set)
5141  {
5142  while (i >= _end_df[proc_id])
5143  proc_id++;
5144  requested_dof_ids[proc_id].push_back(i);
5145  }
5146 
5147  typedef std::vector<std::pair<dof_id_type, Real>> row_datum;
5148 
5149  typedef std::vector<Number> rhss_datum;
5150 
5151  auto row_gather_functor =
5152  [this]
5154  const std::vector<dof_id_type> & ids,
5155  std::vector<row_datum> & data)
5156  {
5157  // Fill those requests
5158  const std::size_t query_size = ids.size();
5159 
5160  data.resize(query_size);
5161  for (std::size_t i=0; i != query_size; ++i)
5162  {
5163  dof_id_type constrained = ids[i];
5164  if (_dof_constraints.count(constrained))
5165  {
5166  DofConstraintRow & row = _dof_constraints[constrained];
5167  std::size_t row_size = row.size();
5168  data[i].reserve(row_size);
5169  for (const auto & j : row)
5170  {
5171  data[i].push_back(j);
5172 
5173  // We should never have an invalid constraining
5174  // dof id
5175  libmesh_assert(j.first != DofObject::invalid_id);
5176 
5177  // We should never have a 0 constraint
5178  // coefficient; that's implicit via sparse
5179  // constraint storage
5180  //
5181  // But we can't easily control how users add
5182  // constraints, so we can't safely assert that
5183  // we're being efficient here.
5184  //
5185  // libmesh_assert(j.second);
5186  }
5187  }
5188  else
5189  {
5190  // We have to distinguish "constraint with no
5191  // constraining dofs" (e.g. due to Dirichlet
5192  // constraint equations) from "no constraint".
5193  // We'll use invalid_id for the latter.
5194  data[i].emplace_back(DofObject::invalid_id, Real(0));
5195  }
5196  }
5197  };
5198 
5199  auto rhss_gather_functor =
5200  [this,
5201  max_qoi_num]
5203  const std::vector<dof_id_type> & ids,
5204  std::vector<rhss_datum> & data)
5205  {
5206  // Fill those requests
5207  const std::size_t query_size = ids.size();
5208 
5209  data.resize(query_size);
5210  for (std::size_t i=0; i != query_size; ++i)
5211  {
5212  dof_id_type constrained = ids[i];
5213  data[i].clear();
5214  if (_dof_constraints.count(constrained))
5215  {
5216  DofConstraintValueMap::const_iterator rhsit =
5217  _primal_constraint_values.find(constrained);
5218  data[i].push_back
5219  ((rhsit == _primal_constraint_values.end()) ?
5220  0 : rhsit->second);
5221 
5222  for (unsigned int q = 0; q != max_qoi_num; ++q)
5223  {
5224  AdjointDofConstraintValues::const_iterator adjoint_map_it =
5226 
5227  if (adjoint_map_it == _adjoint_constraint_values.end())
5228  {
5229  data[i].push_back(0);
5230  continue;
5231  }
5232 
5233  const DofConstraintValueMap & constraint_map =
5234  adjoint_map_it->second;
5235 
5236  DofConstraintValueMap::const_iterator adj_rhsit =
5237  constraint_map.find(constrained);
5238  data[i].push_back
5239  ((adj_rhsit == constraint_map.end()) ?
5240  0 : adj_rhsit->second);
5241  }
5242  }
5243  }
5244  };
5245 
5246  auto row_action_functor =
5247  [this,
5248  & unexpanded_dofs]
5250  const std::vector<dof_id_type> & ids,
5251  const std::vector<row_datum> & data)
5252  {
5253  // Add any new constraint rows we've found
5254  const std::size_t query_size = ids.size();
5255 
5256  for (std::size_t i=0; i != query_size; ++i)
5257  {
5258  const dof_id_type constrained = ids[i];
5259 
5260  // An empty row is an constraint with an empty row; for
5261  // no constraint we use a "no row" placeholder
5262  if (data[i].empty())
5263  {
5264  DofConstraintRow & row = _dof_constraints[constrained];
5265  row.clear();
5266  }
5267  else if (data[i][0].first != DofObject::invalid_id)
5268  {
5269  DofConstraintRow & row = _dof_constraints[constrained];
5270  row.clear();
5271  for (auto & pair : data[i])
5272  {
5273  libmesh_assert_less(pair.first, this->n_dofs());
5274  row[pair.first] = pair.second;
5275  }
5276 
5277  // And prepare to check for more recursive constraints
5278  unexpanded_dofs.insert(constrained);
5279  }
5280  }
5281  };
5282 
5283  auto rhss_action_functor =
5284  [this,
5285  max_qoi_num]
5287  const std::vector<dof_id_type> & ids,
5288  const std::vector<rhss_datum> & data)
5289  {
5290  // Add rhs data for any new constraint rows we've found
5291  const std::size_t query_size = ids.size();
5292 
5293  for (std::size_t i=0; i != query_size; ++i)
5294  {
5295  if (!data[i].empty())
5296  {
5297  dof_id_type constrained = ids[i];
5298  if (data[i][0] != Number(0))
5299  _primal_constraint_values[constrained] = data[i][0];
5300  else
5301  _primal_constraint_values.erase(constrained);
5302 
5303  for (unsigned int q = 0; q != max_qoi_num; ++q)
5304  {
5305  AdjointDofConstraintValues::iterator adjoint_map_it =
5307 
5308  if ((adjoint_map_it == _adjoint_constraint_values.end()) &&
5309  data[i][q+1] == Number(0))
5310  continue;
5311 
5312  if (adjoint_map_it == _adjoint_constraint_values.end())
5313  adjoint_map_it = _adjoint_constraint_values.emplace
5314  (q, DofConstraintValueMap()).first;
5315 
5316  DofConstraintValueMap & constraint_map =
5317  adjoint_map_it->second;
5318 
5319  if (data[i][q+1] != Number(0))
5320  constraint_map[constrained] =
5321  data[i][q+1];
5322  else
5323  constraint_map.erase(constrained);
5324  }
5325  }
5326  }
5327 
5328  };
5329 
5330  // Now request constraint rows from other processors
5331  row_datum * row_ex = nullptr;
5332  Parallel::pull_parallel_vector_data
5333  (this->comm(), requested_dof_ids, row_gather_functor,
5334  row_action_functor, row_ex);
5335 
5336  // And request constraint right hand sides from other procesors
5337  rhss_datum * rhs_ex = nullptr;
5338  Parallel::pull_parallel_vector_data
5339  (this->comm(), requested_dof_ids, rhss_gather_functor,
5340  rhss_action_functor, rhs_ex);
5341 
5342  // We have to keep recursing while the unexpanded set is
5343  // nonempty on *any* processor
5344  unexpanded_set_nonempty = !unexpanded_dofs.empty();
5345  this->comm().max(unexpanded_set_nonempty);
5346  }
5347 }
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:831
uint8_t processor_id_type
Definition: id_types.h:104
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:2034
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:477
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
Storage for DofConstraint right hand sides for a particular problem.
Definition: dof_map.h:110
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
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:90
std::vector< dof_id_type > _end_df
Last DOF index (plus 1) on processor p.
Definition: dof_map.h:1881
uint8_t dof_id_type
Definition: id_types.h:67
const DirichletBoundaries * libMesh::DofMap::get_adjoint_dirichlet_boundaries ( unsigned int  q) const

在文件 dof_map_constraints.C5480 行定义.

参考 _adjoint_dirichlet_boundaries.

5481 {
5482  libmesh_assert_greater(_adjoint_dirichlet_boundaries.size(),q);
5483  return _adjoint_dirichlet_boundaries[q].get();
5484 }
std::vector< std::unique_ptr< DirichletBoundaries > > _adjoint_dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition: dof_map.h:2064
DirichletBoundaries * libMesh::DofMap::get_adjoint_dirichlet_boundaries ( unsigned int  q)

在文件 dof_map_constraints.C5488 行定义.

参考 _adjoint_dirichlet_boundaries.

5489 {
5490  unsigned int old_size = cast_int<unsigned int>
5492  for (unsigned int i = old_size; i <= q; ++i)
5493  _adjoint_dirichlet_boundaries.push_back(std::make_unique<DirichletBoundaries>());
5494 
5495  return _adjoint_dirichlet_boundaries[q].get();
5496 }
std::vector< std::unique_ptr< DirichletBoundaries > > _adjoint_dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition: dof_map.h:2064
const DirichletBoundaries* libMesh::DofMap::get_dirichlet_boundaries ( ) const
inline

在文件 dof_map.h1482 行定义.

参考 _dirichlet_boundaries.

1483  {
1484  return _dirichlet_boundaries.get();
1485  }
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition: dof_map.h:2058
DirichletBoundaries* libMesh::DofMap::get_dirichlet_boundaries ( )
inline

在文件 dof_map.h1487 行定义.

参考 _dirichlet_boundaries.

1488  {
1489  return _dirichlet_boundaries.get();
1490  }
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition: dof_map.h:2058
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.

在文件 dof_map.h1023 行定义.

参考 _dof_constraints.

1023 { return _dof_constraints; }
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
std::string libMesh::ReferenceCounter::get_info ( )
staticinherited

Gets a string containing the reference information.

在文件 reference_counter.C47 行定义.

参考 libMesh::ReferenceCounter::_counts.

参考自 libMesh::ReferenceCounter::print_info().

48 {
49 #if defined(LIBMESH_ENABLE_REFERENCE_COUNTING) && defined(DEBUG)
50 
51  std::ostringstream oss;
52 
53  oss << '\n'
54  << " ---------------------------------------------------------------------------- \n"
55  << "| Reference count information |\n"
56  << " ---------------------------------------------------------------------------- \n";
57 
58  for (const auto & [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 libMesh::DofMap::get_info ( ) const

Gets summary info about the sparsity bandwidth and constraints.

在文件 dof_map.C2922 行定义.

参考 _dof_constraints, _matrices, _node_constraints, _primal_constraint_values, _sp , 以及 local_index().

参考自 print_info().

2923 {
2924  std::ostringstream os;
2925 
2926  // If we didn't calculate the exact sparsity pattern, the threaded
2927  // sparsity pattern assembly may have just given us an upper bound
2928  // on sparsity.
2929  const char * may_equal = " <= ";
2930 
2931  // If we calculated the exact sparsity pattern, then we can report
2932  // exact bandwidth figures:
2933  for (const auto & mat : _matrices)
2934  if (mat->need_full_sparsity_pattern())
2935  may_equal = " = ";
2936 
2937  dof_id_type max_n_nz = 0, max_n_oz = 0;
2938  long double avg_n_nz = 0, avg_n_oz = 0;
2939 
2940  if (_sp)
2941  {
2942  for (const auto & val : _sp->get_n_nz())
2943  {
2944  max_n_nz = std::max(max_n_nz, val);
2945  avg_n_nz += val;
2946  }
2947 
2948  std::size_t n_nz_size = _sp->get_n_nz().size();
2949 
2950  this->comm().max(max_n_nz);
2951  this->comm().sum(avg_n_nz);
2952  this->comm().sum(n_nz_size);
2953 
2954  avg_n_nz /= std::max(n_nz_size,std::size_t(1));
2955 
2956  for (const auto & val : _sp->get_n_oz())
2957  {
2958  max_n_oz = std::max(max_n_oz, val);
2959  avg_n_oz += val;
2960  }
2961 
2962  std::size_t n_oz_size = _sp->get_n_oz().size();
2963 
2964  this->comm().max(max_n_oz);
2965  this->comm().sum(avg_n_oz);
2966  this->comm().sum(n_oz_size);
2967 
2968  avg_n_oz /= std::max(n_oz_size,std::size_t(1));
2969  }
2970 
2971  os << " DofMap Sparsity\n Average On-Processor Bandwidth"
2972  << may_equal << avg_n_nz << '\n';
2973 
2974  os << " Average Off-Processor Bandwidth"
2975  << may_equal << avg_n_oz << '\n';
2976 
2977  os << " Maximum On-Processor Bandwidth"
2978  << may_equal << max_n_nz << '\n';
2979 
2980  os << " Maximum Off-Processor Bandwidth"
2981  << may_equal << max_n_oz << std::endl;
2982 
2983 #ifdef LIBMESH_ENABLE_CONSTRAINTS
2984 
2985  std::size_t n_constraints = 0, max_constraint_length = 0,
2986  n_rhss = 0;
2987  long double avg_constraint_length = 0.;
2988 
2989  for (const auto & [constrained_dof, row] : _dof_constraints)
2990  {
2991  // Only count local constraints, then sum later
2992  if (!this->local_index(constrained_dof))
2993  continue;
2994 
2995  std::size_t rowsize = row.size();
2996 
2997  max_constraint_length = std::max(max_constraint_length,
2998  rowsize);
2999  avg_constraint_length += rowsize;
3000  n_constraints++;
3001 
3002  if (_primal_constraint_values.count(constrained_dof))
3003  n_rhss++;
3004  }
3005 
3006  this->comm().sum(n_constraints);
3007  this->comm().sum(n_rhss);
3008  this->comm().sum(avg_constraint_length);
3009  this->comm().max(max_constraint_length);
3010 
3011  os << " DofMap Constraints\n Number of DoF Constraints = "
3012  << n_constraints;
3013  if (n_rhss)
3014  os << '\n'
3015  << " Number of Heterogenous Constraints= " << n_rhss;
3016  if (n_constraints)
3017  {
3018  avg_constraint_length /= n_constraints;
3019 
3020  os << '\n'
3021  << " Average DoF Constraint Length= " << avg_constraint_length;
3022  }
3023 
3024 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3025  std::size_t n_node_constraints = 0, max_node_constraint_length = 0,
3026  n_node_rhss = 0;
3027  long double avg_node_constraint_length = 0.;
3028 
3029  for (const auto & [node, pr] : _node_constraints)
3030  {
3031  // Only count local constraints, then sum later
3032  if (node->processor_id() != this->processor_id())
3033  continue;
3034 
3035  const NodeConstraintRow & row = pr.first;
3036  std::size_t rowsize = row.size();
3037 
3038  max_node_constraint_length = std::max(max_node_constraint_length,
3039  rowsize);
3040  avg_node_constraint_length += rowsize;
3041  n_node_constraints++;
3042 
3043  if (pr.second != Point(0))
3044  n_node_rhss++;
3045  }
3046 
3047  this->comm().sum(n_node_constraints);
3048  this->comm().sum(n_node_rhss);
3049  this->comm().sum(avg_node_constraint_length);
3050  this->comm().max(max_node_constraint_length);
3051 
3052  os << "\n Number of Node Constraints = " << n_node_constraints;
3053  if (n_node_rhss)
3054  os << '\n'
3055  << " Number of Heterogenous Node Constraints= " << n_node_rhss;
3056  if (n_node_constraints)
3057  {
3058  avg_node_constraint_length /= n_node_constraints;
3059  os << "\n Maximum Node Constraint Length= " << max_node_constraint_length
3060  << '\n'
3061  << " Average Node Constraint Length= " << avg_node_constraint_length;
3062  }
3063 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
3064 
3065  os << std::endl;
3066 
3067 #endif // LIBMESH_ENABLE_CONSTRAINTS
3068 
3069  return os.str();
3070 }
std::unique_ptr< SparsityPattern::Build > _sp
The sparsity pattern of the global matrix.
Definition: dof_map.h:1983
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:831
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
std::vector< SparseMatrix< Number > * > _matrices
Additional matrices handled by this object.
Definition: dof_map.h:1871
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
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:138
uint8_t dof_id_type
Definition: id_types.h:67
NodeConstraints _node_constraints
Data structure containing DofObject constraints.
Definition: dof_map.h:2041
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.

在文件 dof_map_constraints.C2288 行定义.

参考 _adjoint_constraint_values, _adjoint_dirichlet_boundaries, _dof_constraints, _node_constraints, _primal_constraint_values , 以及 local_index().

参考自 print_dof_constraints().

2289 {
2290  std::ostringstream os;
2291 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2292  if (print_nonlocal)
2293  os << "All ";
2294  else
2295  os << "Local ";
2296 
2297  os << "Node Constraints:"
2298  << std::endl;
2299 
2300  for (const auto & [node, pr] : _node_constraints)
2301  {
2302  // Skip non-local nodes if requested
2303  if (!print_nonlocal &&
2304  node->processor_id() != this->processor_id())
2305  continue;
2306 
2307  const NodeConstraintRow & row = pr.first;
2308  const Point & offset = pr.second;
2309 
2310  os << "Constraints for Node id " << node->id()
2311  << ": \t";
2312 
2313  for (const auto & [cnode, val] : row)
2314  os << " (" << cnode->id() << "," << val << ")\t";
2315 
2316  os << "rhs: " << offset;
2317 
2318  os << std::endl;
2319  }
2320 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
2321 
2322  if (print_nonlocal)
2323  os << "All ";
2324  else
2325  os << "Local ";
2326 
2327  os << "DoF Constraints:"
2328  << std::endl;
2329 
2330  for (const auto & [i, row] : _dof_constraints)
2331  {
2332  // Skip non-local dofs if requested
2333  if (!print_nonlocal && !this->local_index(i))
2334  continue;
2335 
2336  DofConstraintValueMap::const_iterator rhsit =
2337  _primal_constraint_values.find(i);
2338  const Number rhs = (rhsit == _primal_constraint_values.end()) ?
2339  0 : rhsit->second;
2340 
2341  os << "Constraints for DoF " << i
2342  << ": \t";
2343 
2344  for (const auto & item : row)
2345  os << " (" << item.first << "," << item.second << ")\t";
2346 
2347  os << "rhs: " << rhs;
2348  os << std::endl;
2349  }
2350 
2351  for (unsigned int qoi_index = 0,
2352  n_qois = cast_int<unsigned int>(_adjoint_dirichlet_boundaries.size());
2353  qoi_index != n_qois; ++qoi_index)
2354  {
2355  os << "Adjoint " << qoi_index << " DoF rhs values:"
2356  << std::endl;
2357 
2358  AdjointDofConstraintValues::const_iterator adjoint_map_it =
2359  _adjoint_constraint_values.find(qoi_index);
2360 
2361  if (adjoint_map_it != _adjoint_constraint_values.end())
2362  for (const auto [i, rhs] : adjoint_map_it->second)
2363  {
2364  // Skip non-local dofs if requested
2365  if (!print_nonlocal && !this->local_index(i))
2366  continue;
2367 
2368  os << "RHS for DoF " << i
2369  << ": " << rhs;
2370 
2371  os << std::endl;
2372  }
2373  }
2374 
2375  return os.str();
2376 }
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:831
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:2034
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
std::vector< std::unique_ptr< DirichletBoundaries > > _adjoint_dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition: dof_map.h:2064
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
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:138
NodeConstraints _node_constraints
Data structure containing DofObject constraints.
Definition: dof_map.h:2041
const std::vector<dof_id_type>& libMesh::DofMap::get_n_nz ( ) const
inline
返回
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.

在文件 dof_map.h520 行定义.

参考 _sp.

521  {
522  libmesh_assert(_sp);
523  return _sp->get_n_nz();
524  }
std::unique_ptr< SparsityPattern::Build > _sp
The sparsity pattern of the global matrix.
Definition: dof_map.h:1983
const std::vector<dof_id_type>& libMesh::DofMap::get_n_oz ( ) const
inline
返回
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.

在文件 dof_map.h533 行定义.

参考 _sp.

534  {
535  libmesh_assert(_sp);
536  return _sp->get_n_oz();
537  }
std::unique_ptr< SparsityPattern::Build > _sp
The sparsity pattern of the global matrix.
Definition: dof_map.h:1983
PeriodicBoundaries* libMesh::DofMap::get_periodic_boundaries ( )
inline

在文件 dof_map.h1429 行定义.

参考 _periodic_boundaries.

1430  {
1431  return _periodic_boundaries.get();
1432  }
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Data structure containing periodic boundaries.
Definition: dof_map.h:2050
const PeriodicBoundaries* libMesh::DofMap::get_periodic_boundaries ( ) const
inline

在文件 dof_map.h1434 行定义.

参考 _periodic_boundaries.

1435  {
1436  return _periodic_boundaries.get();
1437  }
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Data structure containing periodic boundaries.
Definition: dof_map.h:2050
DofConstraintValueMap & libMesh::DofMap::get_primal_constraint_values ( )
inline
返回
A reference to the set of right-hand-side values in primal constraint equations

在文件 dof_map.h2224 行定义.

参考 _primal_constraint_values.

2225 {
2227 }
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
const std::vector<dof_id_type>& libMesh::DofMap::get_send_list ( ) const
inline
返回
A constant reference to the _send_list for this processor.

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

在文件 dof_map.h511 行定义.

参考 _send_list.

参考自 enforce_adjoint_constraints_exactly(), enforce_constraints_exactly() , 以及 enforce_constraints_on_residual().

511 { return _send_list; }
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:1893
const SparsityPattern::Build* libMesh::DofMap::get_sparsity_pattern ( ) const
inline
返回
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.

在文件 dof_map.h548 行定义.

参考 _sp.

参考自 libMesh::SparseMatrix< T >::attach_dof_map().

549  {
550  return _sp.get();
551  }
std::unique_ptr< SparsityPattern::Build > _sp
The sparsity pattern of the global matrix.
Definition: dof_map.h:1983
bool libMesh::DofMap::has_adjoint_dirichlet_boundaries ( unsigned int  q) const

在文件 dof_map_constraints.C5470 行定义.

参考 _adjoint_dirichlet_boundaries.

5471 {
5472  if (_adjoint_dirichlet_boundaries.size() > q)
5473  return true;
5474 
5475  return false;
5476 }
std::vector< std::unique_ptr< DirichletBoundaries > > _adjoint_dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition: dof_map.h:2064
bool libMesh::DofMap::has_blocked_representation ( ) const
inline
返回
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.

在文件 dof_map.h634 行定义.

参考 n_variable_groups() , 以及 n_variables().

参考自 block_size().

635  {
636  return ((this->n_variable_groups() == 1) && (this->n_variables() > 1));
637  }
unsigned int n_variable_groups() const
Definition: dof_map.h:613
unsigned int n_variables() const
Definition: dof_map.h:621
Number libMesh::DofMap::has_heterogeneous_adjoint_constraint ( const unsigned int  qoi_num,
const dof_id_type  dof 
) const
inline
返回
The heterogeneous constraint value if the degree of freedom dof has a heterogeneous constraint for adjoint solution qoi_num, zero otherwise.

在文件 dof_map.h2203 行定义.

参考 _adjoint_constraint_values.

参考自 has_heterogenous_adjoint_constraint().

2205 {
2206  AdjointDofConstraintValues::const_iterator it =
2207  _adjoint_constraint_values.find(qoi_num);
2208  if (it != _adjoint_constraint_values.end())
2209  {
2210  DofConstraintValueMap::const_iterator rhsit =
2211  it->second.find(dof);
2212  if (rhsit == it->second.end())
2213  return 0;
2214  else
2215  return rhsit->second;
2216  }
2217 
2218  return 0;
2219 }
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:2034
bool libMesh::DofMap::has_heterogeneous_adjoint_constraints ( const unsigned int  qoi_num) const
inline
返回
true if the system has any heterogeneous constraints for adjoint solution qoi_num, false otherwise.

在文件 dof_map.h2189 行定义.

参考 _adjoint_constraint_values.

参考自 has_heterogenous_adjoint_constraints().

2190 {
2191  AdjointDofConstraintValues::const_iterator it =
2192  _adjoint_constraint_values.find(qoi_num);
2193  if (it == _adjoint_constraint_values.end())
2194  return false;
2195  if (it->second.empty())
2196  return false;
2197 
2198  return true;
2199 }
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:2034
Number libMesh::DofMap::has_heterogenous_adjoint_constraint ( const unsigned int  qoi_num,
const dof_id_type  dof 
) const
inline

Backwards compatibility with misspelling.

在文件 dof_map.h1099 行定义.

参考 has_heterogeneous_adjoint_constraint().

1101  {
1102  return this->has_heterogeneous_adjoint_constraint (qoi_num, dof);
1103  }
Number has_heterogeneous_adjoint_constraint(const unsigned int qoi_num, const dof_id_type dof) const
Definition: dof_map.h:2203
bool libMesh::DofMap::has_heterogenous_adjoint_constraints ( const unsigned int  qoi_num) const
inline

Backwards compatibility with misspelling.

在文件 dof_map.h1083 行定义.

参考 has_heterogeneous_adjoint_constraints().

1084  {
1085  return this->has_heterogeneous_adjoint_constraints (qoi_num);
1086  }
bool has_heterogeneous_adjoint_constraints(const unsigned int qoi_num) const
Definition: dof_map.h:2189
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 has the opposite sign convention from u:=K, and we apply heterogeneous constraints accordingly.

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

在文件 dof_map_constraints.C2635 行定义.

参考 libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::right_multiply(), libMesh::DenseVector< T >::size(), libMesh::NumericVector< T >::type() , 以及 libMesh::DenseMatrix< T >::vector_mult_transpose().

2639 {
2640  libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
2641  libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
2642  libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
2643 
2644  libmesh_assert (solution_local.type() == SERIAL ||
2645  solution_local.type() == GHOSTED);
2646 
2647  // check for easy return
2648  if (this->_dof_constraints.empty())
2649  return;
2650 
2651  // The constrained matrix is built up as C^T K C.
2652  // The constrained RHS is built up as C^T F
2653  // Asymmetric residual terms are added if we do not have x = Cx+h
2656 
2657  this->build_constraint_matrix_and_vector (C, H, elem_dofs);
2658 
2659  LOG_SCOPE("hetero_cnstrn_elem_jac_res()", "DofMap");
2660 
2661  // It is possible that the matrix is not constrained at all.
2662  if ((C.m() != matrix.m()) ||
2663  (C.n() != elem_dofs.size()))
2664  return;
2665 
2666  // Compute the matrix-vector product C^T F
2667  DenseVector<Number> old_rhs(rhs);
2668  C.vector_mult_transpose(rhs, old_rhs);
2669 
2670  // Compute the matrix-matrix-matrix product C^T K C
2671  matrix.left_multiply_transpose (C);
2672  matrix.right_multiply (C);
2673 
2674  libmesh_assert_equal_to (matrix.m(), matrix.n());
2675  libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
2676  libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
2677 
2678  for (unsigned int i=0,
2679  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2680  i != n_elem_dofs; i++)
2681  {
2682  const dof_id_type dof_id = elem_dofs[i];
2683 
2684  const DofConstraints::const_iterator
2685  pos = _dof_constraints.find(dof_id);
2686 
2687  if (pos != _dof_constraints.end())
2688  {
2689  for (auto j : make_range(matrix.n()))
2690  matrix(i,j) = 0.;
2691 
2692  // If the DOF is constrained
2693  matrix(i,i) = 1.;
2694 
2695  // This will put a nonsymmetric entry in the constraint
2696  // row to ensure that the linear system produces the
2697  // correct value for the constrained DOF.
2698  const DofConstraintRow & constraint_row = pos->second;
2699 
2700  for (const auto & item : constraint_row)
2701  for (unsigned int j=0; j != n_elem_dofs; j++)
2702  if (elem_dofs[j] == item.first)
2703  matrix(i,j) = -item.second;
2704 
2705  const DofConstraintValueMap::const_iterator valpos =
2706  _primal_constraint_values.find(dof_id);
2707 
2708  Number & rhs_val = rhs(i);
2709  rhs_val = (valpos == _primal_constraint_values.end()) ?
2710  0 : -valpos->second;
2711  for (const auto & [constraining_dof, coef] : constraint_row)
2712  rhs_val -= coef * solution_local(constraining_dof);
2713  rhs_val += solution_local(dof_id);
2714  }
2715  }
2716 }
unsigned int n() const
返回矩阵的列维度。
void build_constraint_matrix_and_vector(DenseMatrix< Number > &C, DenseVector< Number > &H, std::vector< dof_id_type > &elem_dofs, int qoi_index=-1, const bool called_recursively=false) const
Build the constraint matrix C and the forcing vector H associated with the element degree of freedom ...
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this)^T * arg。
unsigned int m() const
返回矩阵的行维度。
virtual void right_multiply(const DenseMatrixBase< T > &M2) overridefinal
右乘以矩阵 M2。
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
void left_multiply_transpose(const DenseMatrix< T > &A)
用矩阵 A 的转置左乘。
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
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:90
ParallelType type() const
获取向量的类型。
定义用于有限元计算的稠密向量类。该类基本上是为了补充 DenseMatrix 类而设计的。 它相对于 std::vector 具有额外的功能,使其在有限元中特别有用,特别是对于方程组。 所有重写的虚拟函...
Definition: dof_map.h:64
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
virtual unsigned int size() const overridefinal
Definition: dense_vector.h:111
uint8_t dof_id_type
Definition: id_types.h:67
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.

在文件 dof_map_constraints.C2529 行定义.

参考 _adjoint_constraint_values, _dof_constraints, _primal_constraint_values, build_constraint_matrix_and_vector(), is_constrained_dof(), libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::right_multiply(), libMesh::DenseVector< T >::size(), libMesh::DenseMatrix< T >::vector_mult() , 以及 libMesh::DenseMatrix< T >::vector_mult_transpose().

参考自 heterogenously_constrain_element_matrix_and_vector() , 以及 process_mesh_constraint_rows().

2534 {
2535  libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
2536  libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
2537  libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
2538 
2539  // check for easy return
2540  if (this->_dof_constraints.empty())
2541  return;
2542 
2543  // The constrained matrix is built up as C^T K C.
2544  // The constrained RHS is built up as C^T (F - K H)
2547 
2548  this->build_constraint_matrix_and_vector (C, H, elem_dofs, qoi_index);
2549 
2550  LOG_SCOPE("hetero_cnstrn_elem_mat_vec()", "DofMap");
2551 
2552  // It is possible that the matrix is not constrained at all.
2553  if ((C.m() == matrix.m()) &&
2554  (C.n() == elem_dofs.size())) // It the matrix is constrained
2555  {
2556  // We may have rhs values to use later
2557  const DofConstraintValueMap * rhs_values = nullptr;
2558  if (qoi_index < 0)
2559  rhs_values = &_primal_constraint_values;
2560  else
2561  {
2562  const AdjointDofConstraintValues::const_iterator
2563  it = _adjoint_constraint_values.find(qoi_index);
2564  if (it != _adjoint_constraint_values.end())
2565  rhs_values = &it->second;
2566  }
2567 
2568  // Compute matrix/vector product K H
2570  matrix.vector_mult(KH, H);
2571 
2572  // Compute the matrix-vector product C^T (F - KH)
2573  DenseVector<Number> F_minus_KH(rhs);
2574  F_minus_KH -= KH;
2575  C.vector_mult_transpose(rhs, F_minus_KH);
2576 
2577  // Compute the matrix-matrix-matrix product C^T K C
2578  matrix.left_multiply_transpose (C);
2579  matrix.right_multiply (C);
2580 
2581  libmesh_assert_equal_to (matrix.m(), matrix.n());
2582  libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
2583  libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
2584 
2585  for (unsigned int i=0,
2586  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2587  i != n_elem_dofs; i++)
2588  {
2589  const dof_id_type dof_id = elem_dofs[i];
2590 
2591  if (this->is_constrained_dof(dof_id))
2592  {
2593  for (auto j : make_range(matrix.n()))
2594  matrix(i,j) = 0.;
2595 
2596  // If the DOF is constrained
2597  matrix(i,i) = 1.;
2598 
2599  // This will put a nonsymmetric entry in the constraint
2600  // row to ensure that the linear system produces the
2601  // correct value for the constrained DOF.
2602  if (asymmetric_constraint_rows)
2603  {
2604  DofConstraints::const_iterator
2605  pos = _dof_constraints.find(dof_id);
2606 
2607  libmesh_assert (pos != _dof_constraints.end());
2608 
2609  const DofConstraintRow & constraint_row = pos->second;
2610 
2611  for (const auto & item : constraint_row)
2612  for (unsigned int j=0; j != n_elem_dofs; j++)
2613  if (elem_dofs[j] == item.first)
2614  matrix(i,j) = -item.second;
2615 
2616  if (rhs_values)
2617  {
2618  const DofConstraintValueMap::const_iterator valpos =
2619  rhs_values->find(dof_id);
2620 
2621  rhs(i) = (valpos == rhs_values->end()) ?
2622  0 : valpos->second;
2623  }
2624  }
2625  else
2626  rhs(i) = 0.;
2627  }
2628  }
2629 
2630  } // end if is constrained...
2631 }
unsigned int n() const
返回矩阵的列维度。
void build_constraint_matrix_and_vector(DenseMatrix< Number > &C, DenseVector< Number > &H, std::vector< dof_id_type > &elem_dofs, int qoi_index=-1, const bool called_recursively=false) const
Build the constraint matrix C and the forcing vector H associated with the element degree of freedom ...
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this)^T * arg。
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:2034
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
unsigned int m() const
返回矩阵的行维度。
virtual void right_multiply(const DenseMatrixBase< T > &M2) overridefinal
右乘以矩阵 M2。
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
Storage for DofConstraint right hand sides for a particular problem.
Definition: dof_map.h:110
void left_multiply_transpose(const DenseMatrix< T > &A)
用矩阵 A 的转置左乘。
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
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:90
定义用于有限元计算的稠密向量类。该类基本上是为了补充 DenseMatrix 类而设计的。 它相对于 std::vector 具有额外的功能,使其在有限元中特别有用,特别是对于方程组。 所有重写的虚拟函...
Definition: dof_map.h:64
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this) * arg。
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
virtual unsigned int size() const overridefinal
Definition: dense_vector.h:111
uint8_t dof_id_type
Definition: id_types.h:67
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

在文件 dof_map_constraints.C2720 行定义.

参考 libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::size(), libMesh::NumericVector< T >::type() , 以及 libMesh::DenseMatrix< T >::vector_mult_transpose().

2723 {
2724  libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
2725 
2726  libmesh_assert (solution_local.type() == SERIAL ||
2727  solution_local.type() == GHOSTED);
2728 
2729  // check for easy return
2730  if (this->_dof_constraints.empty())
2731  return;
2732 
2733  // The constrained RHS is built up as C^T F
2734  // Asymmetric residual terms are added if we do not have x = Cx+h
2737 
2738  this->build_constraint_matrix_and_vector (C, H, elem_dofs);
2739 
2740  LOG_SCOPE("hetero_cnstrn_elem_res()", "DofMap");
2741 
2742  // It is possible that the element is not constrained at all.
2743  if ((C.m() != rhs.size()) ||
2744  (C.n() != elem_dofs.size()))
2745  return;
2746 
2747  // Compute the matrix-vector product C^T F
2748  DenseVector<Number> old_rhs(rhs);
2749  C.vector_mult_transpose(rhs, old_rhs);
2750 
2751  for (unsigned int i=0,
2752  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2753  i != n_elem_dofs; i++)
2754  {
2755  const dof_id_type dof_id = elem_dofs[i];
2756 
2757  const DofConstraints::const_iterator
2758  pos = _dof_constraints.find(dof_id);
2759 
2760  if (pos != _dof_constraints.end())
2761  {
2762  // This will put a nonsymmetric entry in the constraint
2763  // row to ensure that the linear system produces the
2764  // correct value for the constrained DOF.
2765  const DofConstraintRow & constraint_row = pos->second;
2766 
2767  const DofConstraintValueMap::const_iterator valpos =
2768  _primal_constraint_values.find(dof_id);
2769 
2770  Number & rhs_val = rhs(i);
2771  rhs_val = (valpos == _primal_constraint_values.end()) ?
2772  0 : -valpos->second;
2773  for (const auto & [constraining_dof, coef] : constraint_row)
2774  rhs_val -= coef * solution_local(constraining_dof);
2775  rhs_val += solution_local(dof_id);
2776  }
2777  }
2778 }
unsigned int n() const
返回矩阵的列维度。
void build_constraint_matrix_and_vector(DenseMatrix< Number > &C, DenseVector< Number > &H, std::vector< dof_id_type > &elem_dofs, int qoi_index=-1, const bool called_recursively=false) const
Build the constraint matrix C and the forcing vector H associated with the element degree of freedom ...
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this)^T * arg。
unsigned int m() const
返回矩阵的行维度。
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
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:90
ParallelType type() const
获取向量的类型。
定义用于有限元计算的稠密向量类。该类基本上是为了补充 DenseMatrix 类而设计的。 它相对于 std::vector 具有额外的功能,使其在有限元中特别有用,特别是对于方程组。 所有重写的虚拟函...
Definition: dof_map.h:64
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
virtual unsigned int size() const overridefinal
Definition: dense_vector.h:111
uint8_t dof_id_type
Definition: id_types.h:67
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 has the opposite sign convention from u:=u_in-J, 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.

在文件 dof_map_constraints.C2836 行定义.

参考 _adjoint_constraint_values, _dof_constraints, _primal_constraint_values, build_constraint_matrix_and_vector(), is_constrained_dof(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::size(), libMesh::DenseMatrix< T >::vector_mult() , 以及 libMesh::DenseMatrix< T >::vector_mult_transpose().

参考自 heterogenously_constrain_element_vector().

2841 {
2842  libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
2843  libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
2844  libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
2845 
2846  // check for easy return
2847  if (this->_dof_constraints.empty())
2848  return;
2849 
2850  // The constrained matrix is built up as C^T K C.
2851  // The constrained RHS is built up as C^T (F - K H)
2854 
2855  this->build_constraint_matrix_and_vector (C, H, elem_dofs, qoi_index);
2856 
2857  LOG_SCOPE("hetero_cnstrn_elem_vec()", "DofMap");
2858 
2859  // It is possible that the matrix is not constrained at all.
2860  if ((C.m() == matrix.m()) &&
2861  (C.n() == elem_dofs.size())) // It the matrix is constrained
2862  {
2863  // We may have rhs values to use later
2864  const DofConstraintValueMap * rhs_values = nullptr;
2865  if (qoi_index < 0)
2866  rhs_values = &_primal_constraint_values;
2867  else
2868  {
2869  const AdjointDofConstraintValues::const_iterator
2870  it = _adjoint_constraint_values.find(qoi_index);
2871  if (it != _adjoint_constraint_values.end())
2872  rhs_values = &it->second;
2873  }
2874 
2875  // Compute matrix/vector product K H
2877  matrix.vector_mult(KH, H);
2878 
2879  // Compute the matrix-vector product C^T (F - KH)
2880  DenseVector<Number> F_minus_KH(rhs);
2881  F_minus_KH -= KH;
2882  C.vector_mult_transpose(rhs, F_minus_KH);
2883 
2884  for (unsigned int i=0,
2885  n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2886  i != n_elem_dofs; i++)
2887  {
2888  const dof_id_type dof_id = elem_dofs[i];
2889 
2890  if (this->is_constrained_dof(dof_id))
2891  {
2892  // This will put a nonsymmetric entry in the constraint
2893  // row to ensure that the linear system produces the
2894  // correct value for the constrained DOF.
2895  if (asymmetric_constraint_rows && rhs_values)
2896  {
2897  const DofConstraintValueMap::const_iterator valpos =
2898  rhs_values->find(dof_id);
2899 
2900  rhs(i) = (valpos == rhs_values->end()) ?
2901  0 : valpos->second;
2902  }
2903  else
2904  rhs(i) = 0.;
2905  }
2906  }
2907 
2908  } // end if is constrained...
2909 }
unsigned int n() const
返回矩阵的列维度。
void build_constraint_matrix_and_vector(DenseMatrix< Number > &C, DenseVector< Number > &H, std::vector< dof_id_type > &elem_dofs, int qoi_index=-1, const bool called_recursively=false) const
Build the constraint matrix C and the forcing vector H associated with the element degree of freedom ...
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this)^T * arg。
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:2034
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
unsigned int m() const
返回矩阵的行维度。
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
Storage for DofConstraint right hand sides for a particular problem.
Definition: dof_map.h:110
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
定义用于有限元计算的稠密向量类。该类基本上是为了补充 DenseMatrix 类而设计的。 它相对于 std::vector 具有额外的功能,使其在有限元中特别有用,特别是对于方程组。 所有重写的虚拟函...
Definition: dof_map.h:64
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this) * arg。
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
virtual unsigned int size() const overridefinal
Definition: dense_vector.h:111
uint8_t dof_id_type
Definition: id_types.h:67
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

在文件 dof_map.h1234 行定义.

参考 heterogeneously_constrain_element_matrix_and_vector().

1239  {
1241  (matrix, rhs, elem_dofs, asymmetric_constraint_rows, qoi_index);
1242  }
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 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

在文件 dof_map.h1278 行定义.

参考 heterogeneously_constrain_element_vector().

1283  {
1285  (matrix, rhs, elem_dofs, asymmetric_constraint_rows, qoi_index);
1286  }
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 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.

在文件 reference_counter.h183 行定义.

参考 libMesh::err.

参考自 libMesh::ReferenceCountedObject< SparseMatrix< T > >::ReferenceCountedObject().

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 }
OStreamProxy err
static Counts _counts
Actually holds the data.
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.

在文件 reference_counter.h207 行定义.

参考 libMesh::err.

参考自 libMesh::ReferenceCountedObject< SparseMatrix< T > >::~ReferenceCountedObject().

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 }
OStreamProxy err
static Counts _counts
Actually holds the data.
void libMesh::DofMap::invalidate_dofs ( MeshBase &  mesh) const
private

Invalidates all active DofObject dofs for this system.

在文件 dof_map.C835 行定义.

参考 sys_number().

参考自 distribute_dofs() , 以及 reinit().

836 {
837  const unsigned int sys_num = this->sys_number();
838 
839  // All the nodes
840  for (auto & node : mesh.node_ptr_range())
841  node->invalidate_dofs(sys_num);
842 
843  // All the active elements.
844  for (auto & elem : mesh.active_element_ptr_range())
845  elem->invalidate_dofs(sys_num);
846 }
unsigned int sys_number() const
Definition: dof_map.h:2093
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

在文件 dof_map.C333 行定义.

参考 _matrices.

334 {
335  return (std::find(_matrices.begin(), _matrices.end(),
336  &matrix) != _matrices.end());
337 }
std::vector< SparseMatrix< Number > * > _matrices
Additional matrices handled by this object.
Definition: dof_map.h:1871
bool libMesh::DofMap::is_constrained_dof ( const dof_id_type  dof) const
inline
bool libMesh::DofMap::is_constrained_node ( const Node *  node) const
inline
返回
true if the Node is constrained, false otherwise.

在文件 dof_map.h2163 行定义.

参考 _node_constraints.

参考自 allgather_recursive_constraints() , 以及 scatter_constraints().

2168 {
2169 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2170  if (_node_constraints.count(node))
2171  return true;
2172 #endif
2173 
2174  return false;
2175 }
NodeConstraints _node_constraints
Data structure containing DofObject constraints.
Definition: dof_map.h:2041
template<typename DofObjectSubclass >
template LIBMESH_EXPORT bool libMesh::DofMap::is_evaluable< Node > ( const DofObjectSubclass &  obj,
unsigned int  var_num = libMesh::invalid_uint 
) const
返回
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)

在文件 dof_map.C2609 行定义.

参考 all_semilocal_indices(), dof_indices() , 以及 libMesh::invalid_uint.

2611 {
2612  // Everything is evaluable on a local object
2613  if (obj.processor_id() == this->processor_id())
2614  return true;
2615 
2616  std::vector<dof_id_type> di;
2617 
2618  if (var_num == libMesh::invalid_uint)
2619  this->dof_indices(&obj, di);
2620  else
2621  this->dof_indices(&obj, di, var_num);
2622 
2623  return this->all_semilocal_indices(di);
2624 }
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:254
bool all_semilocal_indices(const std::vector< dof_id_type > &dof_indices) const
Definition: dof_map.C:2596
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Fills the vector di with the global degree of freedom indices for the element.
Definition: dof_map.C:1992
bool libMesh::DofMap::is_periodic_boundary ( const boundary_id_type  boundaryid) const
返回
true if the boundary given by boundaryid is periodic, false otherwise

在文件 dof_map.C219 行定义.

参考 _periodic_boundaries.

220 {
221  if (_periodic_boundaries->count(boundaryid) != 0)
222  return true;
223 
224  return false;
225 }
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Data structure containing periodic boundaries.
Definition: dof_map.h:2050
bool libMesh::DofMap::local_index ( dof_id_type  dof_index) const
inline
void libMesh::DofMap::local_variable_indices ( std::vector< dof_id_type > &  idx,
const MeshBase &  mesh,
unsigned int  var_num 
) const

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

在文件 dof_map.C1109 行定义.

参考 libMesh::Variable::active_on_subdomain(), local_index(), SCALAR_dof_indices(), sys_number(), variable() , 以及 variable_type().

1112 {
1113  // Count dofs in the *exact* order that distribute_dofs numbered
1114  // them, so that we can assume ascending indices and use push_back
1115  // instead of find+insert.
1116 
1117  const unsigned int sys_num = this->sys_number();
1118 
1119  // If this isn't a SCALAR variable, we need to find all its field
1120  // dofs on the mesh
1121  if (this->variable_type(var_num).family != SCALAR)
1122  {
1123  const Variable & var(this->variable(var_num));
1124 
1125  for (auto & elem : mesh.active_local_element_ptr_range())
1126  {
1127  if (!var.active_on_subdomain(elem->subdomain_id()))
1128  continue;
1129 
1130  // Only count dofs connected to active
1131  // elements on this processor.
1132  const unsigned int n_nodes = elem->n_nodes();
1133 
1134  // First get any new nodal DOFS
1135  for (unsigned int n=0; n<n_nodes; n++)
1136  {
1137  const Node & node = elem->node_ref(n);
1138 
1139  if (node.processor_id() != this->processor_id())
1140  continue;
1141 
1142  const unsigned int n_comp = node.n_comp(sys_num, var_num);
1143  for(unsigned int i=0; i<n_comp; i++)
1144  {
1145  const dof_id_type index = node.dof_number(sys_num,var_num,i);
1146  libmesh_assert (this->local_index(index));
1147 
1148  if (idx.empty() || index > idx.back())
1149  idx.push_back(index);
1150  }
1151  }
1152 
1153  // Next get any new element DOFS
1154  const unsigned int n_comp = elem->n_comp(sys_num, var_num);
1155  for (unsigned int i=0; i<n_comp; i++)
1156  {
1157  const dof_id_type index = elem->dof_number(sys_num,var_num,i);
1158  if (idx.empty() || index > idx.back())
1159  idx.push_back(index);
1160  }
1161  } // done looping over elements
1162 
1163 
1164  // we may have missed assigning DOFs to nodes that we own
1165  // but to which we have no connected elements matching our
1166  // variable restriction criterion. this will happen, for example,
1167  // if variable V is restricted to subdomain S. We may not own
1168  // any elements which live in S, but we may own nodes which are
1169  // *connected* to elements which do. in this scenario these nodes
1170  // will presently have unnumbered DOFs. we need to take care of
1171  // them here since we own them and no other processor will touch them.
1172  for (const auto & node : mesh.local_node_ptr_range())
1173  {
1174  libmesh_assert(node);
1175 
1176  const unsigned int n_comp = node->n_comp(sys_num, var_num);
1177  for (unsigned int i=0; i<n_comp; i++)
1178  {
1179  const dof_id_type index = node->dof_number(sys_num,var_num,i);
1180  if (idx.empty() || index > idx.back())
1181  idx.push_back(index);
1182  }
1183  }
1184  }
1185  // Otherwise, count up the SCALAR dofs, if we're on the processor
1186  // that holds this SCALAR variable
1187  else if (this->processor_id() == (this->n_processors()-1))
1188  {
1189  std::vector<dof_id_type> di_scalar;
1190  this->SCALAR_dof_indices(di_scalar,var_num);
1191  idx.insert( idx.end(), di_scalar.begin(), di_scalar.end());
1192  }
1193 }
const FEType & variable_type(const unsigned int c) const
Definition: dof_map.h:2141
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:831
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:2111
unsigned int sys_number() const
Definition: dof_map.h:2093
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:2544
uint8_t dof_id_type
Definition: id_types.h:67
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.

在文件 dof_map_constraints.C3381 行定义.

参考 _dof_constraints, _primal_constraint_values, std::abs(), build_constraint_matrix(), libMesh::NumericVector< T >::closed(), dof_indices(), libMesh::NumericVector< T >::first_local_index(), libMesh::NumericVector< T >::get(), is_constrained_dof(), libMesh::NumericVector< T >::last_local_index(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n() , 以及 libMesh::Real.

3383 {
3384  if (!v)
3385  v = system.solution.get();
3386  NumericVector<Number> & vec = *v;
3387 
3388  // We'll assume the vector is closed
3389  libmesh_assert (vec.closed());
3390 
3391  Real max_absolute_error = 0., max_relative_error = 0.;
3392 
3393  const MeshBase & mesh = system.get_mesh();
3394 
3395  libmesh_assert_equal_to (this, &(system.get_dof_map()));
3396 
3397  // indices on each element
3398  std::vector<dof_id_type> local_dof_indices;
3399 
3400  for (const auto & elem : mesh.active_local_element_ptr_range())
3401  {
3402  this->dof_indices(elem, local_dof_indices);
3403  std::vector<dof_id_type> raw_dof_indices = local_dof_indices;
3404 
3405  // Constraint matrix for each element
3407 
3408  this->build_constraint_matrix (C, local_dof_indices);
3409 
3410  // Continue if the element is unconstrained
3411  if (!C.m())
3412  continue;
3413 
3414  libmesh_assert_equal_to (C.m(), raw_dof_indices.size());
3415  libmesh_assert_equal_to (C.n(), local_dof_indices.size());
3416 
3417  for (auto i : make_range(C.m()))
3418  {
3419  // Recalculate any constrained dof owned by this processor
3420  dof_id_type global_dof = raw_dof_indices[i];
3421  if (this->is_constrained_dof(global_dof) &&
3422  global_dof >= vec.first_local_index() &&
3423  global_dof < vec.last_local_index())
3424  {
3425 #ifndef NDEBUG
3426  DofConstraints::const_iterator
3427  pos = _dof_constraints.find(global_dof);
3428 
3429  libmesh_assert (pos != _dof_constraints.end());
3430 #endif
3431 
3432  Number exact_value = 0;
3433  DofConstraintValueMap::const_iterator rhsit =
3434  _primal_constraint_values.find(global_dof);
3435  if (rhsit != _primal_constraint_values.end())
3436  exact_value = rhsit->second;
3437 
3438  for (auto j : make_range(C.n()))
3439  {
3440  if (local_dof_indices[j] != global_dof)
3441  exact_value += C(i,j) *
3442  vec(local_dof_indices[j]);
3443  }
3444 
3445  max_absolute_error = std::max(max_absolute_error,
3446  std::abs(vec(global_dof) - exact_value));
3447  max_relative_error = std::max(max_relative_error,
3448  std::abs(vec(global_dof) - exact_value)
3449  / std::abs(exact_value));
3450  }
3451  }
3452  }
3453 
3454  return std::pair<Real, Real>(max_absolute_error, max_relative_error);
3455 }
virtual bool closed() const
检查向量是否已经关闭并准备好进行计算。
unsigned int n() const
返回矩阵的列维度。
提供了不同线性代数库的向量存储方案的统一接口。
Definition: dof_map.h:67
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
计算自动微分实数向量的绝对值。
Definition: type_vector.h:112
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
unsigned int m() const
返回矩阵的行维度。
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
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...
virtual numeric_index_type first_local_index() const =0
获取实际存储在该处理器上的第一个向量元素的索引。
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
一次访问多个组件。 values 将 *不会* 重新分配空间;它应该已经具有足够的空间。 默认实现对每个索引调用 operator() ,但某些实现可能在此处提供更快的方法。 ...
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
virtual numeric_index_type last_local_index() const =0
获取实际存储在该处理器上的最后一个向量元素的索引+1。
uint8_t dof_id_type
Definition: id_types.h:67
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Fills the vector di with the global degree of freedom indices for the element.
Definition: dof_map.C:1992
void libMesh::DofMap::merge_ghost_functor_outputs ( GhostingFunctor::map_type &  elements_to_ghost,
CouplingMatricesSet temporary_coupling_matrices,
const std::set< GhostingFunctor * >::iterator &  gf_begin,
const std::set< GhostingFunctor * >::iterator &  gf_end,
const MeshBase::const_element_iterator &  elems_begin,
const MeshBase::const_element_iterator &  elems_end,
processor_id_type  p 
)
staticprivate

在文件 dof_map.C1440 行定义.

参考自 add_neighbors_to_send_list(), libMesh::SparsityPattern::Build::operator()() , 以及 scatter_constraints().

1447 {
1448  for (const auto & gf : as_range(gf_begin, gf_end))
1449  {
1450  GhostingFunctor::map_type more_elements_to_ghost;
1451 
1452  libmesh_assert(gf);
1453  (*gf)(elems_begin, elems_end, p, more_elements_to_ghost);
1454 
1455  // A GhostingFunctor should only return active elements, but
1456  // I forgot to *document* that, so let's go as easy as we
1457  // can on functors that return inactive elements.
1458 #if defined(LIBMESH_ENABLE_DEPRECATED) && defined(LIBMESH_ENABLE_AMR)
1459  std::vector<std::pair<const Elem*, const CouplingMatrix*>> children_to_couple;
1460  for (auto it = more_elements_to_ghost.begin();
1461  it != more_elements_to_ghost.end();)
1462  {
1463  const Elem * elem = it->first;
1464  if (!elem->active())
1465  {
1466  libmesh_deprecated();
1467  std::vector<const Elem*> children_to_ghost;
1468  elem->active_family_tree(children_to_ghost,
1469  /*reset=*/ false);
1470  for (const Elem * child : children_to_ghost)
1471  if (child->processor_id() != p)
1472  children_to_couple.emplace_back(child, it->second);
1473 
1474  it = more_elements_to_ghost.erase(it);
1475  }
1476  else
1477  ++it;
1478  }
1479  more_elements_to_ghost.insert(children_to_couple.begin(),
1480  children_to_couple.end());
1481 #endif
1482 
1483  for (const auto & [elem, elem_cm] : more_elements_to_ghost)
1484  {
1485  // At this point we should only have active elements, even
1486  // if we had to fix up gf output to get here.
1487  libmesh_assert(elem->active());
1488 
1489  GhostingFunctor::map_type::iterator existing_it =
1490  elements_to_ghost.find (elem);
1491 
1492  if (existing_it == elements_to_ghost.end())
1493  elements_to_ghost.emplace(elem, elem_cm);
1494  else
1495  {
1496  if (existing_it->second)
1497  {
1498  if (elem_cm)
1499  {
1500  // If this isn't already a temporary
1501  // then we need to make one so we'll
1502  // have a non-const matrix to merge
1503  if (temporary_coupling_matrices.empty() ||
1504  !temporary_coupling_matrices.count(existing_it->second))
1505  {
1506  // Make copy. This just calls the
1507  // compiler-generated copy constructor
1508  // because the CouplingMatrix class does not
1509  // define a custom copy constructor.
1510  auto result_pr = temporary_coupling_matrices.insert(std::make_unique<CouplingMatrix>(*existing_it->second));
1511  existing_it->second = result_pr.first->get();
1512  }
1513 
1514  // Merge elem_cm into existing CouplingMatrix
1515  const_cast<CouplingMatrix &>(*existing_it->second) &= *elem_cm;
1516  }
1517  else // elem_cm == nullptr
1518  {
1519  // Any existing_it matrix merged with a full
1520  // matrix (symbolized as nullptr) gives another
1521  // full matrix (symbolizable as nullptr).
1522 
1523  // So if existing_it->second is a temporary then
1524  // we don't need it anymore; we might as well
1525  // remove it to keep the set of temporaries
1526  // small.
1527  auto temp_it = temporary_coupling_matrices.find(existing_it->second);
1528  if (temp_it != temporary_coupling_matrices.end())
1529  temporary_coupling_matrices.erase(temp_it);
1530 
1531  existing_it->second = nullptr;
1532  }
1533  }
1534  // else we have a nullptr already, then we have a full
1535  // coupling matrix, already, and merging with anything
1536  // else won't change that, so we're done.
1537  }
1538  }
1539  }
1540 }
dof_id_type libMesh::DofMap::n_constrained_dofs ( ) const
返回
The total number of constrained degrees of freedom in the problem.

在文件 dof_map_constraints.C1714 行定义.

参考 n_local_constrained_dofs().

参考自 enforce_adjoint_constraints_exactly(), enforce_constraints_exactly(), enforce_constraints_on_jacobian() , 以及 enforce_constraints_on_residual().

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
uint8_t dof_id_type
Definition: id_types.h:67
dof_id_type libMesh::DofMap::n_constrained_nodes ( ) const
inline
返回
The total number of constrained Nodes in the mesh.

在文件 dof_map.h908 行定义.

参考 _node_constraints.

909  { return cast_int<dof_id_type>(_node_constraints.size()); }
NodeConstraints _node_constraints
Data structure containing DofObject constraints.
Definition: dof_map.h:2041
dof_id_type libMesh::DofMap::n_dofs ( ) const
inline
dof_id_type libMesh::DofMap::n_dofs_on_processor ( const processor_id_type  proc) const
inline
返回
The number of degrees of freedom on partition proc.

在文件 dof_map.h675 行定义.

参考 _end_df , 以及 _first_df.

参考自 build_sparsity(), libMesh::SparsityPattern::Build::join(), n_local_dofs(), libMesh::SparsityPattern::Build::operator()() , 以及 libMesh::SparsityPattern::Build::parallel_sync().

676  {
677  libmesh_assert_less (proc, _first_df.size());
678  return cast_int<dof_id_type>(_end_df[proc] - _first_df[proc]);
679  }
std::vector< dof_id_type > _end_df
Last DOF index (plus 1) on processor p.
Definition: dof_map.h:1881
std::vector< dof_id_type > _first_df
First DOF index on processor p.
Definition: dof_map.h:1876
dof_id_type libMesh::DofMap::n_local_constrained_dofs ( ) const
返回
The number of constrained degrees of freedom on this processor.

在文件 dof_map_constraints.C1724 行定义.

参考 _dof_constraints, end_dof() , 以及 first_dof().

参考自 n_constrained_dofs().

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 }
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
dof_id_type end_dof() const
Definition: dof_map.h:711
dof_id_type first_dof() const
Definition: dof_map.h:687
dof_id_type libMesh::DofMap::n_local_dofs ( ) const
inline
返回
The number of degrees of freedom on this processor.

在文件 dof_map.h669 行定义.

参考 n_dofs_on_processor().

参考自 enforce_adjoint_constraints_exactly(), enforce_constraints_exactly() , 以及 process_mesh_constraint_rows().

670  { return this->n_dofs_on_processor (this->processor_id()); }
dof_id_type n_dofs_on_processor(const processor_id_type proc) const
Definition: dof_map.h:675
static unsigned int libMesh::ReferenceCounter::n_objects ( )
inlinestaticinherited

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

在文件 reference_counter.h85 行定义.

参考 libMesh::ReferenceCounter::_n_objects.

参考自 libMesh::LibMeshInit::~LibMeshInit().

86  { return _n_objects; }
static Threads::atomic< unsigned int > _n_objects
The number of objects.
dof_id_type libMesh::DofMap::n_old_dofs ( ) const
inline
返回
The total number of degrees of freedom on old_dof_objects

在文件 dof_map.h1539 行定义.

参考 _n_old_dfs.

参考自 SCALAR_dof_indices().

1539 { return _n_old_dfs; }
dof_id_type _n_old_dfs
Total number of degrees of freedom on old dof objects.
Definition: dof_map.h:2001
dof_id_type libMesh::DofMap::n_SCALAR_dofs ( ) const
inline
返回
The number of SCALAR dofs.

在文件 dof_map.h664 行定义.

参考 _n_SCALAR_dofs.

参考自 distribute_dofs() , 以及 SCALAR_dof_indices().

664 { return _n_SCALAR_dofs; }
dof_id_type _n_SCALAR_dofs
The total number of SCALAR dofs associated to all SCALAR variables.
Definition: dof_map.h:1994
unsigned int libMesh::DofMap::n_variable_groups ( ) const
inline
返回
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...

在文件 dof_map.h613 行定义.

参考 _variable_groups.

参考自 distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), distribute_scalar_dofs(), dof_indices(), has_blocked_representation(), old_dof_indices(), reinit() , 以及 set_nonlocal_dof_objects().

614  { return cast_int<unsigned int>(_variable_groups.size()); }
std::vector< VariableGroup > _variable_groups
The finite element type for each variable group.
Definition: dof_map.h:1844
unsigned int libMesh::DofMap::n_variables ( ) const
inline
返回
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...

在文件 dof_map.h621 行定义.

参考 _variables.

参考自 add_neighbors_to_send_list(), block_size(), create_dof_constraints(), distribute_dofs(), has_blocked_representation(), libMesh::SparsityPattern::Build::operator()(), process_mesh_constraint_rows(), reinit(), use_coupled_neighbor_dofs() , 以及 var_group_from_var_number().

622  { return cast_int<unsigned int>(_variables.size()); }
std::vector< Variable > _variables
The finite element type for each variable.
Definition: dof_map.h:1839
NodeConstraints::const_iterator libMesh::DofMap::node_constraint_rows_begin ( ) const
inline
返回
An iterator pointing to the first Node constraint row.

在文件 dof_map.h1058 行定义.

参考 _node_constraints.

1059  { return _node_constraints.begin(); }
NodeConstraints _node_constraints
Data structure containing DofObject constraints.
Definition: dof_map.h:2041
NodeConstraints::const_iterator libMesh::DofMap::node_constraint_rows_end ( ) const
inline
返回
An iterator pointing just past the last Node constraint row.

在文件 dof_map.h1064 行定义.

参考 _node_constraints.

1065  { return _node_constraints.end(); }
NodeConstraints _node_constraints
Data structure containing DofObject constraints.
Definition: dof_map.h:2041
DofObject * libMesh::DofMap::node_ptr ( MeshBase &  mesh,
dof_id_type  i 
) const
private
返回
The Node pointer with index i from the mesh.

在文件 dof_map.C341 行定义.

参考自 distribute_dofs().

342 {
343  return mesh.node_ptr(i);
344 }
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.

在文件 dof_map.C2283 行定义.

参考 _node_dof_indices() , 以及 libMesh::DofObject::get_old_dof_object_ref().

2287 {
2288  const DofObject & old_obj = elem.node_ref(n).get_old_dof_object_ref();
2289  this->_node_dof_indices(elem, n, old_obj, di, vn);
2290 }
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:2296
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.

在文件 dof_map.C2630 行定义.

参考 _dont_p_refine, libMesh::Variable::active_on_subdomain(), libMesh::DofObject::dof_number(), libMesh::DofObject::get_old_dof_object_ref(), libMesh::DofObject::invalid_id, libMesh::invalid_uint, libMesh::DofObject::n_comp_group(), libMesh::DofObject::n_systems(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::VariableGroup::number(), SCALAR_dof_indices(), sys_number(), libMesh::Variable::type() , 以及 variable_group().

2633 {
2634  LOG_SCOPE("old_dof_indices()", "DofMap");
2635 
2636  libmesh_assert(elem);
2637 
2638  const ElemType type = elem->type();
2639  const unsigned int sys_num = this->sys_number();
2640  const unsigned int n_var_groups = this->n_variable_groups();
2641 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2642  const bool is_inf = elem->infinite();
2643 #endif
2644 
2645  // If we have dof indices stored on the elem, and there's no chance
2646  // that we only have those indices because we were just p refined,
2647  // then we should have old dof indices too.
2648  libmesh_assert(!elem->has_dofs(sys_num) ||
2649  elem->p_refinement_flag() == Elem::JUST_REFINED ||
2650  elem->get_old_dof_object());
2651 
2652  // Clear the DOF indices vector.
2653  di.clear();
2654 
2655  // Determine the nodes contributing to element elem
2656  std::vector<const Node *> elem_nodes;
2657  const Node * const * nodes_ptr;
2658  unsigned int n_nodes;
2659  if (elem->type() == TRI3SUBDIVISION)
2660  {
2661  // Subdivision surface FE require the 1-ring around elem
2662  const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
2663  MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
2664  nodes_ptr = elem_nodes.data();
2665  n_nodes = cast_int<unsigned int>(elem_nodes.size());
2666  }
2667  else
2668  {
2669  // All other FE use only the nodes of elem itself
2670  nodes_ptr = elem->get_nodes();
2671  n_nodes = elem->n_nodes();
2672  }
2673 
2674  // Get the dof numbers
2675  for (unsigned int vg=0; vg<n_var_groups; vg++)
2676  {
2677  const VariableGroup & var = this->variable_group(vg);
2678  const unsigned int vars_in_group = var.n_variables();
2679 
2680  for (unsigned int vig=0; vig<vars_in_group; vig++)
2681  {
2682  const unsigned int v = var.number(vig);
2683  if ((vn == v) || (vn == libMesh::invalid_uint))
2684  {
2685  if (var.type().family == SCALAR &&
2686  (!elem ||
2687  var.active_on_subdomain(elem->subdomain_id())))
2688  {
2689  // We asked for this variable, so add it to the vector.
2690  std::vector<dof_id_type> di_new;
2691  this->SCALAR_dof_indices(di_new,v,true);
2692  di.insert( di.end(), di_new.begin(), di_new.end());
2693  }
2694  else
2695  if (var.active_on_subdomain(elem->subdomain_id()))
2696  { // Do this for all the variables if one was not specified
2697  // or just for the specified variable
2698 
2699  FEType fe_type = var.type();
2700  const bool add_p_level =
2701 #ifdef LIBMESH_ENABLE_AMR
2702  !_dont_p_refine.count(vg);
2703 #else
2704  false;
2705 #endif
2706  // Increase the polynomial order on p refined elements,
2707  // but make sure you get the right polynomial order for
2708  // the OLD degrees of freedom
2709  int p_adjustment = 0;
2710  if (elem->p_refinement_flag() == Elem::JUST_REFINED)
2711  {
2712  libmesh_assert_greater (elem->p_level(), 0);
2713  p_adjustment = -1;
2714  }
2715  else if (elem->p_refinement_flag() == Elem::JUST_COARSENED)
2716  {
2717  p_adjustment = 1;
2718  }
2719  p_adjustment *= add_p_level;
2720 
2721  // Compute the net amount of "extra" order, including Elem::p_level()
2722  int extra_order = int(add_p_level*elem->p_level()) + p_adjustment;
2723 
2724  const bool extra_hanging_dofs =
2725  FEInterface::extra_hanging_dofs(fe_type);
2726 
2727  const FEInterface::n_dofs_at_node_ptr ndan =
2728  FEInterface::n_dofs_at_node_function(fe_type, elem);
2729 
2730  // Get the node-based DOF numbers
2731  for (unsigned int n=0; n<n_nodes; n++)
2732  {
2733  const Node * node = nodes_ptr[n];
2734  const DofObject & old_dof_obj = node->get_old_dof_object_ref();
2735 
2736  // There is a potential problem with h refinement. Imagine a
2737  // quad9 that has a linear FE on it. Then, on the hanging side,
2738  // it can falsely identify a DOF at the mid-edge node. This is why
2739  // we call FEInterface instead of node->n_comp() directly.
2740  const unsigned int nc =
2741 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2742  is_inf ?
2743  FEInterface::n_dofs_at_node(var.type(), extra_order, elem, n) :
2744 #endif
2745  ndan (type, static_cast<Order>(var.type().order + extra_order), n);
2746 
2747  const int n_comp = old_dof_obj.n_comp_group(sys_num,vg);
2748 
2749  // If this is a non-vertex on a hanging node with extra
2750  // degrees of freedom, we use the non-vertex dofs (which
2751  // come in reverse order starting from the end, to
2752  // simplify p refinement)
2753  if (extra_hanging_dofs && !elem->is_vertex(n))
2754  {
2755  const int dof_offset = n_comp - nc;
2756 
2757  // We should never have fewer dofs than necessary on a
2758  // node unless we're getting indices on a parent element
2759  // or a just-coarsened element
2760  if (dof_offset < 0)
2761  {
2762  libmesh_assert(!elem->active() || elem->refinement_flag() ==
2763  Elem::JUST_COARSENED);
2764  di.resize(di.size() + nc, DofObject::invalid_id);
2765  }
2766  else
2767  for (int i=n_comp-1; i>=dof_offset; i--)
2768  {
2769  const dof_id_type d =
2770  old_dof_obj.dof_number(sys_num, vg, vig, i, n_comp);
2771 
2772  // On a newly-expanded subdomain, we
2773  // may have some DoFs that didn't
2774  // exist in the old system, in which
2775  // case we can't assert this:
2776  // libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2777 
2778  di.push_back(d);
2779  }
2780  }
2781  // If this is a vertex or an element without extra hanging
2782  // dofs, our dofs come in forward order coming from the
2783  // beginning. But we still might not have all
2784  // those dofs on the old_dof_obj, in cases
2785  // where a subdomain-restricted variable just
2786  // had its subdomain expanded.
2787  else
2788  {
2789  const unsigned int old_nc =
2790  std::min(static_cast<unsigned int>(n_comp), nc);
2791  for (unsigned int i=0; i != old_nc; ++i)
2792  {
2793  const dof_id_type d =
2794  old_dof_obj.dof_number(sys_num, vg, vig, i, n_comp);
2795 
2796  libmesh_assert_not_equal_to (d, DofObject::invalid_id);
2797 
2798  di.push_back(d);
2799  }
2800  for (unsigned int i=old_nc; i != nc; ++i)
2801  di.push_back(DofObject::invalid_id);
2802  }
2803  }
2804 
2805  // If there are any element-based DOF numbers, get them
2806  const unsigned int nc =
2807  FEInterface::n_dofs_per_elem(fe_type, extra_order, elem);
2808 
2809  if (nc != 0)
2810  {
2811  const DofObject & old_dof_obj = elem->get_old_dof_object_ref();
2812 
2813  const unsigned int n_comp =
2814  old_dof_obj.n_comp_group(sys_num,vg);
2815 
2816  if (old_dof_obj.n_systems() > sys_num &&
2817  nc <= n_comp)
2818  {
2819 
2820  for (unsigned int i=0; i<nc; i++)
2821  {
2822  const dof_id_type d =
2823  old_dof_obj.dof_number(sys_num, vg, vig, i, n_comp);
2824 
2825  di.push_back(d);
2826  }
2827  }
2828  else
2829  {
2830  // We should never have fewer dofs than
2831  // necessary on an element unless we're
2832  // getting indices on a parent element, a
2833  // just-coarsened element ... or a
2834  // subdomain-restricted variable with a
2835  // just-expanded subdomain
2836  // libmesh_assert(!elem->active() || fe_type.family == LAGRANGE ||
2837  // elem->refinement_flag() == Elem::JUST_COARSENED);
2838  di.resize(di.size() + nc, DofObject::invalid_id);
2839  }
2840  }
2841  }
2842  }
2843  } // end loop over variables within group
2844  } // end loop over variable groups
2845 }
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:254
const VariableGroup & variable_group(const unsigned int c) const
Definition: dof_map.h:2101
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:477
unsigned int n_variable_groups() const
Definition: dof_map.h:613
unsigned int sys_number() const
Definition: dof_map.h:2093
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:2544
std::unordered_set< unsigned int > _dont_p_refine
A container of variable groups that we should not p-refine.
Definition: dof_map.h:2022
uint8_t dof_id_type
Definition: id_types.h:67
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.

在文件 dof_map.C1692 行定义.

参考 _augment_send_list, _extra_send_list_context, _extra_send_list_function, _send_list, libMesh::DofMap::AugmentSendList::augment_send_list(), n_dofs() , 以及 libMesh::out.

参考自 reinit_send_list().

1693 {
1694  LOG_SCOPE("prepare_send_list()", "DofMap");
1695 
1696  // Return immediately if there's no ghost data
1697  if (this->n_processors() == 1)
1698  return;
1699 
1700  // Check to see if we have any extra stuff to add to the send_list
1702  {
1703  if (_augment_send_list)
1704  {
1705  libmesh_here();
1706  libMesh::out << "WARNING: You have specified both an extra send list function and object.\n"
1707  << " Are you sure this is what you meant to do??"
1708  << std::endl;
1709  }
1710 
1712  }
1713 
1714  if (_augment_send_list)
1716 
1717  // First sort the send list. After this
1718  // duplicated elements will be adjacent in the
1719  // vector
1720  std::sort(_send_list.begin(), _send_list.end());
1721 
1722  // Now use std::unique to remove duplicate entries
1723  std::vector<dof_id_type>::iterator new_end =
1724  std::unique (_send_list.begin(), _send_list.end());
1725 
1726  // Remove the end of the send_list. Use the "swap trick"
1727  // from Effective STL
1728  std::vector<dof_id_type> (_send_list.begin(), new_end).swap (_send_list);
1729 
1730  // Make sure the send list has nothing invalid in it.
1731  libmesh_assert(_send_list.empty() || _send_list.back() < this->n_dofs());
1732 }
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:1893
virtual void augment_send_list(std::vector< dof_id_type > &send_list)=0
User-defined function to augment the send list.
dof_id_type n_dofs() const
Definition: dof_map.h:659
AugmentSendList * _augment_send_list
Function object to call to add extra entries to the send list.
Definition: dof_map.h:1915
OStreamProxy out
void * _extra_send_list_context
A pointer associated with the extra send list that can optionally be passed in.
Definition: dof_map.h:1925
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:1920
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.

在文件 dof_map_constraints.C2262 行定义.

参考 get_local_constraints().

2264 {
2265  parallel_object_only();
2266 
2267  std::string local_constraints =
2268  this->get_local_constraints(print_nonlocal);
2269 
2270  if (this->processor_id())
2271  {
2272  this->comm().send(0, local_constraints);
2273  }
2274  else
2275  {
2276  os << "Processor 0:\n";
2277  os << local_constraints;
2278 
2279  for (auto p : IntRange<processor_id_type>(1, this->n_processors()))
2280  {
2281  this->comm().receive(p, local_constraints);
2282  os << "Processor " << p << ":\n";
2283  os << local_constraints;
2284  }
2285  }
2286 }
std::string get_local_constraints(bool print_nonlocal=false) const
Gets a string reporting all DoF and Node constraints local to this processor.
void libMesh::ReferenceCounter::print_info ( std::ostream &  out_stream = libMesh::out)
staticinherited

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

在文件 reference_counter.C81 行定义.

参考 libMesh::ReferenceCounter::_enable_print_counter , 以及 libMesh::ReferenceCounter::get_info().

参考自 libMesh::LibMeshInit::~LibMeshInit().

82 {
84  out_stream << ReferenceCounter::get_info();
85 }
static std::string get_info()
Gets a string containing the reference information.
static bool _enable_print_counter
Flag to control whether reference count information is printed when print_info is called...
void libMesh::DofMap::print_info ( std::ostream &  os = libMesh::out) const

Prints summary info about the sparsity bandwidth and constraints.

在文件 dof_map.C2915 行定义.

参考 get_info().

2916 {
2917  os << this->get_info();
2918 }
std::string get_info() const
Gets summary info about the sparsity bandwidth and constraints.
Definition: dof_map.C:2922
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.

在文件 dof_map_constraints.C4372 行定义.

参考 _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::Real , 以及 scatter_constraints().

参考自 reinit_send_list().

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

在文件 dof_map_constraints.C1898 行定义.

参考 _adjoint_constraint_values, _dof_constraints, _periodic_boundaries, _primal_constraint_values, add_constraint_row(), libMesh::SparseMatrix< T >::build(), libMesh::NumericVector< T >::build(), build_sparsity(), dof_indices(), end_dof(), first_dof(), heterogeneously_constrain_element_matrix_and_vector(), is_constrained_dof(), local_index(), n_dofs(), n_local_dofs(), n_variables(), sys_number(), libMesh::TOLERANCE , 以及 variable_type().

参考自 create_dof_constraints().

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  // This is fairly new code, still a bit experimental.
1919  libmesh_experimental();
1920 
1921  // We can't handle periodic boundary conditions on spline meshes
1922  // yet.
1923 #ifdef LIBMESH_ENABLE_PERIODIC
1924  libmesh_error_msg_if (!_periodic_boundaries->empty(),
1925  "Periodic boundary conditions are not yet implemented for spline meshes");
1926 #endif
1927 
1928  // We can handle existing Dirichlet constraints, but we'll need
1929  // to do solves to project them down onto the spline basis.
1930  std::unique_ptr<SparsityPattern::Build> sp;
1931  std::unique_ptr<SparseMatrix<Number>> mat;
1932 
1933  const unsigned int n_adjoint_rhs =
1935 
1936  // [0] for primal rhs, [q+1] for adjoint qoi q
1937  std::vector<std::unique_ptr<NumericVector<Number>>>
1938  solve_rhs(n_adjoint_rhs+1);
1939 
1940  // Keep track of which spline DoFs will be Dirichlet.
1941  // We use a set here to make it easier to find what processors
1942  // to send the DoFs to later.
1943  std::set<dof_id_type> my_dirichlet_spline_dofs;
1944 
1945  // And keep track of which non-spline Dofs were Dirichlet
1946  std::unordered_set<dof_id_type> was_previously_constrained;
1947 
1948  const unsigned int sys_num = this->sys_number();
1949  for (auto & node_row : constraint_rows)
1950  {
1951  const Node * node = node_row.first;
1952  libmesh_assert(node == mesh.node_ptr(node->id()));
1953 
1954  // Each processor only computes its own (and in distributed
1955  // cases, is only guaranteed to have the dependency data to
1956  // compute its own) constraints here.
1957  if (node->processor_id() != mesh.processor_id())
1958  continue;
1959 
1960  for (auto var_num : IntRange<unsigned int>(0, this->n_variables()))
1961  {
1962  const FEFamily & fe_family = this->variable_type(var_num).family;
1963 
1964  // constraint_rows only applies to nodal variables
1965  if (fe_family != LAGRANGE &&
1966  fe_family != RATIONAL_BERNSTEIN)
1967  continue;
1968 
1969  DofConstraintRow dc_row;
1970 
1971  const dof_id_type constrained_id =
1972  node->dof_number(sys_num, var_num, 0);
1973  for (const auto & [pr, val] : node_row.second)
1974  {
1975  const Elem * spline_elem = pr.first;
1976  libmesh_assert(spline_elem == mesh.elem_ptr(spline_elem->id()));
1977 
1978  const Node & spline_node =
1979  spline_elem->node_ref(pr.second);
1980 
1981  const dof_id_type spline_dof_id =
1982  spline_node.dof_number(sys_num, var_num, 0);
1983  dc_row[spline_dof_id] = val;
1984  }
1985 
1986  // See if we already have a constraint here.
1987  if (this->is_constrained_dof(constrained_id))
1988  {
1989  was_previously_constrained.insert(constrained_id);
1990 
1991  // Keep track of which spline DoFs will be
1992  // inheriting this non-spline DoF's constraints
1993  for (auto & row_entry : dc_row)
1994  my_dirichlet_spline_dofs.insert(row_entry.first);
1995 
1996  // If it wasn't a simple Dirichlet-type constraint
1997  // then I don't know what to do with it. We'll make
1998  // this an assertion only because this should only
1999  // crop up with periodic boundary conditions, which
2000  // we've already made sure we don't have.
2001  libmesh_assert(_dof_constraints[constrained_id].empty());
2002  }
2003 
2004  // Add the constraint, replacing any previous, so we can
2005  // use the new constraint in setting up the solve below
2006  this->add_constraint_row(constrained_id, dc_row, false);
2007  }
2008  }
2009 
2010  // my_dirichlet_spline_dofs may now include DoFs whose owners
2011  // don't know they need to become spline DoFs! We need to push
2012  // this data to them.
2013  if (this->comm().size() > 1)
2014  {
2015  std::unordered_map
2016  <processor_id_type, std::vector<dof_id_type>>
2017  their_dirichlet_spline_dofs;
2018 
2019  // If we ever change the underlying container here then we'd
2020  // better do some kind of sort before using it; we'll rely
2021  // on sorting to make the processor id lookup efficient.
2022  libmesh_assert(std::is_sorted(my_dirichlet_spline_dofs.begin(),
2023  my_dirichlet_spline_dofs.end()));
2024  processor_id_type destination_pid = 0;
2025  for (auto d : my_dirichlet_spline_dofs)
2026  {
2027  libmesh_assert_less(d, this->end_dof(this->comm().size()-1));
2028  while (d >= this->end_dof(destination_pid))
2029  destination_pid++;
2030 
2031  if (destination_pid != this->processor_id())
2032  their_dirichlet_spline_dofs[destination_pid].push_back(d);
2033  }
2034 
2035  auto receive_dof_functor =
2036  [& my_dirichlet_spline_dofs]
2038  const std::vector<dof_id_type> & dofs)
2039  {
2040  my_dirichlet_spline_dofs.insert(dofs.begin(), dofs.end());
2041  };
2042 
2043  Parallel::push_parallel_vector_data
2044  (this->comm(), their_dirichlet_spline_dofs, receive_dof_functor);
2045  }
2046 
2047 
2048  // If anyone had any prior constraints in effect, then we need
2049  // to convert them to constraints on the spline nodes.
2050  //
2051  // NOT simply testing prior_constraints here; maybe it turned
2052  // out that all our constraints were on non-spline-constrained
2053  // parts of a hybrid mesh?
2054  bool important_prior_constraints =
2055  !was_previously_constrained.empty();
2056  this->comm().max(important_prior_constraints);
2057 
2058  if (important_prior_constraints)
2059  {
2060  // Now that we have the spline constraints added, we can
2061  // finally construct a sparsity pattern that correctly
2062  // accounts for those constraints!
2063  mat = SparseMatrix<Number>::build(this->comm());
2064  for (auto q : IntRange<unsigned int>(0, n_adjoint_rhs+1))
2065  {
2066  solve_rhs[q] = NumericVector<Number>::build(this->comm());
2067  solve_rhs[q]->init(this->n_dofs(), this->n_local_dofs(),
2068  false, PARALLEL);
2069  }
2070 
2071  // We need to compute our own sparsity pattern, to take into
2072  // account the particularly non-sparse rows that can be
2073  // created by the spline constraints we just added.
2074  mat->attach_dof_map(*this);
2075  sp = this->build_sparsity(mesh);
2076  mat->attach_sparsity_pattern(*sp);
2077  mat->init();
2078 
2079  for (auto & node_row : constraint_rows)
2080  {
2081  const Node * node = node_row.first;
2082  libmesh_assert(node == mesh.node_ptr(node->id()));
2083 
2084  for (auto var_num : IntRange<unsigned int>(0, this->n_variables()))
2085  {
2086  const FEFamily & fe_family = this->variable_type(var_num).family;
2087 
2088  // constraint_rows only applies to nodal variables
2089  if (fe_family != LAGRANGE &&
2090  fe_family != RATIONAL_BERNSTEIN)
2091  continue;
2092 
2093  const dof_id_type constrained_id =
2094  node->dof_number(sys_num, var_num, 0);
2095 
2096  if (was_previously_constrained.count(constrained_id))
2097  {
2098  for (auto q : IntRange<int>(0, n_adjoint_rhs+1))
2099  {
2100  DenseMatrix<Number> K(1,1);
2101  DenseVector<Number> F(1);
2102  std::vector<dof_id_type> dof_indices(1, constrained_id);
2103 
2104  K(0,0) = 1;
2105 
2106  DofConstraintValueMap & vals = q ?
2109 
2110  DofConstraintValueMap::const_iterator rhsit =
2111  vals.find(constrained_id);
2112  F(0) = (rhsit == vals.end()) ? 0 : rhsit->second;
2113 
2114  // We no longer need any rhs values here directly.
2115  if (rhsit != vals.end())
2116  vals.erase(rhsit);
2117 
2119  (K, F, dof_indices, false, q ? (q-1) : -1);
2120  if (!q)
2121  mat->add_matrix(K, dof_indices);
2122  solve_rhs[q]->add_vector(F, dof_indices);
2123  }
2124  }
2125  }
2126  }
2127 
2128  // Any DoFs that aren't part of any constraint, directly or
2129  // indirectly, need a diagonal term to make the matrix
2130  // here invertible.
2131  for (dof_id_type d : IntRange<dof_id_type>(this->first_dof(),
2132  this->end_dof()))
2133  if (!was_previously_constrained.count(d) &&
2134  !my_dirichlet_spline_dofs.count(d))
2135  mat->add(d,d,1);
2136 
2137  // At this point, we're finally ready to solve for Dirichlet
2138  // constraint values on spline nodes.
2139  std::unique_ptr<LinearSolver<Number>> linear_solver =
2140  LinearSolver<Number>::build(this->comm());
2141 
2142  std::unique_ptr<NumericVector<Number>> projected_vals =
2143  NumericVector<Number>::build(this->comm());
2144 
2145  projected_vals->init(this->n_dofs(), this->n_local_dofs(),
2146  false, PARALLEL);
2147 
2148  DofConstraintRow empty_row;
2149  for (auto sd : my_dirichlet_spline_dofs)
2150  if (this->local_index(sd))
2151  this->add_constraint_row(sd, empty_row);
2152 
2153  for (auto q : IntRange<unsigned int>(0, n_adjoint_rhs+1))
2154  {
2155  // FIXME: we don't have an EquationSystems here, but I'd
2156  // rather not hardcode these...
2157  const double tol = double(TOLERANCE * TOLERANCE);
2158  const unsigned int max_its = 5000;
2159 
2160  linear_solver->solve(*mat, *projected_vals,
2161  *(solve_rhs[q]), tol, max_its);
2162 
2163  DofConstraintValueMap & vals = q ?
2166 
2167  for (auto sd : my_dirichlet_spline_dofs)
2168  if (this->local_index(sd))
2169  {
2170  Number constraint_rhs = (*projected_vals)(sd);
2171 
2172  std::pair<DofConstraintValueMap::iterator, bool> rhs_it =
2173  vals.emplace(sd, constraint_rhs);
2174  if (!rhs_it.second)
2175  rhs_it.first->second = constraint_rhs;
2176  }
2177  }
2178  }
2179 }
const FEType & variable_type(const unsigned int c) const
Definition: dof_map.h:2141
static constexpr Real TOLERANCE
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:831
dof_id_type n_dofs() const
Definition: dof_map.h:659
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)
使用由 solver_package 指定的线性求解器包构建一个 SparseMatrix&lt;T&gt;。
uint8_t processor_id_type
Definition: id_types.h:104
AdjointDofConstraintValues _adjoint_constraint_values
Definition: dof_map.h:2034
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2179
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 ...
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
std::unique_ptr< SparsityPattern::Build > build_sparsity(const MeshBase &mesh, bool calculate_constrained=false) const
Builds a sparsity pattern for matrices using the current degree-of-freedom numbering and coupling...
Definition: dof_map.C:64
unsigned int sys_number() const
Definition: dof_map.h:2093
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package())
构建一个 NumericVector 对象。
Storage for DofConstraint right hand sides for a particular problem.
Definition: dof_map.h:110
dof_id_type end_dof() const
Definition: dof_map.h:711
unsigned int n_variables() const
Definition: dof_map.h:621
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Data structure containing periodic boundaries.
Definition: dof_map.h:2050
DofConstraintValueMap _primal_constraint_values
Definition: dof_map.h:2032
dof_id_type n_local_dofs() const
Definition: dof_map.h:669
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:90
定义用于有限元计算的稠密向量类。该类基本上是为了补充 DenseMatrix 类而设计的。 它相对于 std::vector 具有额外的功能,使其在有限元中特别有用,特别是对于方程组。 所有重写的虚拟函...
Definition: dof_map.h:64
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
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.
dof_id_type first_dof() const
Definition: dof_map.h:687
uint8_t dof_id_type
Definition: id_types.h:67
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Fills the vector di with the global degree of freedom indices for the element.
Definition: dof_map.C:1992
void libMesh::DofMap::reinit ( MeshBase &  mesh)

Reinitialize the underlying data structures conformal to the current mesh.

在文件 dof_map.C506 行定义.

参考 _default_coupling, _dof_coupling, _dont_p_refine, _n_SCALAR_dofs, libMesh::Variable::active_on_subdomain(), libMesh::err, invalidate_dofs(), n_variable_groups(), libMesh::VariableGroup::n_variables(), n_variables(), sys_number(), libMesh::Variable::type(), use_coupled_neighbor_dofs() , 以及 variable_group().

参考自 distribute_dofs().

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

在文件 dof_map.C1734 行定义.

参考 add_neighbors_to_send_list(), clear_send_list(), prepare_send_list() , 以及 process_constraints().

1735 {
1736  this->clear_send_list();
1737  this->add_neighbors_to_send_list(mesh);
1738 
1739 #ifdef LIBMESH_ENABLE_CONSTRAINTS
1740  // This is assuming that we only need to recommunicate
1741  // the constraints and no new ones have been added since
1742  // a previous call to reinit_constraints.
1743  this->process_constraints(mesh);
1744 #endif
1745  this->prepare_send_list();
1746 }
void clear_send_list()
Clears the _send_list vector.
Definition: dof_map.h:485
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:1544
void process_constraints(MeshBase &)
Postprocesses any constrained degrees of freedom to be constrained only in terms of unconstrained dof...
void prepare_send_list()
Takes the _send_list vector (which may have duplicate entries) and sorts it.
Definition: dof_map.C:1692
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.

在文件 dof_map_constraints.C5513 行定义.

参考 _adjoint_dirichlet_boundaries, libMesh::DirichletBoundary::b , 以及 libMesh::DirichletBoundary::variables.

5515 {
5516  libmesh_assert_greater(_adjoint_dirichlet_boundaries.size(),
5517  qoi_index);
5518 
5519  auto lam = [&boundary_to_remove](const auto & bdy)
5520  {return bdy->b == boundary_to_remove.b && bdy->variables == boundary_to_remove.variables;};
5521 
5522  auto it = std::find_if(_adjoint_dirichlet_boundaries[qoi_index]->begin(),
5523  _adjoint_dirichlet_boundaries[qoi_index]->end(),
5524  lam);
5525 
5526  // Assert it was actually found and remove it from the vector
5527  libmesh_assert (it != _adjoint_dirichlet_boundaries[qoi_index]->end());
5528  _adjoint_dirichlet_boundaries[qoi_index]->erase(it);
5529 }
std::vector< std::unique_ptr< DirichletBoundaries > > _adjoint_dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition: dof_map.h:2064
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.

在文件 dof_map.C1898 行定义.

参考 _algebraic_ghosting_functors, _mesh , 以及 _shared_functors.

参考自 remove_default_ghosting().

1899 {
1900  _algebraic_ghosting_functors.erase(&evaluable_functor);
1901  _mesh.remove_ghosting_functor(evaluable_functor);
1902 
1903  auto it = _shared_functors.find(&evaluable_functor);
1904  if (it != _shared_functors.end())
1905  _shared_functors.erase(it);
1906 }
std::set< GhostingFunctor * > _algebraic_ghosting_functors
The list of all GhostingFunctor objects to be used when distributing ghosted vectors.
Definition: dof_map.h:1951
MeshBase & _mesh
The mesh that system uses.
Definition: dof_map.h:1864
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:1970
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.

在文件 dof_map.C1873 行定义.

参考 _coupling_functors, _mesh , 以及 _shared_functors.

参考自 remove_default_ghosting().

1874 {
1875  _coupling_functors.erase(&coupling_functor);
1876  _mesh.remove_ghosting_functor(coupling_functor);
1877 
1878  auto it = _shared_functors.find(&coupling_functor);
1879  if (it != _shared_functors.end())
1880  _shared_functors.erase(it);
1881 }
std::set< GhostingFunctor * > _coupling_functors
The list of all GhostingFunctor objects to be used when coupling degrees of freedom in matrix sparsit...
Definition: dof_map.h:1964
MeshBase & _mesh
The mesh that system uses.
Definition: dof_map.h:1864
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:1970
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.

在文件 dof_map.C1844 行定义.

参考 default_algebraic_ghosting(), default_coupling(), remove_algebraic_ghosting_functor() , 以及 remove_coupling_functor().

1845 {
1848 }
DefaultCoupling & default_coupling()
Default coupling functor.
Definition: dof_map.h:356
DefaultCoupling & default_algebraic_ghosting()
Default algebraic ghosting functor.
Definition: dof_map.h:418
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:1873
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.
Definition: dof_map.C:1898
void libMesh::DofMap::remove_dirichlet_boundary ( const DirichletBoundary dirichlet_boundary)

Removes the specified Dirichlet boundary from the system.

在文件 dof_map_constraints.C5499 行定义.

参考 _dirichlet_boundaries, libMesh::DirichletBoundary::b , 以及 libMesh::DirichletBoundary::variables.

5500 {
5501  // Find a boundary condition matching the one to be removed
5502  auto lam = [&boundary_to_remove](const auto & bdy)
5503  {return bdy->b == boundary_to_remove.b && bdy->variables == boundary_to_remove.variables;};
5504 
5505  auto it = std::find_if(_dirichlet_boundaries->begin(), _dirichlet_boundaries->end(), lam);
5506 
5507  // Assert it was actually found and remove it from the vector
5508  libmesh_assert (it != _dirichlet_boundaries->end());
5509  _dirichlet_boundaries->erase(it);
5510 }
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Data structure containing Dirichlet functions.
Definition: dof_map.h:2058
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.

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

在文件 dof_map.C2544 行定义.

参考 _first_old_scalar_df, _first_scalar_df, libMesh::DofObject::invalid_id, n_old_dofs(), n_SCALAR_dofs(), libMesh::Variable::type() , 以及 variable().

参考自 dof_indices(), local_variable_indices() , 以及 old_dof_indices().

2552 {
2553  LOG_SCOPE("SCALAR_dof_indices()", "DofMap");
2554 
2555  libmesh_assert(this->variable(vn).type().family == SCALAR);
2556 
2557 #ifdef LIBMESH_ENABLE_AMR
2558  // If we're asking for old dofs then we'd better have some
2559  if (old_dofs)
2560  libmesh_assert_greater_equal(n_old_dofs(), n_SCALAR_dofs());
2561 
2562  dof_id_type my_idx = old_dofs ?
2563  this->_first_old_scalar_df[vn] : this->_first_scalar_df[vn];
2564 #else
2565  dof_id_type my_idx = this->_first_scalar_df[vn];
2566 #endif
2567 
2568  libmesh_assert_not_equal_to(my_idx, DofObject::invalid_id);
2569 
2570  // The number of SCALAR dofs comes from the variable order
2571  const int n_dofs_vn = this->variable(vn).type().order.get_order();
2572 
2573  di.resize(n_dofs_vn);
2574  for (int i = 0; i != n_dofs_vn; ++i)
2575  di[i] = my_idx++;
2576 }
const FEType & type() const
Definition: variable.h:140
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:2111
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:1887
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:2017
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:477
dof_id_type n_old_dofs() const
Definition: dof_map.h:1539
dof_id_type n_SCALAR_dofs() const
Definition: dof_map.h:664
uint8_t dof_id_type
Definition: id_types.h:67
void libMesh::DofMap::scatter_constraints ( MeshBase &  mesh)

Sends constraint equations to constraining processors.

在文件 dof_map_constraints.C4643 行定义.

参考 _dof_constraints, _end_df, _node_constraints, _primal_constraint_values, coupling_functors_begin(), coupling_functors_end(), dof_indices(), gather_constraints(), is_constrained_dof(), is_constrained_node() , 以及 merge_ghost_functor_outputs().

参考自 process_constraints().

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

在文件 dof_map.C2580 行定义.

参考 _send_list , 以及 local_index().

参考自 all_semilocal_indices().

2581 {
2582  // If it's not in the local indices
2583  if (!this->local_index(dof_index))
2584  {
2585  // and if it's not in the ghost indices, then we're not
2586  // semilocal
2587  if (!std::binary_search(_send_list.begin(), _send_list.end(), dof_index))
2588  return false;
2589  }
2590 
2591  return true;
2592 }
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:1893
bool local_index(dof_id_type dof_index) const
Definition: dof_map.h:831
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.

在文件 dof_map.h2294 行定义.

参考 _constrained_sparsity_construction , 以及 libMesh::libmesh_ignore().

2295 {
2296  // This got only partly finished...
2297  if (use_constraints)
2298  libmesh_not_implemented();
2299 
2300 #ifdef LIBMESH_ENABLE_CONSTRAINTS
2301  _constrained_sparsity_construction = use_constraints;
2302 #endif
2303  libmesh_ignore(use_constraints);
2304 }
bool _constrained_sparsity_construction
This flag indicates whether or not we explicitly take constraint equations into account when computin...
Definition: dof_map.h:1834
void libmesh_ignore(const Args &...)
void libMesh::DofMap::set_error_on_constraint_loop ( bool  error_on_constraint_loop)

在文件 dof_map.C245 行定义.

参考 _error_on_constraint_loop.

参考自 set_error_on_cyclic_constraint().

246 {
247  _error_on_constraint_loop = error_on_constraint_loop;
248 }
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:1828
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.

注解
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.

在文件 dof_map.C238 行定义.

参考 set_error_on_constraint_loop().

239 {
240  // This function will eventually be officially libmesh_deprecated();
241  // Call DofMap::set_error_on_constraint_loop() instead.
242  set_error_on_constraint_loop(error_on_cyclic_constraint);
243 }
void set_error_on_constraint_loop(bool error_on_constraint_loop)
Definition: dof_map.C:245
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.

在文件 dof_map.C1748 行定义.

参考 _implicit_neighbor_dofs , 以及 _implicit_neighbor_dofs_initialized.

1749 {
1751  _implicit_neighbor_dofs = implicit_neighbor_dofs;
1752 }
bool _implicit_neighbor_dofs_initialized
Bools to indicate if we override the –implicit_neighbor_dofs commandline options. ...
Definition: dof_map.h:2073
bool _implicit_neighbor_dofs
Definition: dof_map.h:2074
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.

在文件 dof_map.C356 行定义.

参考 libMesh::DofObject::dof_number(), libMesh::DofObject::id(), libMesh::DofObject::invalid_id, libMesh::DofObject::invalid_processor_id, libMesh::DofObject::n_comp(), libMesh::DofObject::n_comp_group(), libMesh::DofObject::n_var_groups(), n_variable_groups(), libMesh::DofObject::n_vars(), libMesh::DofObject::processor_id(), libMesh::DofObject::set_n_comp_group(), libMesh::DofObject::set_vg_dof_base(), sys_number() , 以及 libMesh::DofObject::vg_dof_base().

参考自 distribute_dofs().

360 {
361  // This function must be run on all processors at once
362  parallel_object_only();
363 
364  // First, iterate over local objects to find out how many
365  // are on each processor
366  std::unordered_map<processor_id_type, dof_id_type> ghost_objects_from_proc;
367 
368  iterator_type it = objects_begin;
369 
370  for (; it != objects_end; ++it)
371  {
372  DofObject * obj = *it;
373 
374  if (obj)
375  {
376  processor_id_type obj_procid = obj->processor_id();
377  // We'd better be completely partitioned by now
378  libmesh_assert_not_equal_to (obj_procid, DofObject::invalid_processor_id);
379  ghost_objects_from_proc[obj_procid]++;
380  }
381  }
382 
383  // Request sets to send to each processor
384  std::map<processor_id_type, std::vector<dof_id_type>>
385  requested_ids;
386 
387  // We know how many of our objects live on each processor, so
388  // reserve() space for requests from each.
389  for (auto [p, size] : ghost_objects_from_proc)
390  {
391  if (p != this->processor_id())
392  requested_ids[p].reserve(size);
393  }
394 
395  for (it = objects_begin; it != objects_end; ++it)
396  {
397  DofObject * obj = *it;
398  if (obj->processor_id() != DofObject::invalid_processor_id)
399  requested_ids[obj->processor_id()].push_back(obj->id());
400  }
401 #ifdef DEBUG
402  for (auto p : make_range(this->n_processors()))
403  {
404  if (ghost_objects_from_proc.count(p))
405  libmesh_assert_equal_to (requested_ids[p].size(), ghost_objects_from_proc[p]);
406  else
407  libmesh_assert(!requested_ids.count(p));
408  }
409 #endif
410 
411  typedef std::vector<dof_id_type> datum;
412 
413  auto gather_functor =
414  [this, &mesh, &objects]
416  const std::vector<dof_id_type> & ids,
417  std::vector<datum> & data)
418  {
419  // Fill those requests
420  const unsigned int
421  sys_num = this->sys_number(),
422  n_var_groups = this->n_variable_groups();
423 
424  const std::size_t query_size = ids.size();
425 
426  data.resize(query_size);
427  for (auto & d : data)
428  d.resize(2 * n_var_groups);
429 
430  for (std::size_t i=0; i != query_size; ++i)
431  {
432  DofObject * requested = (this->*objects)(mesh, ids[i]);
433  libmesh_assert(requested);
434  libmesh_assert_equal_to (requested->processor_id(), this->processor_id());
435  libmesh_assert_equal_to (requested->n_var_groups(sys_num), n_var_groups);
436  for (unsigned int vg=0; vg != n_var_groups; ++vg)
437  {
438  unsigned int n_comp_g =
439  requested->n_comp_group(sys_num, vg);
440  data[i][vg] = n_comp_g;
441  dof_id_type my_first_dof = n_comp_g ?
442  requested->vg_dof_base(sys_num, vg) : 0;
443  libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
444  data[i][n_var_groups+vg] = my_first_dof;
445  }
446  }
447  };
448 
449  auto action_functor =
450  [this, &mesh, &objects]
451  (processor_id_type libmesh_dbg_var(pid),
452  const std::vector<dof_id_type> & ids,
453  const std::vector<datum> & data)
454  {
455  const unsigned int
456  sys_num = this->sys_number(),
457  n_var_groups = this->n_variable_groups();
458 
459  // Copy the id changes we've now been informed of
460  for (auto i : index_range(ids))
461  {
462  DofObject * requested = (this->*objects)(mesh, ids[i]);
463  libmesh_assert(requested);
464  libmesh_assert_equal_to (requested->processor_id(), pid);
465  for (unsigned int vg=0; vg != n_var_groups; ++vg)
466  {
467  unsigned int n_comp_g =
468  cast_int<unsigned int>(data[i][vg]);
469  requested->set_n_comp_group(sys_num, vg, n_comp_g);
470  if (n_comp_g)
471  {
472  dof_id_type my_first_dof = data[i][n_var_groups+vg];
473  libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
474  requested->set_vg_dof_base
475  (sys_num, vg, my_first_dof);
476  }
477  }
478  }
479  };
480 
481  datum * ex = nullptr;
482  Parallel::pull_parallel_vector_data
483  (this->comm(), requested_ids, gather_functor, action_functor, ex);
484 
485 #ifdef DEBUG
486  // Double check for invalid dofs
487  for (it = objects_begin; it != objects_end; ++it)
488  {
489  DofObject * obj = *it;
490  libmesh_assert (obj);
491  unsigned int num_variables = obj->n_vars(this->sys_number());
492  for (unsigned int v=0; v != num_variables; ++v)
493  {
494  unsigned int n_comp =
495  obj->n_comp(this->sys_number(), v);
496  dof_id_type my_first_dof = n_comp ?
497  obj->dof_number(this->sys_number(), v, 0) : 0;
498  libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
499  }
500  }
501 #endif
502 }
uint8_t processor_id_type
Definition: id_types.h:104
static const 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:488
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:477
unsigned int n_variable_groups() const
Definition: dof_map.h:613
unsigned int sys_number() const
Definition: dof_map.h:2093
uint8_t dof_id_type
Definition: id_types.h:67
void libMesh::DofMap::set_verify_dirichlet_bc_consistency ( bool  val)

Set the _verify_dirichlet_bc_consistency flag.

在文件 dof_map.C1754 行定义.

参考 _verify_dirichlet_bc_consistency.

1755 {
1757 }
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:2086
void libMesh::DofMap::should_p_refine ( unsigned int  g,
bool  p_refine 
)
inline

Describe whether the given variable group should be p-refined.

If this API is not called with false, the default is to p-refine

在文件 dof_map.h2319 行定义.

参考 _dont_p_refine , 以及 libMesh::libmesh_ignore().

2320 {
2321 #ifdef LIBMESH_ENABLE_AMR
2322  if (p_refine)
2323  {
2324  auto it = _dont_p_refine.find(g);
2325  if (it != _dont_p_refine.end())
2326  _dont_p_refine.erase(it);
2327  }
2328  else
2329  _dont_p_refine.insert(g);
2330 #else
2331  libmesh_ignore(g, p_refine);
2332 #endif
2333 }
void libmesh_ignore(const Args &...)
std::unordered_set< unsigned int > _dont_p_refine
A container of variable groups that we should not p-refine.
Definition: dof_map.h:2022
bool libMesh::DofMap::should_p_refine ( unsigned int  g) const
inline

Whether the given variable group should be p-refined.

在文件 dof_map.h2336 行定义.

参考 _dont_p_refine , 以及 libMesh::libmesh_ignore().

2337 {
2338 #ifdef LIBMESH_ENABLE_AMR
2339  return !_dont_p_refine.count(g);
2340 #else
2341  libmesh_ignore(g);
2342  return false;
2343 #endif
2344 }
void libmesh_ignore(const Args &...)
std::unordered_set< unsigned int > _dont_p_refine
A container of variable groups that we should not p-refine.
Definition: dof_map.h:2022
void libMesh::DofMap::should_p_refine ( FEFamily  ,
bool   
)
delete
void libMesh::DofMap::should_p_refine ( Order  ,
bool   
)
delete
bool libMesh::DofMap::should_p_refine ( FEFamily  ) const
delete
bool libMesh::DofMap::should_p_refine ( Order  ) const
delete
bool libMesh::DofMap::should_p_refine_var ( unsigned int  var) const
inline

Whether the given variable should be p-refined.

在文件 dof_map.h2354 行定义.

参考 _dont_p_refine, libMesh::libmesh_ignore() , 以及 var_group_from_var_number().

2355 {
2356 #ifdef LIBMESH_ENABLE_AMR
2357  const auto vg = this->var_group_from_var_number(var);
2358  return !_dont_p_refine.count(vg);
2359 #else
2360  libmesh_ignore(var);
2361  return false;
2362 #endif
2363 }
unsigned int var_group_from_var_number(unsigned int var_num) const
Definition: dof_map.h:2347
void libmesh_ignore(const Args &...)
std::unordered_set< unsigned int > _dont_p_refine
A container of variable groups that we should not p-refine.
Definition: dof_map.h:2022
void libMesh::DofMap::stash_dof_constraints ( )
inline

在文件 dof_map.h1025 行定义.

参考 _dof_constraints , 以及 _stashed_dof_constraints.

1026  {
1027  libmesh_assert(_stashed_dof_constraints.empty());
1029  }
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
DofConstraints _stashed_dof_constraints
Definition: dof_map.h:2030
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.

注解
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.

在文件 dof_map.h1049 行定义.

参考 _dof_constraints , 以及 _stashed_dof_constraints.

1050  {
1052  }
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
DofConstraints _stashed_dof_constraints
Definition: dof_map.h:2030
unsigned int libMesh::DofMap::sys_number ( ) const
inline
void libMesh::DofMap::unstash_dof_constraints ( )
inline

在文件 dof_map.h1031 行定义.

参考 _dof_constraints , 以及 _stashed_dof_constraints.

1032  {
1033  libmesh_assert(_dof_constraints.empty());
1035  }
DofConstraints _dof_constraints
Data structure containing DOF constraints.
Definition: dof_map.h:2030
DofConstraints _stashed_dof_constraints
Definition: dof_map.h:2030
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.

在文件 dof_map.C307 行定义.

参考 _sp, libMesh::SparseMatrix< T >::attach_dof_map(), libMesh::SparseMatrix< T >::attach_sparsity_pattern(), computed_sparsity_already(), libMesh::SparseMatrix< T >::need_full_sparsity_pattern(), need_full_sparsity_pattern , 以及 libMesh::SparseMatrix< T >::update_sparsity_pattern().

参考自 attach_matrix().

308 {
309  matrix.attach_dof_map (*this);
310 
311  // If we've already computed sparsity, then it's too late
312  // to wait for "compute_sparsity" to help with sparse matrix
313  // initialization, and we need to handle this matrix individually
314  if (this->computed_sparsity_already())
315  {
316  libmesh_assert(_sp.get());
317 
318  if (matrix.need_full_sparsity_pattern())
319  {
320  // We'd better have already computed the full sparsity
321  // pattern if we need it here
322  libmesh_assert(need_full_sparsity_pattern);
323 
324  matrix.update_sparsity_pattern (_sp->get_sparsity_pattern());
325  }
326 
327  matrix.attach_sparsity_pattern(*_sp);
328  }
329 }
std::unique_ptr< SparsityPattern::Build > _sp
The sparsity pattern of the global matrix.
Definition: dof_map.h:1983
bool computed_sparsity_already() const
Returns true iff a sparsity pattern has already been computed.
Definition: dof_map.C:296
bool need_full_sparsity_pattern
Default false; set to true if any attached matrix requires a full sparsity pattern.
Definition: dof_map.h:1976
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.

在文件 dof_map.C1760 行定义.

参考 _implicit_neighbor_dofs, _implicit_neighbor_dofs_initialized, libMesh::command_line_next(), n_variables(), libMesh::on_command_line() , 以及 variable_type().

参考自 build_sparsity(), clear() , 以及 reinit().

1761 {
1762  // If we were asked on the command line, then we need to
1763  // include sensitivities between neighbor degrees of freedom
1764  bool implicit_neighbor_dofs =
1765  libMesh::on_command_line ("--implicit-neighbor-dofs");
1766 
1767  // If the user specifies --implicit-neighbor-dofs 0, then
1768  // presumably he knows what he is doing and we won't try to
1769  // automatically turn it on even when all the variables are
1770  // discontinuous.
1771  if (implicit_neighbor_dofs)
1772  {
1773  // No flag provided defaults to 'true'
1774  int flag = 1;
1775  flag = libMesh::command_line_next ("--implicit-neighbor-dofs", flag);
1776 
1777  if (!flag)
1778  {
1779  // The user said --implicit-neighbor-dofs 0, so he knows
1780  // what he is doing and really doesn't want it.
1781  return false;
1782  }
1783  }
1784 
1785  // Possibly override the commandline option, if set_implicit_neighbor_dofs
1786  // has been called.
1788  {
1789  implicit_neighbor_dofs = _implicit_neighbor_dofs;
1790 
1791  // Again, if the user explicitly says implicit_neighbor_dofs = false,
1792  // then we return here.
1793  if (!implicit_neighbor_dofs)
1794  return false;
1795  }
1796 
1797  // Look at all the variables in this system. If every one is
1798  // discontinuous then the user must be doing DG/FVM, so be nice
1799  // and force implicit_neighbor_dofs=true.
1800  {
1801  bool all_discontinuous_dofs = true;
1802 
1803  for (auto var : make_range(this->n_variables()))
1804  if (FEInterface::get_continuity(this->variable_type(var)) != DISCONTINUOUS)
1805  all_discontinuous_dofs = false;
1806 
1807  if (all_discontinuous_dofs)
1808  implicit_neighbor_dofs = true;
1809  }
1810 
1811  return implicit_neighbor_dofs;
1812 }
T command_line_next(std::string name, T value)
Use GetPot&#39;s search()/next() functions to get following arguments from the command line...
Definition: libmesh.C:937
bool _implicit_neighbor_dofs_initialized
Bools to indicate if we override the –implicit_neighbor_dofs commandline options. ...
Definition: dof_map.h:2073
bool _implicit_neighbor_dofs
Definition: dof_map.h:2074
const FEType & variable_type(const unsigned int c) const
Definition: dof_map.h:2141
unsigned int n_variables() const
Definition: dof_map.h:621
bool on_command_line(std::string arg)
Definition: libmesh.C:872
unsigned int libMesh::DofMap::var_group_from_var_number ( unsigned int  var_num) const
inline
返回
The variable group number that the provided variable number belongs to

在文件 dof_map.h2347 行定义.

参考 _var_to_vg , 以及 n_variables().

参考自 should_p_refine_var().

2348 {
2349  libmesh_assert(var_num < n_variables());
2350  return libmesh_map_find(_var_to_vg, var_num);
2351 }
std::unordered_map< unsigned int, unsigned int > _var_to_vg
A map from variable number to variable group number.
Definition: dof_map.h:1854
unsigned int n_variables() const
Definition: dof_map.h:621
const Variable & libMesh::DofMap::variable ( const unsigned int  c) const
inline
返回
The variable description object for variable c.

在文件 dof_map.h2111 行定义.

参考 _variables.

参考自 distribute_dofs(), local_variable_indices() , 以及 SCALAR_dof_indices().

2112 {
2113  libmesh_assert_less (c, _variables.size());
2114 
2115  return _variables[c];
2116 }
std::vector< Variable > _variables
The finite element type for each variable.
Definition: dof_map.h:1839
const VariableGroup & libMesh::DofMap::variable_group ( const unsigned int  c) const
inline
返回
The VariableGroup description object for group g.

在文件 dof_map.h2101 行定义.

参考 _variable_groups.

参考自 _dof_indices(), _node_dof_indices(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), distribute_scalar_dofs(), dof_indices(), old_dof_indices() , 以及 reinit().

2102 {
2103  libmesh_assert_less (g, _variable_groups.size());
2104 
2105  return _variable_groups[g];
2106 }
std::vector< VariableGroup > _variable_groups
The finite element type for each variable group.
Definition: dof_map.h:1844
Order libMesh::DofMap::variable_group_order ( const unsigned int  vg) const
inline
返回
The approximation order for VariableGroup vg.

在文件 dof_map.h2131 行定义.

参考 _variable_groups.

2132 {
2133  libmesh_assert_less (vg, _variable_groups.size());
2134 
2135  return _variable_groups[vg].type().order;
2136 }
std::vector< VariableGroup > _variable_groups
The finite element type for each variable group.
Definition: dof_map.h:1844
const FEType & libMesh::DofMap::variable_group_type ( const unsigned int  vg) const
inline
返回
The finite element type for VariableGroup vg.

在文件 dof_map.h2151 行定义.

参考 _variable_groups.

2152 {
2153  libmesh_assert_less (vg, _variable_groups.size());
2154 
2155  return _variable_groups[vg].type();
2156 }
std::vector< VariableGroup > _variable_groups
The finite element type for each variable group.
Definition: dof_map.h:1844
Order libMesh::DofMap::variable_order ( const unsigned int  c) const
inline
返回
The approximation order for variable c.

在文件 dof_map.h2121 行定义.

参考 _variables.

2122 {
2123  libmesh_assert_less (c, _variables.size());
2124 
2125  return _variables[c].type().order;
2126 }
std::vector< Variable > _variables
The finite element type for each variable.
Definition: dof_map.h:1839
const FEType & libMesh::DofMap::variable_type ( const unsigned int  c) const
inline
返回
The finite element type for variable c.

在文件 dof_map.h2141 行定义.

参考 _variables.

参考自 constrain_p_dofs(), local_variable_indices(), process_mesh_constraint_rows() , 以及 use_coupled_neighbor_dofs().

2142 {
2143  libmesh_assert_less (c, _variables.size());
2144 
2145  return _variables[c].type();
2146 }
std::vector< Variable > _variables
The finite element type for each variable.
Definition: dof_map.h:1839

友元及相关函数文档

friend class SparsityPattern::Build
friend

在文件 dof_map.h2067 行定义.

类成员变量说明

AdjointDofConstraintValues libMesh::DofMap::_adjoint_constraint_values
private
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.

在文件 dof_map.h2064 行定义.

参考自 add_adjoint_dirichlet_boundary(), create_dof_constraints(), get_adjoint_dirichlet_boundaries(), get_local_constraints(), has_adjoint_dirichlet_boundaries() , 以及 remove_adjoint_dirichlet_boundary().

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

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

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

在文件 dof_map.h1951 行定义.

参考自 add_algebraic_ghosting_functor(), algebraic_ghosting_functors_begin(), algebraic_ghosting_functors_end(), clear(), distribute_dofs() , 以及 remove_algebraic_ghosting_functor().

AugmentSendList* libMesh::DofMap::_augment_send_list
private

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

在文件 dof_map.h1915 行定义.

参考自 attach_extra_send_list_object() , 以及 prepare_send_list().

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

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

在文件 dof_map.h1898 行定义.

参考自 attach_extra_sparsity_object() , 以及 build_sparsity().

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.

在文件 dof_map.h1834 行定义.

参考自 compute_sparsity(), constrained_sparsity_construction() , 以及 set_constrained_sparsity_construction().

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

Actually holds the data.

在文件 reference_counter.h124 行定义.

参考自 libMesh::ReferenceCounter::get_info().

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

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

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

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

在文件 dof_map.h1964 行定义.

参考自 add_coupling_functor(), build_sparsity(), clear(), coupling_functors_begin(), coupling_functors_end(), distribute_dofs() , 以及 remove_coupling_functor().

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.

在文件 dof_map.h1933 行定义.

参考自 clear(), default_coupling(), DofMap(), reinit() , 以及 ~DofMap().

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.

在文件 dof_map.h1941 行定义.

参考自 clear(), default_algebraic_ghosting(), DofMap() , 以及 ~DofMap().

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.

在文件 dof_map.h2058 行定义.

参考自 add_dirichlet_boundary(), create_dof_constraints(), get_dirichlet_boundaries() , 以及 remove_dirichlet_boundary().

DofConstraints libMesh::DofMap::_dof_constraints
private
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.

在文件 dof_map.h1589 行定义.

参考自 build_sparsity(), clear() , 以及 reinit().

std::unordered_set<unsigned int> libMesh::DofMap::_dont_p_refine
private

A container of variable groups that we should not p-refine.

在文件 dof_map.h2022 行定义.

参考自 _dof_indices(), _node_dof_indices(), old_dof_indices(), reinit(), should_p_refine() , 以及 should_p_refine_var().

bool libMesh::ReferenceCounter::_enable_print_counter = true
staticprotectedinherited

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

在文件 reference_counter.h143 行定义.

参考自 libMesh::ReferenceCounter::disable_print_counter_info(), libMesh::ReferenceCounter::enable_print_counter_info() , 以及 libMesh::ReferenceCounter::print_info().

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

Last DOF index (plus 1) on processor p.

在文件 dof_map.h1881 行定义.

参考自 clear(), distribute_dofs(), dof_owner(), end_dof(), gather_constraints(), n_dofs_on_processor() , 以及 scatter_constraints().

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

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

在文件 dof_map.h2011 行定义.

参考自 clear(), distribute_dofs() , 以及 end_old_dof().

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.

在文件 dof_map.h1828 行定义.

参考自 process_constraints() , 以及 set_error_on_constraint_loop().

void* libMesh::DofMap::_extra_send_list_context
private

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

在文件 dof_map.h1925 行定义.

参考自 attach_extra_send_list_function() , 以及 prepare_send_list().

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.

在文件 dof_map.h1920 行定义.

参考自 attach_extra_send_list_function() , 以及 prepare_send_list().

void* libMesh::DofMap::_extra_sparsity_context
private

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

在文件 dof_map.h1910 行定义.

参考自 attach_extra_sparsity_function() , 以及 build_sparsity().

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.

在文件 dof_map.h1903 行定义.

参考自 attach_extra_sparsity_function() , 以及 build_sparsity().

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

First DOF index on processor p.

在文件 dof_map.h1876 行定义.

参考自 clear(), distribute_dofs(), first_dof() , 以及 n_dofs_on_processor().

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

First old DOF index on processor p.

在文件 dof_map.h2006 行定义.

参考自 clear(), distribute_dofs() , 以及 first_old_dof().

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.

在文件 dof_map.h2017 行定义.

参考自 clear(), distribute_dofs() , 以及 SCALAR_dof_indices().

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.

在文件 dof_map.h1887 行定义.

参考自 clear(), distribute_dofs() , 以及 SCALAR_dof_indices().

bool libMesh::DofMap::_implicit_neighbor_dofs
private

在文件 dof_map.h2074 行定义.

参考自 set_implicit_neighbor_dofs() , 以及 use_coupled_neighbor_dofs().

bool libMesh::DofMap::_implicit_neighbor_dofs_initialized
private

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

在文件 dof_map.h2073 行定义.

参考自 set_implicit_neighbor_dofs() , 以及 use_coupled_neighbor_dofs().

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.

在文件 dof_map.h1871 行定义.

参考自 attach_matrix(), clear(), compute_sparsity(), DofMap(), get_info() , 以及 is_attached().

MeshBase& libMesh::DofMap::_mesh
private
Threads::spin_mutex libMesh::ReferenceCounter::_mutex
staticprotectedinherited

Mutual exclusion object to enable thread-safe reference counting.

在文件 reference_counter.h137 行定义.

dof_id_type libMesh::DofMap::_n_dfs
private

Total number of degrees of freedom.

在文件 dof_map.h1988 行定义.

参考自 clear(), distribute_dofs() , 以及 n_dofs().

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

The number of objects.

Print the reference count information when the number returns to 0.

在文件 reference_counter.h132 行定义.

参考自 libMesh::ReferenceCounter::n_objects(), libMesh::ReferenceCounter::ReferenceCounter() , 以及 libMesh::ReferenceCounter::~ReferenceCounter().

dof_id_type libMesh::DofMap::_n_old_dfs
private

Total number of degrees of freedom on old dof objects.

在文件 dof_map.h2001 行定义.

参考自 clear(), distribute_dofs() , 以及 n_old_dofs().

dof_id_type libMesh::DofMap::_n_SCALAR_dofs
private

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

在文件 dof_map.h1994 行定义.

参考自 distribute_scalar_dofs(), n_SCALAR_dofs() , 以及 reinit().

NodeConstraints libMesh::DofMap::_node_constraints
private
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.

在文件 dof_map.h2050 行定义.

参考自 add_periodic_boundary(), create_dof_constraints(), DofMap(), get_periodic_boundaries(), is_periodic_boundary() , 以及 process_mesh_constraint_rows().

DofConstraintValueMap libMesh::DofMap::_primal_constraint_values
private
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.

在文件 dof_map.h1893 行定义.

参考自 add_constraints_to_send_list(), add_neighbors_to_send_list(), clear_send_list(), get_send_list(), prepare_send_list() , 以及 semilocal_index().

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.

在文件 dof_map.h1970 行定义.

参考自 add_algebraic_ghosting_functor(), add_coupling_functor(), clear(), remove_algebraic_ghosting_functor() , 以及 remove_coupling_functor().

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.

在文件 dof_map.h1983 行定义.

参考自 clear_sparsity(), compute_sparsity(), computed_sparsity_already(), get_info(), get_n_nz(), get_n_oz(), get_sparsity_pattern() , 以及 update_sparsity_pattern().

DofConstraints libMesh::DofMap::_stashed_dof_constraints
private
const unsigned int libMesh::DofMap::_sys_number
private

The number of the system we manage DOFs for.

在文件 dof_map.h1859 行定义.

参考自 sys_number().

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

A map from variable number to variable group number.

在文件 dof_map.h1854 行定义.

参考自 add_variable_group(), clear() , 以及 var_group_from_var_number().

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

The variable group number for each variable.

在文件 dof_map.h1849 行定义.

参考自 add_variable_group(), clear() , 以及 dof_indices().

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

The finite element type for each variable group.

在文件 dof_map.h1844 行定义.

参考自 add_variable_group(), clear(), n_variable_groups(), variable_group(), variable_group_order() , 以及 variable_group_type().

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

The finite element type for each variable.

在文件 dof_map.h1839 行定义.

参考自 add_variable_group(), clear(), n_variables(), variable(), variable_order() , 以及 variable_type().

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.

在文件 dof_map.h2086 行定义.

参考自 create_dof_constraints() , 以及 set_verify_dirichlet_bc_consistency().

bool libMesh::DofMap::need_full_sparsity_pattern
private

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

在文件 dof_map.h1976 行定义.

参考自 attach_matrix(), build_sparsity(), clear(), compute_sparsity() , 以及 update_sparsity_pattern().


该类的文档由以下文件生成: