libMesh::DofMap Class Reference
#include <dof_map.h>

Classes | |
| class | AugmentSendList |
| class | AugmentSparsityPattern |
Public Member Functions | |
| DofMap (const unsigned int sys_number) | |
| ~DofMap () | |
| void | attach_matrix (SparseMatrix< Number > &matrix) |
| bool | is_attached (SparseMatrix< Number > &matrix) |
| void | distribute_dofs (MeshBase &) |
| void | compute_sparsity (const MeshBase &) |
| void | clear_sparsity () |
| void | attach_extra_sparsity_object (DofMap::AugmentSparsityPattern &asp) |
| void | attach_extra_sparsity_function (void(*func)(SparsityPattern::Graph &sparsity, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *), void *context=NULL) |
| void | attach_extra_send_list_object (DofMap::AugmentSendList &asl) |
| void | attach_extra_send_list_function (void(*func)(std::vector< dof_id_type > &, void *), void *context=NULL) |
| void | prepare_send_list () |
| const std::vector< dof_id_type > & | get_send_list () const |
| const std::vector< dof_id_type > & | get_n_nz () const |
| const std::vector< dof_id_type > & | get_n_oz () const |
| void | add_variable_group (const VariableGroup &var_group) |
| const VariableGroup & | variable_group (const unsigned int c) const |
| const Variable & | variable (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 |
| 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=libMesh::processor_id()) const |
| dof_id_type | first_old_dof (const processor_id_type proc=libMesh::processor_id()) const |
| dof_id_type | last_dof (const processor_id_type proc=libMesh::processor_id()) const |
| dof_id_type | end_dof (const processor_id_type proc=libMesh::processor_id()) const |
| dof_id_type | end_old_dof (const processor_id_type proc=libMesh::processor_id()) const |
| void | dof_indices (const Elem *const elem, std::vector< dof_id_type > &di, const unsigned int vn=libMesh::invalid_uint) const |
| void | SCALAR_dof_indices (std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const |
| bool | all_semilocal_indices (const std::vector< dof_id_type > &dof_indices) const |
| bool | use_coupled_neighbor_dofs (const MeshBase &mesh) const |
| void | extract_local_vector (const NumericVector< Number > &Ug, const std::vector< dof_id_type > &dof_indices, DenseVectorBase< Number > &Ue) const |
| dof_id_type | n_constrained_dofs () const |
| dof_id_type | n_local_constrained_dofs () const |
| dof_id_type | n_constrained_nodes () const |
| void | create_dof_constraints (const MeshBase &, Real time=0) |
| void | allgather_recursive_constraints (MeshBase &) |
| void | scatter_constraints (MeshBase &) |
| void | process_constraints (MeshBase &) |
| void | add_constraint_row (const dof_id_type dof_number, const DofConstraintRow &constraint_row, const Number constraint_rhs, const bool forbid_constraint_overwrite) |
| void | add_constraint_row (const dof_id_type dof_number, const DofConstraintRow &constraint_row, const bool forbid_constraint_overwrite=true) |
| DofConstraints::const_iterator | constraint_rows_begin () const |
| DofConstraints::const_iterator | constraint_rows_end () const |
| 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 | is_constrained_node (const Node *node) const |
| void | print_dof_constraints (std::ostream &os=libMesh::out, bool print_nonlocal=false) const |
| std::string | get_local_constraints (bool print_nonlocal=false) const |
| std::pair< Real, Real > | max_constraint_error (const System &system, NumericVector< Number > *v=NULL) const |
| void | constrain_element_matrix (DenseMatrix< Number > &matrix, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const |
| void | constrain_element_matrix (DenseMatrix< Number > &matrix, std::vector< dof_id_type > &row_dofs, std::vector< dof_id_type > &col_dofs, bool asymmetric_constraint_rows=true) const |
| void | constrain_element_vector (DenseVector< Number > &rhs, std::vector< dof_id_type > &dofs, bool asymmetric_constraint_rows=true) const |
| void | constrain_element_matrix_and_vector (DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const |
| void | heterogenously_constrain_element_matrix_and_vector (DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const |
| void | constrain_element_dyad_matrix (DenseVector< Number > &v, DenseVector< Number > &w, std::vector< dof_id_type > &row_dofs, bool asymmetric_constraint_rows=true) const |
| void | constrain_nothing (std::vector< dof_id_type > &dofs) const |
| void | enforce_constraints_exactly (const System &system, NumericVector< Number > *v=NULL, bool homogeneous=false) const |
| void | add_periodic_boundary (const PeriodicBoundaryBase &periodic_boundary) |
| void | add_periodic_boundary (const PeriodicBoundaryBase &boundary, const PeriodicBoundaryBase &inverse_boundary) |
| bool | is_periodic_boundary (const boundary_id_type boundaryid) const |
| PeriodicBoundaries * | get_periodic_boundaries () |
| void | add_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary) |
| void | remove_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary) |
| DirichletBoundaries * | get_dirichlet_boundaries () |
| void | old_dof_indices (const Elem *const elem, std::vector< dof_id_type > &di, const unsigned int vn=libMesh::invalid_uint) const |
| dof_id_type | n_old_dofs () const |
| void | constrain_p_dofs (unsigned int var, const Elem *elem, unsigned int s, unsigned int p) |
| void | reinit (MeshBase &mesh) |
| void | clear () |
| void | print_info (std::ostream &os=libMesh::out) const |
| std::string | get_info () const |
| unsigned int | sys_number () const |
Static Public Member Functions | |
| static std::string | get_info () |
| static void | print_info (std::ostream &out=libMesh::out) |
| static unsigned int | n_objects () |
| static void | enable_print_counter_info () |
| static void | disable_print_counter_info () |
Public Attributes | |
| CouplingMatrix * | _dof_coupling |
Protected Types | |
| typedef std::map< std::string, std::pair< unsigned int, unsigned int > > | Counts |
Protected Member Functions | |
| void | increment_constructor_count (const std::string &name) |
| void | increment_destructor_count (const std::string &name) |
Static Protected Attributes | |
| static Counts | _counts |
| static Threads::atomic < unsigned int > | _n_objects |
| static Threads::spin_mutex | _mutex |
| static bool | _enable_print_counter = true |
Private Types | |
| typedef DofObject *(DofMap::* | dofobject_accessor )(MeshBase &mesh, dof_id_type i) const |
Private Member Functions | |
| AutoPtr< SparsityPattern::Build > | build_sparsity (const MeshBase &mesh) const |
| void | invalidate_dofs (MeshBase &mesh) const |
| DofObject * | node_ptr (MeshBase &mesh, dof_id_type i) const |
| DofObject * | elem_ptr (MeshBase &mesh, dof_id_type i) const |
| template<typename iterator_type > | |
| void | set_nonlocal_dof_objects (iterator_type objects_begin, iterator_type objects_end, MeshBase &mesh, dofobject_accessor objects) |
| void | distribute_local_dofs_var_major (dof_id_type &next_free_dof, MeshBase &mesh) |
| void | distribute_local_dofs_node_major (dof_id_type &next_free_dof, MeshBase &mesh) |
| void | add_neighbors_to_send_list (MeshBase &mesh) |
| void | build_constraint_matrix (DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const |
| void | build_constraint_matrix_and_vector (DenseMatrix< Number > &C, DenseVector< Number > &H, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const |
| void | find_connected_dofs (std::vector< dof_id_type > &elem_dofs) const |
| void | find_connected_dof_objects (std::vector< const DofObject * > &objs) const |
| void | add_constraints_to_send_list () |
Private Attributes | |
| std::vector< Variable > | _variables |
| std::vector< VariableGroup > | _variable_groups |
| const unsigned int | _sys_number |
| std::vector< SparseMatrix < Number > * > | _matrices |
| std::vector< dof_id_type > | _first_df |
| std::vector< dof_id_type > | _end_df |
| std::vector< dof_id_type > | _send_list |
| AugmentSparsityPattern * | _augment_sparsity_pattern |
| void(* | _extra_sparsity_function )(SparsityPattern::Graph &, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *) |
| void * | _extra_sparsity_context |
| AugmentSendList * | _augment_send_list |
| void(* | _extra_send_list_function )(std::vector< dof_id_type > &, void *) |
| void * | _extra_send_list_context |
| bool | need_full_sparsity_pattern |
| AutoPtr< SparsityPattern::Build > | _sp |
| std::vector< dof_id_type > * | _n_nz |
| std::vector< dof_id_type > * | _n_oz |
| dof_id_type | _n_dfs |
| dof_id_type | _n_SCALAR_dofs |
| dof_id_type | _n_old_dfs |
| std::vector< dof_id_type > | _first_old_df |
| std::vector< dof_id_type > | _end_old_df |
| DofConstraints | _dof_constraints |
| NodeConstraints | _node_constraints |
| PeriodicBoundaries * | _periodic_boundaries |
| DirichletBoundaries * | _dirichlet_boundaries |
Friends | |
| class | SparsityPattern::Build |
Detailed Description
This class handles the numbering of degrees of freedom on a mesh. For systems of equations the class supports a fixed number of variables. The degrees of freedom are numbered such that sequential, contiguous blocks correspond to distinct subdomains. This is so that the resulting data structures will work well with parallel linear algebra packages.
Definition at line 142 of file dof_map.h.
Member Typedef Documentation
typedef std::map<std::string, std::pair<unsigned int, unsigned int> > libMesh::ReferenceCounter::Counts [protected, inherited] |
Data structure to log the information. The log is identified by the class name.
Definition at line 113 of file reference_counter.h.
typedef DofObject*(DofMap::* libMesh::DofMap::dofobject_accessor)(MeshBase &mesh, dof_id_type i) const [private] |
Constructor & Destructor Documentation
| libMesh::DofMap::DofMap | ( | const unsigned int | sys_number | ) | [explicit] |
Constructor. Requires the number of the system for which we will be numbering degrees of freedom.
Definition at line 128 of file dof_map.C.
References _matrices.
00128 : 00129 _dof_coupling(NULL), 00130 _variables(), 00131 _variable_groups(), 00132 _sys_number(number), 00133 _matrices(), 00134 _first_df(), 00135 _end_df(), 00136 _send_list(), 00137 _augment_sparsity_pattern(NULL), 00138 _extra_sparsity_function(NULL), 00139 _extra_sparsity_context(NULL), 00140 _augment_send_list(NULL), 00141 _extra_send_list_function(NULL), 00142 _extra_send_list_context(NULL), 00143 need_full_sparsity_pattern(false), 00144 _n_nz(NULL), 00145 _n_oz(NULL), 00146 _n_dfs(0), 00147 _n_SCALAR_dofs(0) 00148 #ifdef LIBMESH_ENABLE_AMR 00149 , _n_old_dfs(0), 00150 _first_old_df(), 00151 _end_old_df() 00152 #endif 00153 #ifdef LIBMESH_ENABLE_CONSTRAINTS 00154 , _dof_constraints() 00155 #endif 00156 #ifdef LIBMESH_ENABLE_PERIODIC 00157 , _periodic_boundaries(new PeriodicBoundaries) 00158 #endif 00159 #ifdef LIBMESH_ENABLE_DIRICHLET 00160 , _dirichlet_boundaries(new DirichletBoundaries) 00161 #endif 00162 { 00163 _matrices.clear(); 00164 }
| libMesh::DofMap::~DofMap | ( | ) |
Destructor.
Definition at line 169 of file dof_map.C.
References _dirichlet_boundaries, _periodic_boundaries, and clear().
00170 { 00171 this->clear(); 00172 #ifdef LIBMESH_ENABLE_PERIODIC 00173 delete _periodic_boundaries; 00174 #endif 00175 #ifdef LIBMESH_ENABLE_DIRICHLET 00176 delete _dirichlet_boundaries; 00177 #endif 00178 }
Member Function Documentation
| void libMesh::DofMap::add_constraint_row | ( | const dof_id_type | dof_number, | |
| const DofConstraintRow & | constraint_row, | |||
| const bool | forbid_constraint_overwrite = true | |||
| ) | [inline] |
Adds a copy of the user-defined row to the constraint matrix, using a homogeneous right-hand-side for the constraint equation. By default, produces an error if the DOF was already constrained.
Definition at line 550 of file dof_map.h.
References add_constraint_row().
Referenced by add_constraint_row().
00553 { add_constraint_row(dof_number, constraint_row, 0., forbid_constraint_overwrite); }
| void libMesh::DofMap::add_constraint_row | ( | const dof_id_type | dof_number, | |
| const DofConstraintRow & | constraint_row, | |||
| const Number | constraint_rhs, | |||
| const bool | forbid_constraint_overwrite | |||
| ) |
Adds a copy of the user-defined row to the constraint matrix, using an inhomogeneous right-hand-side for the constraint equation.
Definition at line 980 of file dof_map_constraints.C.
References _dof_constraints, libMesh::err, and is_constrained_dof().
00984 { 00985 // Optionally allow the user to overwrite constraints. Defaults to false. 00986 if (forbid_constraint_overwrite) 00987 if (this->is_constrained_dof(dof_number)) 00988 { 00989 libMesh::err << "ERROR: DOF " << dof_number << " was already constrained!" 00990 << std::endl; 00991 libmesh_error(); 00992 } 00993 00994 std::pair<dof_id_type, std::pair<DofConstraintRow,Number> > kv(dof_number, std::make_pair(constraint_row, constraint_rhs)); 00995 00996 _dof_constraints.insert(kv); 00997 }
| void libMesh::DofMap::add_constraints_to_send_list | ( | ) | [private] |
Adds entries to the _send_list vector corresponding to DoFs which are dependencies for constraint equations on the current processor.
Definition at line 2961 of file dof_map_constraints.C.
References _dof_constraints, _send_list, libMesh::CommWorld, end_dof(), first_dof(), libMesh::Parallel::Communicator::max(), and libMesh::n_processors().
Referenced by process_constraints().
02962 { 02963 // This function must be run on all processors at once 02964 parallel_only(); 02965 02966 // Return immediately if there's nothing to gather 02967 if (libMesh::n_processors() == 1) 02968 return; 02969 02970 // We might get to return immediately if none of the processors 02971 // found any constraints 02972 unsigned int has_constraints = !_dof_constraints.empty(); 02973 CommWorld.max(has_constraints); 02974 if (!has_constraints) 02975 return; 02976 02977 for (DofConstraints::iterator i = _dof_constraints.begin(); 02978 i != _dof_constraints.end(); ++i) 02979 { 02980 dof_id_type constrained_dof = i->first; 02981 02982 // We only need the dependencies of our own constrained dofs 02983 if (constrained_dof < this->first_dof() || 02984 constrained_dof >= this->end_dof()) 02985 continue; 02986 02987 DofConstraintRow& constraint_row = i->second.first; 02988 for (DofConstraintRow::const_iterator 02989 j=constraint_row.begin(); j != constraint_row.end(); 02990 ++j) 02991 { 02992 dof_id_type constraint_dependency = j->first; 02993 02994 // No point in adding one of our own dofs to the send_list 02995 if (constraint_dependency >= this->first_dof() && 02996 constraint_dependency < this->end_dof()) 02997 continue; 02998 02999 _send_list.push_back(constraint_dependency); 03000 } 03001 } 03002 }
| void libMesh::DofMap::add_dirichlet_boundary | ( | const DirichletBoundary & | dirichlet_boundary | ) |
Adds a copy of the specified Dirichlet boundary to the system.
Definition at line 3076 of file dof_map_constraints.C.
References _dirichlet_boundaries.
03077 { 03078 _dirichlet_boundaries->push_back(new DirichletBoundary(dirichlet_boundary)); 03079 }
| void libMesh::DofMap::add_neighbors_to_send_list | ( | MeshBase & | mesh | ) | [private] |
Adds entries to the _send_list vector corresponding to DoFs on elements neighboring the current processor.
Definition at line 1242 of file dof_map.C.
References _send_list, libMesh::Elem::active(), libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::Elem::active_family_tree_by_neighbor(), libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), dof_indices(), libMesh::DofObject::dof_number(), end_dof(), first_dof(), libMesh::Elem::get_node(), libMesh::MeshBase::max_node_id(), libMesh::DofObject::n_comp(), libMesh::Elem::n_neighbors(), libMesh::Elem::n_nodes(), libMesh::DofObject::n_vars(), n_vars, libMesh::Elem::neighbor(), libMesh::Elem::node(), libMesh::DofObject::processor_id(), libMesh::processor_id(), and sys_number().
Referenced by distribute_dofs().
01243 { 01244 START_LOG("add_neighbors_to_send_list()", "DofMap"); 01245 01246 const unsigned int sys_num = this->sys_number(); 01247 01248 //------------------------------------------------------------------------- 01249 // We need to add the DOFs from elements that live on neighboring processors 01250 // that are neighbors of the elements on the local processor 01251 //------------------------------------------------------------------------- 01252 01253 MeshBase::const_element_iterator local_elem_it 01254 = mesh.active_local_elements_begin(); 01255 const MeshBase::const_element_iterator local_elem_end 01256 = mesh.active_local_elements_end(); 01257 01258 std::vector<bool> node_on_processor(mesh.max_node_id(), false); 01259 std::vector<dof_id_type> di; 01260 std::vector<const Elem *> family; 01261 01262 // Loop over the active local elements, adding all active elements 01263 // that neighbor an active local element to the send list. 01264 for ( ; local_elem_it != local_elem_end; ++local_elem_it) 01265 { 01266 const Elem* elem = *local_elem_it; 01267 01268 for (unsigned int n=0; n!=elem->n_nodes(); n++) 01269 { 01270 // Flag all the nodes of active local elements as seen, so 01271 // we can add nodal neighbor dofs to the send_list later. 01272 node_on_processor[elem->node(n)] = true; 01273 01274 // Add all remote dofs on these nodes to the send_list. 01275 // This is necessary in case those dofs are *not* also dofs 01276 // on neighbors; e.g. in the case of a HIERARCHIC's local 01277 // side which is only a vertex on the neighbor that owns it. 01278 const Node* node = elem->get_node(n); 01279 const unsigned n_vars = node->n_vars(sys_num); 01280 for (unsigned int v=0; v != n_vars; ++v) 01281 { 01282 const unsigned int n_comp = node->n_comp(sys_num, v); 01283 for (unsigned int c=0; c != n_comp; ++c) 01284 { 01285 const dof_id_type dof_index = node->dof_number(sys_num, v, c); 01286 if (dof_index < this->first_dof() || dof_index >= this->end_dof()) 01287 { 01288 _send_list.push_back(dof_index); 01289 // libmesh_here(); 01290 // std::cout << "sys_num,v,c,dof_index=" 01291 // << sys_num << ", " 01292 // << v << ", " 01293 // << c << ", " 01294 // << dof_index << '\n'; 01295 // node->debug_buffer(); 01296 } 01297 } 01298 } 01299 } 01300 01301 // Loop over the neighbors of those elements 01302 for (unsigned int s=0; s<elem->n_neighbors(); s++) 01303 if (elem->neighbor(s) != NULL) 01304 { 01305 family.clear(); 01306 01307 // Find all the active elements that neighbor elem 01308 #ifdef LIBMESH_ENABLE_AMR 01309 if (!elem->neighbor(s)->active()) 01310 elem->neighbor(s)->active_family_tree_by_neighbor(family, elem); 01311 else 01312 #endif 01313 family.push_back(elem->neighbor(s)); 01314 01315 for (dof_id_type i=0; i!=family.size(); ++i) 01316 // If the neighbor lives on a different processor 01317 if (family[i]->processor_id() != libMesh::processor_id()) 01318 { 01319 // Get the DOF indices for this neighboring element 01320 this->dof_indices (family[i], di); 01321 01322 // Insert the remote DOF indices into the send list 01323 for (std::size_t j=0; j != di.size(); ++j) 01324 if (di[j] < this->first_dof() || 01325 di[j] >= this->end_dof()) 01326 _send_list.push_back(di[j]); 01327 } 01328 } 01329 } 01330 01331 // Now loop over all non_local active elements and add any missing 01332 // nodal-only neighbors. This will also get any dofs from nonlocal 01333 // nodes on local elements, because every nonlocal node exists on a 01334 // nonlocal nodal neighbor element. 01335 MeshBase::const_element_iterator elem_it 01336 = mesh.active_elements_begin(); 01337 const MeshBase::const_element_iterator elem_end 01338 = mesh.active_elements_end(); 01339 01340 for ( ; elem_it != elem_end; ++elem_it) 01341 { 01342 const Elem* elem = *elem_it; 01343 01344 // If this is one of our elements, we've already added it 01345 if (elem->processor_id() == libMesh::processor_id()) 01346 continue; 01347 01348 // Do we need to add the element DOFs? 01349 bool add_elem_dofs = false; 01350 01351 // Check all the nodes of the element to see if it 01352 // shares a node with us 01353 for (unsigned int n=0; n!=elem->n_nodes(); n++) 01354 if (node_on_processor[elem->node(n)]) 01355 add_elem_dofs = true; 01356 01357 // Add the element degrees of freedom if it shares at 01358 // least one node. 01359 if (add_elem_dofs) 01360 { 01361 // Get the DOF indices for this neighboring element 01362 this->dof_indices (elem, di); 01363 01364 // Insert the remote DOF indices into the send list 01365 for (std::size_t j=0; j != di.size(); ++j) 01366 if (di[j] < this->first_dof() || 01367 di[j] >= this->end_dof()) 01368 _send_list.push_back(di[j]); 01369 } 01370 } 01371 01372 STOP_LOG("add_neighbors_to_send_list()", "DofMap"); 01373 }
| void libMesh::DofMap::add_periodic_boundary | ( | const PeriodicBoundaryBase & | boundary, | |
| const PeriodicBoundaryBase & | inverse_boundary | |||
| ) |
Add a periodic boundary pair
- Parameters:
-
boundary - primary boundary inverse_boundary - inverse boundary
Definition at line 3144 of file dof_map_constraints.C.
References _periodic_boundaries, libMesh::PeriodicBoundaryBase::clone(), libMesh::PeriodicBoundaryBase::myboundary, and libMesh::PeriodicBoundaryBase::pairedboundary.
03145 { 03146 libmesh_assert_equal_to (boundary.myboundary, inverse_boundary.pairedboundary); 03147 libmesh_assert_equal_to (boundary.pairedboundary, inverse_boundary.myboundary); 03148 03149 // Allocate copies on the heap. The _periodic_boundaries object will manage this memory. 03150 // Note: this also means that the copy constructor for the PeriodicBoundary (or user class 03151 // derived therefrom) must be implemented! 03152 // PeriodicBoundary* p_boundary = new PeriodicBoundary(boundary); 03153 // PeriodicBoundary* p_inverse_boundary = new PeriodicBoundary(inverse_boundary); 03154 03155 // We can't use normal copy construction since this leads to slicing with derived classes. 03156 // Use clone() "virtual constructor" instead. But, this *requires* user to override the clone() 03157 // method. Note also that clone() allocates memory. In this case, the _periodic_boundaries object 03158 // takes responsibility for cleanup. 03159 PeriodicBoundaryBase* p_boundary = boundary.clone().release(); 03160 PeriodicBoundaryBase* p_inverse_boundary = inverse_boundary.clone().release(); 03161 03162 // Add the periodic boundary and its inverse to the PeriodicBoundaries data structure. The 03163 // PeriodicBoundaries data structure takes ownership of the pointers. 03164 _periodic_boundaries->insert(std::make_pair(p_boundary->myboundary, p_boundary)); 03165 _periodic_boundaries->insert(std::make_pair(p_inverse_boundary->myboundary, p_inverse_boundary)); 03166 }
| void libMesh::DofMap::add_periodic_boundary | ( | const PeriodicBoundaryBase & | periodic_boundary | ) |
Adds a copy of the specified periodic boundary to the system.
Definition at line 3114 of file dof_map_constraints.C.
References _periodic_boundaries, libMesh::PeriodicBoundaries::boundary(), libMesh::PeriodicBoundaryBase::clone(), libMesh::PeriodicBoundaryBase::INVERSE, libMesh::PeriodicBoundaryBase::merge(), libMesh::PeriodicBoundaryBase::myboundary, and libMesh::PeriodicBoundaryBase::pairedboundary.
03115 { 03116 // See if we already have a periodic boundary associated myboundary... 03117 PeriodicBoundaryBase* existing_boundary = _periodic_boundaries->boundary(periodic_boundary.myboundary); 03118 03119 if ( existing_boundary == NULL ) 03120 { 03121 // ...if not, clone the input (and its inverse) and add them to the PeriodicBoundaries object 03122 PeriodicBoundaryBase* boundary = periodic_boundary.clone().release(); 03123 PeriodicBoundaryBase* inverse_boundary = periodic_boundary.clone(PeriodicBoundaryBase::INVERSE).release(); 03124 03125 // _periodic_boundaries takes ownership of the pointers 03126 _periodic_boundaries->insert(std::make_pair(boundary->myboundary, boundary)); 03127 _periodic_boundaries->insert(std::make_pair(inverse_boundary->myboundary, inverse_boundary)); 03128 } 03129 else 03130 { 03131 // ...otherwise, merge this object's variable IDs with the existing boundary object's. 03132 existing_boundary->merge(periodic_boundary); 03133 03134 // Do the same merging process for the inverse boundary. Note: the inverse better already exist! 03135 PeriodicBoundaryBase* inverse_boundary = _periodic_boundaries->boundary(periodic_boundary.pairedboundary); 03136 libmesh_assert(inverse_boundary); 03137 inverse_boundary->merge(periodic_boundary); 03138 } 03139 }
| void libMesh::DofMap::add_variable_group | ( | const VariableGroup & | var_group | ) |
Add an unknown of order order and finite element type type to the system of equations. Add a group of unknowns of order order and finite element type type to the system of equations.
Definition at line 203 of file dof_map.C.
References _variable_groups, _variables, and libMesh::VariableGroup::n_variables().
00204 { 00205 _variable_groups.push_back(var_group); 00206 00207 VariableGroup &new_var_group = _variable_groups.back(); 00208 00209 for (unsigned int var=0; var<new_var_group.n_variables(); var++) 00210 _variables.push_back (new_var_group(var)); 00211 }
| bool libMesh::DofMap::all_semilocal_indices | ( | const std::vector< dof_id_type > & | dof_indices | ) | const |
Returns true iff all degree of freedom indices in dof_indices are either local indices or in the send_list. Note that this is an O(logN) operation, not O(1); we don't cache enough information for O(1) right now.
Definition at line 1812 of file dof_map.C.
References _send_list, end_dof(), and first_dof().
01813 { 01814 // We're all semilocal unless we find a counterexample 01815 for (std::size_t i=0; i != dof_indices_in.size(); ++i) 01816 { 01817 const dof_id_type di = dof_indices_in[i]; 01818 // If it's not in the local indices 01819 if (di < this->first_dof() || 01820 di >= this->end_dof()) 01821 { 01822 // and if it's not in the ghost indices, then we're not 01823 // semilocal 01824 if (!std::binary_search(_send_list.begin(), _send_list.end(), di)) 01825 return false; 01826 } 01827 } 01828 01829 return true; 01830 }
| void libMesh::DofMap::allgather_recursive_constraints | ( | MeshBase & | mesh | ) |
Gathers constraint equation dependencies from other processors
Definition at line 1971 of file dof_map_constraints.C.
References _dof_constraints, _end_df, _node_constraints, libMesh::MeshBase::active_not_local_elements_begin(), libMesh::MeshBase::active_not_local_elements_end(), libMesh::CommWorld, dof_indices(), end, end_dof(), first_dof(), libMesh::Elem::get_node(), libMesh::DofObject::id(), is_constrained_dof(), is_constrained_node(), libMesh::Parallel::Communicator::max(), libMesh::Elem::n_nodes(), libMesh::n_processors(), libMesh::Elem::node(), libMesh::MeshBase::node_ptr(), libMesh::processor_id(), libMesh::DofObject::processor_id(), libMesh::Parallel::Communicator::send_receive(), and libMesh::Parallel::Communicator::send_receive_packed_range().
Referenced by process_constraints().
01972 { 01973 // This function must be run on all processors at once 01974 parallel_only(); 01975 01976 // Return immediately if there's nothing to gather 01977 if (libMesh::n_processors() == 1) 01978 return; 01979 01980 // We might get to return immediately if none of the processors 01981 // found any constraints 01982 unsigned int has_constraints = !_dof_constraints.empty() 01983 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 01984 || !_node_constraints.empty() 01985 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 01986 ; 01987 CommWorld.max(has_constraints); 01988 if (!has_constraints) 01989 return; 01990 01991 // We might have calculated constraints for constrained dofs 01992 // which have support on other processors. 01993 // Push these out first. 01994 { 01995 std::vector<std::set<dof_id_type> > pushed_ids(libMesh::n_processors()); 01996 01997 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 01998 std::vector<std::set<dof_id_type> > pushed_node_ids(libMesh::n_processors()); 01999 #endif 02000 02001 MeshBase::element_iterator 02002 foreign_elem_it = mesh.active_not_local_elements_begin(), 02003 foreign_elem_end = mesh.active_not_local_elements_end(); 02004 02005 // Collect the constraints to push to each processor 02006 for (; foreign_elem_it != foreign_elem_end; ++foreign_elem_it) 02007 { 02008 Elem *elem = *foreign_elem_it; 02009 02010 std::vector<dof_id_type> my_dof_indices; 02011 this->dof_indices (elem, my_dof_indices); 02012 02013 for (unsigned int i=0; i != my_dof_indices.size(); ++i) 02014 if (this->is_constrained_dof(my_dof_indices[i])) 02015 pushed_ids[elem->processor_id()].insert(my_dof_indices[i]); 02016 02017 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02018 for (unsigned int n=0; n != elem->n_nodes(); ++n) 02019 if (this->is_constrained_node(elem->get_node(n))) 02020 pushed_node_ids[elem->processor_id()].insert(elem->node(n)); 02021 #endif 02022 } 02023 02024 // Now trade constraint rows 02025 for (processor_id_type p = 0; p != libMesh::n_processors(); ++p) 02026 { 02027 // Push to processor procup while receiving from procdown 02028 processor_id_type procup = (libMesh::processor_id() + p) % 02029 libMesh::n_processors(); 02030 processor_id_type procdown = (libMesh::n_processors() + 02031 libMesh::processor_id() - p) % 02032 libMesh::n_processors(); 02033 02034 // Pack the dof constraint rows and rhs's to push to procup 02035 const std::size_t pushed_ids_size = pushed_ids[procup].size(); 02036 std::vector<std::vector<dof_id_type> > pushed_keys(pushed_ids_size); 02037 std::vector<std::vector<Real> > pushed_vals(pushed_ids_size); 02038 std::vector<Number> pushed_rhss(pushed_ids_size); 02039 std::set<dof_id_type>::const_iterator it = pushed_ids[procup].begin(); 02040 for (std::size_t i = 0; it != pushed_ids[procup].end(); 02041 ++i, ++it) 02042 { 02043 const dof_id_type pushed_id = *it; 02044 DofConstraintRow &row = _dof_constraints[pushed_id].first; 02045 std::size_t row_size = row.size(); 02046 pushed_keys[i].reserve(row_size); 02047 pushed_vals[i].reserve(row_size); 02048 for (DofConstraintRow::iterator j = row.begin(); 02049 j != row.end(); ++j) 02050 { 02051 pushed_keys[i].push_back(j->first); 02052 pushed_vals[i].push_back(j->second); 02053 } 02054 pushed_rhss[i] = _dof_constraints[pushed_id].second; 02055 } 02056 02057 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02058 // Pack the node constraint rows to push to procup 02059 const std::size_t pushed_nodes_size = pushed_node_ids[procup].size(); 02060 std::vector<std::vector<dof_id_type> > pushed_node_keys(pushed_nodes_size); 02061 std::vector<std::vector<Real> > pushed_node_vals(pushed_nodes_size); 02062 std::vector<Point> pushed_node_offsets(pushed_nodes_size); 02063 std::set<dof_id_type>::const_iterator node_it = pushed_node_ids[procup].begin(); 02064 for (std::size_t i = 0; node_it != pushed_node_ids[procup].end(); 02065 ++i, ++node_it) 02066 { 02067 const Node *node = mesh.node_ptr(*node_it); 02068 NodeConstraintRow &row = _node_constraints[node].first; 02069 std::size_t row_size = row.size(); 02070 pushed_node_keys[i].reserve(row_size); 02071 pushed_node_vals[i].reserve(row_size); 02072 for (NodeConstraintRow::iterator j = row.begin(); 02073 j != row.end(); ++j) 02074 { 02075 pushed_node_keys[i].push_back(j->first->id()); 02076 pushed_node_vals[i].push_back(j->second); 02077 } 02078 pushed_node_offsets[i] = _node_constraints[node].second; 02079 } 02080 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02081 02082 // Trade pushed dof constraint rows 02083 std::vector<dof_id_type> pushed_ids_from_me 02084 (pushed_ids[procup].begin(), pushed_ids[procup].end()); 02085 std::vector<dof_id_type> pushed_ids_to_me; 02086 std::vector<std::vector<dof_id_type> > pushed_keys_to_me; 02087 std::vector<std::vector<Real> > pushed_vals_to_me; 02088 std::vector<Number> pushed_rhss_to_me; 02089 CommWorld.send_receive(procup, pushed_ids_from_me, 02090 procdown, pushed_ids_to_me); 02091 CommWorld.send_receive(procup, pushed_keys, 02092 procdown, pushed_keys_to_me); 02093 CommWorld.send_receive(procup, pushed_vals, 02094 procdown, pushed_vals_to_me); 02095 CommWorld.send_receive(procup, pushed_rhss, 02096 procdown, pushed_rhss_to_me); 02097 libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_keys_to_me.size()); 02098 libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_vals_to_me.size()); 02099 libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_rhss_to_me.size()); 02100 02101 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02102 // Trade pushed node constraint rows 02103 std::vector<dof_id_type> pushed_node_ids_from_me 02104 (pushed_node_ids[procup].begin(), pushed_node_ids[procup].end()); 02105 std::vector<dof_id_type> pushed_node_ids_to_me; 02106 std::vector<std::vector<dof_id_type> > pushed_node_keys_to_me; 02107 std::vector<std::vector<Real> > pushed_node_vals_to_me; 02108 std::vector<Point> pushed_node_offsets_to_me; 02109 CommWorld.send_receive(procup, pushed_node_ids_from_me, 02110 procdown, pushed_node_ids_to_me); 02111 CommWorld.send_receive(procup, pushed_node_keys, 02112 procdown, pushed_node_keys_to_me); 02113 CommWorld.send_receive(procup, pushed_node_vals, 02114 procdown, pushed_node_vals_to_me); 02115 CommWorld.send_receive(procup, pushed_node_offsets, 02116 procdown, pushed_node_offsets_to_me); 02117 02118 // Note that we aren't doing a send_receive on the Nodes 02119 // themselves. At this point we should only be pushing out 02120 // "raw" constraints, and there should be no 02121 // constrained-by-constrained-by-etc. situations that could 02122 // involve non-semilocal nodes. 02123 02124 libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_keys_to_me.size()); 02125 libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_vals_to_me.size()); 02126 libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_offsets_to_me.size()); 02127 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02128 02129 // Add the dof constraints that I've been sent 02130 for (std::size_t i = 0; i != pushed_ids_to_me.size(); ++i) 02131 { 02132 libmesh_assert_equal_to (pushed_keys_to_me[i].size(), pushed_vals_to_me[i].size()); 02133 02134 dof_id_type constrained = pushed_ids_to_me[i]; 02135 02136 // If we don't already have a constraint for this dof, 02137 // add the one we were sent 02138 if (!this->is_constrained_dof(constrained)) 02139 { 02140 DofConstraintRow &row = _dof_constraints[constrained].first; 02141 for (std::size_t j = 0; j != pushed_keys_to_me[i].size(); ++j) 02142 { 02143 row[pushed_keys_to_me[i][j]] = pushed_vals_to_me[i][j]; 02144 } 02145 _dof_constraints[constrained].second = pushed_rhss_to_me[i]; 02146 } 02147 } 02148 02149 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02150 // Add the node constraints that I've been sent 02151 for (std::size_t i = 0; i != pushed_node_ids_to_me.size(); ++i) 02152 { 02153 libmesh_assert_equal_to (pushed_node_keys_to_me[i].size(), pushed_node_vals_to_me[i].size()); 02154 02155 dof_id_type constrained_id = pushed_node_ids_to_me[i]; 02156 02157 // If we don't already have a constraint for this node, 02158 // add the one we were sent 02159 const Node *constrained = mesh.node_ptr(constrained_id); 02160 if (!this->is_constrained_node(constrained)) 02161 { 02162 NodeConstraintRow &row = _node_constraints[constrained].first; 02163 for (std::size_t j = 0; j != pushed_node_keys_to_me[i].size(); ++j) 02164 { 02165 const Node *key_node = mesh.node_ptr(pushed_node_keys_to_me[i][j]); 02166 libmesh_assert(key_node); 02167 row[key_node] = pushed_node_vals_to_me[i][j]; 02168 } 02169 _node_constraints[constrained].second = pushed_node_offsets_to_me[i]; 02170 } 02171 } 02172 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02173 } 02174 } 02175 02176 // Now start checking for any other constraints we need 02177 // to know about, requesting them recursively. 02178 02179 // Create sets containing the DOFs and nodes we already depend on 02180 typedef std::set<dof_id_type> DoF_RCSet; 02181 DoF_RCSet unexpanded_dofs; 02182 02183 for (DofConstraints::iterator i = _dof_constraints.begin(); 02184 i != _dof_constraints.end(); ++i) 02185 { 02186 unexpanded_dofs.insert(i->first); 02187 } 02188 02189 typedef std::set<const Node *> Node_RCSet; 02190 Node_RCSet unexpanded_nodes; 02191 02192 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02193 for (NodeConstraints::iterator i = _node_constraints.begin(); 02194 i != _node_constraints.end(); ++i) 02195 { 02196 unexpanded_nodes.insert(i->first); 02197 } 02198 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02199 02200 // We have to keep recursing while the unexpanded set is 02201 // nonempty on *any* processor 02202 bool unexpanded_set_nonempty = !unexpanded_dofs.empty() || 02203 !unexpanded_nodes.empty(); 02204 CommWorld.max(unexpanded_set_nonempty); 02205 02206 while (unexpanded_set_nonempty) 02207 { 02208 // Let's make sure we don't lose sync in this loop. 02209 parallel_only(); 02210 02211 // Request sets 02212 DoF_RCSet dof_request_set; 02213 Node_RCSet node_request_set; 02214 02215 // Request sets to send to each processor 02216 std::vector<std::vector<dof_id_type> > 02217 requested_dof_ids(libMesh::n_processors()), 02218 requested_node_ids(libMesh::n_processors()); 02219 02220 // And the sizes of each 02221 std::vector<dof_id_type> 02222 dof_ids_on_proc(libMesh::n_processors(), 0), 02223 node_ids_on_proc(libMesh::n_processors(), 0); 02224 02225 // Fill (and thereby sort and uniq!) the main request sets 02226 for (DoF_RCSet::iterator i = unexpanded_dofs.begin(); 02227 i != unexpanded_dofs.end(); ++i) 02228 { 02229 DofConstraintRow &row = _dof_constraints[*i].first; 02230 for (DofConstraintRow::iterator j = row.begin(); 02231 j != row.end(); ++j) 02232 { 02233 const dof_id_type constraining_dof = j->first; 02234 02235 // If it's non-local and we haven't already got a 02236 // constraint for it, we might need to ask for one 02237 if (((constraining_dof < this->first_dof()) || 02238 (constraining_dof >= this->end_dof())) && 02239 !_dof_constraints.count(constraining_dof)) 02240 dof_request_set.insert(constraining_dof); 02241 } 02242 } 02243 02244 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02245 for (Node_RCSet::iterator i = unexpanded_nodes.begin(); 02246 i != unexpanded_nodes.end(); ++i) 02247 { 02248 NodeConstraintRow &row = _node_constraints[*i].first; 02249 for (NodeConstraintRow::iterator j = row.begin(); 02250 j != row.end(); ++j) 02251 { 02252 const Node* const node = j->first; 02253 libmesh_assert(node); 02254 02255 // If it's non-local and we haven't already got a 02256 // constraint for it, we might need to ask for one 02257 if ((node->processor_id() != libMesh::processor_id()) && 02258 !_node_constraints.count(node)) 02259 node_request_set.insert(node); 02260 } 02261 } 02262 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02263 02264 // Clear the unexpanded constraint sets; we're about to expand 02265 // them 02266 unexpanded_dofs.clear(); 02267 unexpanded_nodes.clear(); 02268 02269 // Count requests by processor 02270 processor_id_type proc_id = 0; 02271 for (DoF_RCSet::iterator i = dof_request_set.begin(); 02272 i != dof_request_set.end(); ++i) 02273 { 02274 while (*i >= _end_df[proc_id]) 02275 proc_id++; 02276 dof_ids_on_proc[proc_id]++; 02277 } 02278 02279 for (Node_RCSet::iterator i = node_request_set.begin(); 02280 i != node_request_set.end(); ++i) 02281 { 02282 libmesh_assert(*i); 02283 libmesh_assert_less ((*i)->processor_id(), libMesh::n_processors()); 02284 node_ids_on_proc[(*i)->processor_id()]++; 02285 } 02286 02287 for (processor_id_type p = 0; p != libMesh::n_processors(); ++p) 02288 { 02289 requested_dof_ids[p].reserve(dof_ids_on_proc[p]); 02290 requested_node_ids[p].reserve(node_ids_on_proc[p]); 02291 } 02292 02293 // Prepare each processor's request set 02294 proc_id = 0; 02295 for (DoF_RCSet::iterator i = dof_request_set.begin(); 02296 i != dof_request_set.end(); ++i) 02297 { 02298 while (*i >= _end_df[proc_id]) 02299 proc_id++; 02300 requested_dof_ids[proc_id].push_back(*i); 02301 } 02302 02303 for (Node_RCSet::iterator i = node_request_set.begin(); 02304 i != node_request_set.end(); ++i) 02305 { 02306 requested_node_ids[(*i)->processor_id()].push_back((*i)->id()); 02307 } 02308 02309 // Now request constraint rows from other processors 02310 for (processor_id_type p=1; p != libMesh::n_processors(); ++p) 02311 { 02312 // Trade my requests with processor procup and procdown 02313 processor_id_type procup = (libMesh::processor_id() + p) % 02314 libMesh::n_processors(); 02315 processor_id_type procdown = (libMesh::n_processors() + 02316 libMesh::processor_id() - p) % 02317 libMesh::n_processors(); 02318 std::vector<dof_id_type> dof_request_to_fill, 02319 node_request_to_fill; 02320 CommWorld.send_receive(procup, requested_dof_ids[procup], 02321 procdown, dof_request_to_fill); 02322 CommWorld.send_receive(procup, requested_node_ids[procup], 02323 procdown, node_request_to_fill); 02324 02325 // Fill those requests 02326 std::vector<std::vector<dof_id_type> > dof_row_keys(dof_request_to_fill.size()), 02327 node_row_keys(node_request_to_fill.size()); 02328 02329 // FIXME - this could be an unordered set, given a 02330 // hash<pointers> specialization 02331 std::set<const Node*> nodes_requested; 02332 02333 std::vector<std::vector<Real> > dof_row_vals(dof_request_to_fill.size()), 02334 node_row_vals(node_request_to_fill.size()); 02335 std::vector<Number> dof_row_rhss(dof_request_to_fill.size()); 02336 std::vector<Point> node_row_rhss(node_request_to_fill.size()); 02337 for (std::size_t i=0; i != dof_request_to_fill.size(); ++i) 02338 { 02339 dof_id_type constrained = dof_request_to_fill[i]; 02340 if (_dof_constraints.count(constrained)) 02341 { 02342 DofConstraintRow &row = _dof_constraints[constrained].first; 02343 std::size_t row_size = row.size(); 02344 dof_row_keys[i].reserve(row_size); 02345 dof_row_vals[i].reserve(row_size); 02346 for (DofConstraintRow::iterator j = row.begin(); 02347 j != row.end(); ++j) 02348 { 02349 dof_row_keys[i].push_back(j->first); 02350 dof_row_vals[i].push_back(j->second); 02351 02352 // We should never have a 0 constraint 02353 // coefficient; that's implicit via sparse 02354 // constraint storage 02355 libmesh_assert(j->second); 02356 } 02357 dof_row_rhss[i] = _dof_constraints[constrained].second; 02358 } 02359 } 02360 02361 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02362 for (std::size_t i=0; i != node_request_to_fill.size(); ++i) 02363 { 02364 dof_id_type constrained_id = node_request_to_fill[i]; 02365 const Node *constrained_node = mesh.node_ptr(constrained_id); 02366 if (_node_constraints.count(constrained_node)) 02367 { 02368 const NodeConstraintRow &row = _node_constraints[constrained_node].first; 02369 std::size_t row_size = row.size(); 02370 node_row_keys[i].reserve(row_size); 02371 node_row_vals[i].reserve(row_size); 02372 for (NodeConstraintRow::const_iterator j = row.begin(); 02373 j != row.end(); ++j) 02374 { 02375 const Node* node = j->first; 02376 node_row_keys[i].push_back(node->id()); 02377 node_row_vals[i].push_back(j->second); 02378 02379 // If we're not sure whether our send 02380 // destination already has this node, let's give 02381 // it a copy. 02382 if (node->processor_id() != procdown) 02383 nodes_requested.insert(node); 02384 02385 // We can have 0 nodal constraint 02386 // coefficients, where no Lagrange constrant 02387 // exists but non-Lagrange basis constraints 02388 // might. 02389 // libmesh_assert(j->second); 02390 } 02391 node_row_rhss[i] = _node_constraints[constrained_node].second; 02392 } 02393 } 02394 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02395 02396 // Trade back the results 02397 std::vector<std::vector<dof_id_type> > dof_filled_keys, 02398 node_filled_keys; 02399 std::vector<std::vector<Real> > dof_filled_vals, 02400 node_filled_vals; 02401 std::vector<Number> dof_filled_rhss; 02402 std::vector<Point> node_filled_rhss; 02403 CommWorld.send_receive(procdown, dof_row_keys, 02404 procup, dof_filled_keys); 02405 CommWorld.send_receive(procdown, dof_row_vals, 02406 procup, dof_filled_vals); 02407 CommWorld.send_receive(procdown, dof_row_rhss, 02408 procup, dof_filled_rhss); 02409 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02410 CommWorld.send_receive(procdown, node_row_keys, 02411 procup, node_filled_keys); 02412 CommWorld.send_receive(procdown, node_row_vals, 02413 procup, node_filled_vals); 02414 CommWorld.send_receive(procdown, node_row_rhss, 02415 procup, node_filled_rhss); 02416 02417 // Constraining nodes might not even exist on our subset of 02418 // a distributed mesh, so let's make them exist. 02419 CommWorld.send_receive_packed_range 02420 (procdown, &mesh, nodes_requested.begin(), nodes_requested.end(), 02421 procup, &mesh, mesh_inserter_iterator<Node>(mesh)); 02422 02423 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02424 libmesh_assert_equal_to (dof_filled_keys.size(), requested_dof_ids[procup].size()); 02425 libmesh_assert_equal_to (dof_filled_vals.size(), requested_dof_ids[procup].size()); 02426 libmesh_assert_equal_to (dof_filled_rhss.size(), requested_dof_ids[procup].size()); 02427 libmesh_assert_equal_to (node_filled_keys.size(), requested_node_ids[procup].size()); 02428 libmesh_assert_equal_to (node_filled_vals.size(), requested_node_ids[procup].size()); 02429 libmesh_assert_equal_to (node_filled_rhss.size(), requested_node_ids[procup].size()); 02430 02431 // Add any new constraint rows we've found 02432 for (std::size_t i=0; i != requested_dof_ids[procup].size(); ++i) 02433 { 02434 libmesh_assert_equal_to (dof_filled_keys[i].size(), dof_filled_vals[i].size()); 02435 // FIXME - what about empty p constraints!? 02436 if (!dof_filled_keys[i].empty()) 02437 { 02438 dof_id_type constrained = requested_dof_ids[procup][i]; 02439 DofConstraintRow &row = _dof_constraints[constrained].first; 02440 for (std::size_t j = 0; j != dof_filled_keys[i].size(); ++j) 02441 row[dof_filled_keys[i][j]] = dof_filled_vals[i][j]; 02442 _dof_constraints[constrained].second = dof_filled_rhss[i]; 02443 02444 // And prepare to check for more recursive constraints 02445 unexpanded_dofs.insert(constrained); 02446 } 02447 } 02448 02449 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02450 for (std::size_t i=0; i != requested_node_ids[procup].size(); ++i) 02451 { 02452 libmesh_assert_equal_to (node_filled_keys[i].size(), node_filled_vals[i].size()); 02453 if (!node_filled_keys[i].empty()) 02454 { 02455 dof_id_type constrained_id = requested_node_ids[procup][i]; 02456 const Node* constrained_node = mesh.node_ptr(constrained_id); 02457 NodeConstraintRow &row = _node_constraints[constrained_node].first; 02458 for (std::size_t j = 0; j != node_filled_keys[i].size(); ++j) 02459 { 02460 const Node* key_node = 02461 mesh.node_ptr(node_filled_keys[i][j]); 02462 libmesh_assert(key_node); 02463 row[key_node] = node_filled_vals[i][j]; 02464 } 02465 _node_constraints[constrained_node].second = node_filled_rhss[i]; 02466 02467 // And prepare to check for more recursive constraints 02468 unexpanded_nodes.insert(constrained_node); 02469 } 02470 } 02471 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02472 } 02473 02474 // We have to keep recursing while the unexpanded set is 02475 // nonempty on *any* processor 02476 unexpanded_set_nonempty = !unexpanded_dofs.empty() || 02477 !unexpanded_nodes.empty(); 02478 CommWorld.max(unexpanded_set_nonempty); 02479 } 02480 }
| void libMesh::DofMap::attach_extra_send_list_function | ( | void(*)(std::vector< dof_id_type > &, void *) | func, | |
| void * | context = NULL | |||
| ) | [inline] |
Attach a function pointer to use as a callback to populate the send_list with extra entries.
Definition at line 270 of file dof_map.h.
References _extra_send_list_context, and _extra_send_list_function.
00271 { _extra_send_list_function = func; _extra_send_list_context = context; }
| void libMesh::DofMap::attach_extra_send_list_object | ( | DofMap::AugmentSendList & | asl | ) | [inline] |
Attach an object to populate the send_list with extra entries. This should only add to the send list, but no checking is done to enforce this behavior.
This is an advanced function... use at your own peril!
Definition at line 261 of file dof_map.h.
References _augment_send_list.
00262 { 00263 _augment_send_list = &asl; 00264 }
| 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 = NULL | |||
| ) | [inline] |
Attach a function pointer to use as a callback to populate the sparsity pattern with extra entries.
Care must be taken that when adding entries they are sorted into the Rows
Further, you _must_ modify n_nz and n_oz properly!
This is an advanced function... use at your own peril!
Definition at line 247 of file dof_map.h.
References _extra_sparsity_context, and _extra_sparsity_function.
00252 { _extra_sparsity_function = func; _extra_sparsity_context = context; }
| void libMesh::DofMap::attach_extra_sparsity_object | ( | DofMap::AugmentSparsityPattern & | asp | ) | [inline] |
Attach an object to use to populate the sparsity pattern with extra entries.
Care must be taken that when adding entries they are sorted into the Rows
Further, you _must_ modify n_nz and n_oz properly!
This is an advanced function... use at your own peril!
Definition at line 232 of file dof_map.h.
References _augment_sparsity_pattern.
00233 { 00234 _augment_sparsity_pattern = &asp; 00235 }
| void libMesh::DofMap::attach_matrix | ( | SparseMatrix< Number > & | matrix | ) |
Additional matrices may be handled with this DofMap. They are initialized to the same sparsity structure as the major matrix.
Definition at line 215 of file dof_map.C.
References _matrices, _n_nz, _n_oz, _sp, libMesh::SparseMatrix< T >::attach_dof_map(), libMesh::CommWorld, libMesh::AutoPtr< Tp >::get(), libMesh::Parallel::Communicator::max(), need_full_sparsity_pattern, libMesh::SparseMatrix< T >::need_full_sparsity_pattern(), and libMesh::SparseMatrix< T >::update_sparsity_pattern().
Referenced by libMesh::ImplicitSystem::init_matrices(), and libMesh::EigenSystem::init_matrices().
00216 { 00217 parallel_only(); 00218 00219 // We shouldn't be trying to re-attach the same matrices repeatedly 00220 libmesh_assert (std::find(_matrices.begin(), _matrices.end(), 00221 &matrix) == _matrices.end()); 00222 00223 _matrices.push_back(&matrix); 00224 00225 matrix.attach_dof_map (*this); 00226 00227 // If we've already computed sparsity, then it's too late 00228 // to wait for "compute_sparsity" to help with sparse matrix 00229 // initialization, and we need to handle this matrix individually 00230 bool computed_sparsity_already = 00231 ((_n_nz && !_n_nz->empty()) || 00232 (_n_oz && !_n_oz->empty())); 00233 CommWorld.max(computed_sparsity_already); 00234 if (computed_sparsity_already && 00235 matrix.need_full_sparsity_pattern()) 00236 { 00237 // We'd better have already computed the full sparsity pattern 00238 // if we need it here 00239 libmesh_assert(need_full_sparsity_pattern); 00240 libmesh_assert(_sp.get()); 00241 00242 matrix.update_sparsity_pattern (_sp->sparsity_pattern); 00243 } 00244 00245 if (matrix.need_full_sparsity_pattern()) 00246 need_full_sparsity_pattern = true; 00247 }
| void libMesh::DofMap::build_constraint_matrix | ( | DenseMatrix< Number > & | C, | |
| std::vector< dof_id_type > & | elem_dofs, | |||
| const bool | called_recursively = false | |||
| ) | const [private] |
Build the constraint matrix C associated with the element degree of freedom indices elem_dofs. The optional parameter called_recursively should be left at the default value false. This is used to handle the special case of an element's degrees of freedom being constrained in terms of other, local degrees of freedom. The usual case is for an elements DOFs to be constrained by some other, external DOFs.
Definition at line 1721 of file dof_map_constraints.C.
References _dof_constraints, is_constrained_dof(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::resize(), and libMesh::DenseMatrix< T >::right_multiply().
Referenced by constrain_element_dyad_matrix(), constrain_element_matrix(), constrain_element_matrix_and_vector(), constrain_element_vector(), constrain_nothing(), and max_constraint_error().
01724 { 01725 if (!called_recursively) START_LOG("build_constraint_matrix()", "DofMap"); 01726 01727 // Create a set containing the DOFs we already depend on 01728 typedef std::set<dof_id_type> RCSet; 01729 RCSet dof_set; 01730 01731 bool we_have_constraints = false; 01732 01733 // Next insert any other dofs the current dofs might be constrained 01734 // in terms of. Note that in this case we may not be done: Those 01735 // may in turn depend on others. So, we need to repeat this process 01736 // in that case until the system depends only on unconstrained 01737 // degrees of freedom. 01738 for (unsigned int i=0; i<elem_dofs.size(); i++) 01739 if (this->is_constrained_dof(elem_dofs[i])) 01740 { 01741 we_have_constraints = true; 01742 01743 // If the DOF is constrained 01744 DofConstraints::const_iterator 01745 pos = _dof_constraints.find(elem_dofs[i]); 01746 01747 libmesh_assert (pos != _dof_constraints.end()); 01748 01749 const DofConstraintRow& constraint_row = pos->second.first; 01750 01751 // Constraint rows in p refinement may be empty 01752 // libmesh_assert (!constraint_row.empty()); 01753 01754 for (DofConstraintRow::const_iterator 01755 it=constraint_row.begin(); it != constraint_row.end(); 01756 ++it) 01757 dof_set.insert (it->first); 01758 } 01759 01760 // May be safe to return at this point 01761 // (but remember to stop the perflog) 01762 if (!we_have_constraints) 01763 { 01764 STOP_LOG("build_constraint_matrix()", "DofMap"); 01765 return; 01766 } 01767 01768 for (unsigned int i=0; i != elem_dofs.size(); ++i) 01769 dof_set.erase (elem_dofs[i]); 01770 01771 // If we added any DOFS then we need to do this recursively. 01772 // It is possible that we just added a DOF that is also 01773 // constrained! 01774 // 01775 // Also, we need to handle the special case of an element having DOFs 01776 // constrained in terms of other, local DOFs 01777 if (!dof_set.empty() || // case 1: constrained in terms of other DOFs 01778 !called_recursively) // case 2: constrained in terms of our own DOFs 01779 { 01780 const unsigned int old_size = 01781 libmesh_cast_int<unsigned int>(elem_dofs.size()); 01782 01783 // Add new dependency dofs to the end of the current dof set 01784 elem_dofs.insert(elem_dofs.end(), 01785 dof_set.begin(), dof_set.end()); 01786 01787 // Now we can build the constraint matrix. 01788 // Note that resize also zeros for a DenseMatrix<Number>. 01789 C.resize (old_size, 01790 libmesh_cast_int<unsigned int>(elem_dofs.size())); 01791 01792 // Create the C constraint matrix. 01793 for (unsigned int i=0; i != old_size; i++) 01794 if (this->is_constrained_dof(elem_dofs[i])) 01795 { 01796 // If the DOF is constrained 01797 DofConstraints::const_iterator 01798 pos = _dof_constraints.find(elem_dofs[i]); 01799 01800 libmesh_assert (pos != _dof_constraints.end()); 01801 01802 const DofConstraintRow& constraint_row = pos->second.first; 01803 01804 // p refinement creates empty constraint rows 01805 // libmesh_assert (!constraint_row.empty()); 01806 01807 for (DofConstraintRow::const_iterator 01808 it=constraint_row.begin(); it != constraint_row.end(); 01809 ++it) 01810 for (unsigned int j=0; j != elem_dofs.size(); j++) 01811 if (elem_dofs[j] == it->first) 01812 C(i,j) = it->second; 01813 } 01814 else 01815 { 01816 C(i,i) = 1.; 01817 } 01818 01819 // May need to do this recursively. It is possible 01820 // that we just replaced a constrained DOF with another 01821 // constrained DOF. 01822 DenseMatrix<Number> Cnew; 01823 01824 this->build_constraint_matrix (Cnew, elem_dofs, true); 01825 01826 if ((C.n() == Cnew.m()) && 01827 (Cnew.n() == elem_dofs.size())) // If the constraint matrix 01828 C.right_multiply(Cnew); // is constrained... 01829 01830 libmesh_assert_equal_to (C.n(), elem_dofs.size()); 01831 } 01832 01833 if (!called_recursively) STOP_LOG("build_constraint_matrix()", "DofMap"); 01834 }
| void libMesh::DofMap::build_constraint_matrix_and_vector | ( | DenseMatrix< Number > & | C, | |
| DenseVector< Number > & | H, | |||
| std::vector< dof_id_type > & | elem_dofs, | |||
| 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.
Definition at line 1839 of file dof_map_constraints.C.
References libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::resize(), libMesh::DenseMatrix< T >::resize(), libMesh::DenseMatrix< T >::right_multiply(), and libMesh::DenseMatrix< T >::vector_mult_add().
Referenced by extract_local_vector().
01843 { 01844 if (!called_recursively) 01845 START_LOG("build_constraint_matrix_and_vector()", "DofMap"); 01846 01847 // Create a set containing the DOFs we already depend on 01848 typedef std::set<dof_id_type> RCSet; 01849 RCSet dof_set; 01850 01851 bool we_have_constraints = false; 01852 01853 // Next insert any other dofs the current dofs might be constrained 01854 // in terms of. Note that in this case we may not be done: Those 01855 // may in turn depend on others. So, we need to repeat this process 01856 // in that case until the system depends only on unconstrained 01857 // degrees of freedom. 01858 for (unsigned int i=0; i<elem_dofs.size(); i++) 01859 if (this->is_constrained_dof(elem_dofs[i])) 01860 { 01861 we_have_constraints = true; 01862 01863 // If the DOF is constrained 01864 DofConstraints::const_iterator 01865 pos = _dof_constraints.find(elem_dofs[i]); 01866 01867 libmesh_assert (pos != _dof_constraints.end()); 01868 01869 const DofConstraintRow& constraint_row = pos->second.first; 01870 01871 // Constraint rows in p refinement may be empty 01872 // libmesh_assert (!constraint_row.empty()); 01873 01874 for (DofConstraintRow::const_iterator 01875 it=constraint_row.begin(); it != constraint_row.end(); 01876 ++it) 01877 dof_set.insert (it->first); 01878 } 01879 01880 // May be safe to return at this point 01881 // (but remember to stop the perflog) 01882 if (!we_have_constraints) 01883 { 01884 STOP_LOG("build_constraint_matrix_and_vector()", "DofMap"); 01885 return; 01886 } 01887 01888 for (unsigned int i=0; i != elem_dofs.size(); ++i) 01889 dof_set.erase (elem_dofs[i]); 01890 01891 // If we added any DOFS then we need to do this recursively. 01892 // It is possible that we just added a DOF that is also 01893 // constrained! 01894 // 01895 // Also, we need to handle the special case of an element having DOFs 01896 // constrained in terms of other, local DOFs 01897 if (!dof_set.empty() || // case 1: constrained in terms of other DOFs 01898 !called_recursively) // case 2: constrained in terms of our own DOFs 01899 { 01900 const unsigned int old_size = 01901 libmesh_cast_int<unsigned int>(elem_dofs.size()); 01902 01903 // Add new dependency dofs to the end of the current dof set 01904 elem_dofs.insert(elem_dofs.end(), 01905 dof_set.begin(), dof_set.end()); 01906 01907 elem_dofs.insert(elem_dofs.end(), 01908 dof_set.begin(), dof_set.end()); 01909 01910 // Now we can build the constraint matrix and vector. 01911 // Note that resize also zeros for a DenseMatrix and DenseVector 01912 C.resize (old_size, 01913 libmesh_cast_int<unsigned int>(elem_dofs.size())); 01914 H.resize (old_size); 01915 01916 // Create the C constraint matrix. 01917 for (unsigned int i=0; i != old_size; i++) 01918 if (this->is_constrained_dof(elem_dofs[i])) 01919 { 01920 // If the DOF is constrained 01921 DofConstraints::const_iterator 01922 pos = _dof_constraints.find(elem_dofs[i]); 01923 01924 libmesh_assert (pos != _dof_constraints.end()); 01925 01926 const DofConstraintRow& constraint_row = pos->second.first; 01927 01928 // p refinement creates empty constraint rows 01929 // libmesh_assert (!constraint_row.empty()); 01930 01931 for (DofConstraintRow::const_iterator 01932 it=constraint_row.begin(); it != constraint_row.end(); 01933 ++it) 01934 for (unsigned int j=0; j != elem_dofs.size(); j++) 01935 if (elem_dofs[j] == it->first) 01936 C(i,j) = it->second; 01937 01938 H(i) = pos->second.second; 01939 } 01940 else 01941 { 01942 C(i,i) = 1.; 01943 } 01944 01945 // May need to do this recursively. It is possible 01946 // that we just replaced a constrained DOF with another 01947 // constrained DOF. 01948 DenseMatrix<Number> Cnew; 01949 DenseVector<Number> Hnew; 01950 01951 this->build_constraint_matrix_and_vector (Cnew, Hnew, elem_dofs, true); 01952 01953 if ((C.n() == Cnew.m()) && // If the constraint matrix 01954 (Cnew.n() == elem_dofs.size())) // is constrained... 01955 { 01956 C.right_multiply(Cnew); 01957 01958 // If x = Cy + h and y = Dz + g 01959 // Then x = (CD)z + (Cg + h) 01960 C.vector_mult_add(H, 1, Hnew); 01961 } 01962 01963 libmesh_assert_equal_to (C.n(), elem_dofs.size()); 01964 } 01965 01966 if (!called_recursively) 01967 STOP_LOG("build_constraint_matrix_and_vector()", "DofMap"); 01968 }
| AutoPtr< SparsityPattern::Build > libMesh::DofMap::build_sparsity | ( | const MeshBase & | mesh | ) | const [private] |
Builds a sparsity pattern
Definition at line 54 of file dof_map.C.
References libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::MeshBase::is_prepared(), libMesh::out, libMesh::Threads::parallel_reduce(), and libMesh::MeshBase::processor_id().
Referenced by compute_sparsity().
00055 { 00056 libmesh_assert (mesh.is_prepared()); 00057 libmesh_assert (this->n_variables()); 00058 00059 START_LOG("build_sparsity()", "DofMap"); 00060 00061 // Compute the sparsity structure of the global matrix. This can be 00062 // fed into a PetscMatrix to allocate exacly the number of nonzeros 00063 // necessary to store the matrix. This algorithm should be linear 00064 // in the (# of elements)*(# nodes per element) 00065 00066 // We can be more efficient in the threaded sparsity pattern assembly 00067 // if we don't need the exact pattern. For some sparse matrix formats 00068 // a good upper bound will suffice. 00069 00070 // See if we need to include sparsity pattern entries for coupling 00071 // between neighbor dofs 00072 bool implicit_neighbor_dofs = this->use_coupled_neighbor_dofs(mesh); 00073 00074 // We can compute the sparsity pattern in parallel on multiple 00075 // threads. The goal is for each thread to compute the full sparsity 00076 // pattern for a subset of elements. These sparsity patterns can 00077 // be efficiently merged in the SparsityPattern::Build::join() 00078 // method, especially if there is not too much overlap between them. 00079 // Even better, if the full sparsity pattern is not needed then 00080 // the number of nonzeros per row can be estimated from the 00081 // sparsity patterns created on each thread. 00082 AutoPtr<SparsityPattern::Build> sp 00083 (new SparsityPattern::Build (mesh, 00084 *this, 00085 this->_dof_coupling, 00086 implicit_neighbor_dofs, 00087 need_full_sparsity_pattern)); 00088 00089 Threads::parallel_reduce (ConstElemRange (mesh.active_local_elements_begin(), 00090 mesh.active_local_elements_end()), *sp); 00091 00092 sp->parallel_sync(); 00093 00094 #ifndef NDEBUG 00095 // Avoid declaring these variables unless asserts are enabled. 00096 const processor_id_type proc_id = mesh.processor_id(); 00097 const dof_id_type n_dofs_on_proc = this->n_dofs_on_processor(proc_id); 00098 #endif 00099 libmesh_assert_equal_to (sp->sparsity_pattern.size(), n_dofs_on_proc); 00100 00101 STOP_LOG("build_sparsity()", "DofMap"); 00102 00103 // Check to see if we have any extra stuff to add to the sparsity_pattern 00104 if (_extra_sparsity_function) 00105 { 00106 if (_augment_sparsity_pattern) 00107 { 00108 libmesh_here(); 00109 libMesh::out << "WARNING: You have specified both an extra sparsity function and object.\n" 00110 << " Are you sure this is what you meant to do??" 00111 << std::endl; 00112 } 00113 00114 _extra_sparsity_function 00115 (sp->sparsity_pattern, sp->n_nz, 00116 sp->n_oz, _extra_sparsity_context); 00117 } 00118 00119 if (_augment_sparsity_pattern) 00120 _augment_sparsity_pattern->augment_sparsity_pattern 00121 (sp->sparsity_pattern, sp->n_nz, sp->n_oz); 00122 00123 return sp; 00124 }
| void libMesh::DofMap::clear | ( | ) |
Free all memory associated with the object, but keep the mesh pointer.
Definition at line 798 of file dof_map.C.
References _dof_constraints, _end_df, _end_old_df, _first_df, _first_old_df, _matrices, _n_dfs, _n_old_dfs, _send_list, _variable_groups, _variables, clear_sparsity(), and need_full_sparsity_pattern.
Referenced by ~DofMap().
00799 { 00800 // we don't want to clear 00801 // the coupling matrix! 00802 // It should not change... 00803 //_dof_coupling->clear(); 00804 00805 _variables.clear(); 00806 _variable_groups.clear(); 00807 _first_df.clear(); 00808 _end_df.clear(); 00809 _send_list.clear(); 00810 this->clear_sparsity(); 00811 need_full_sparsity_pattern = false; 00812 00813 #ifdef LIBMESH_ENABLE_AMR 00814 00815 _dof_constraints.clear(); 00816 _n_old_dfs = 0; 00817 _first_old_df.clear(); 00818 _end_old_df.clear(); 00819 00820 #endif 00821 00822 _matrices.clear(); 00823 00824 _n_dfs = 0; 00825 }
| void libMesh::DofMap::clear_sparsity | ( | ) |
Clears the sparsity pattern
Definition at line 1480 of file dof_map.C.
References _n_nz, _n_oz, _sp, libMesh::AutoPtr< Tp >::get(), need_full_sparsity_pattern, and libMesh::AutoPtr< Tp >::reset().
Referenced by clear(), libMesh::ImplicitSystem::reinit(), and libMesh::EigenSystem::reinit().
01481 { 01482 if (need_full_sparsity_pattern) 01483 { 01484 libmesh_assert(_sp.get()); 01485 libmesh_assert(!_n_nz || _n_nz == &_sp->n_nz); 01486 libmesh_assert(!_n_oz || _n_oz == &_sp->n_oz); 01487 _sp.reset(); 01488 } 01489 else 01490 { 01491 libmesh_assert(!_sp.get()); 01492 delete _n_nz; 01493 delete _n_oz; 01494 } 01495 _n_nz = NULL; 01496 _n_oz = NULL; 01497 }
| void libMesh::DofMap::compute_sparsity | ( | const MeshBase & | mesh | ) |
Computes the sparsity pattern for the matrices corresponding to proc_id and sends that data to Linear Algebra packages for preallocation of sparse matrices.
Definition at line 1443 of file dof_map.C.
References _matrices, _n_nz, _n_oz, _sp, build_sparsity(), end, need_full_sparsity_pattern, and libMesh::AutoPtr< Tp >::reset().
Referenced by libMesh::ImplicitSystem::init_matrices(), libMesh::EigenSystem::init_matrices(), libMesh::ImplicitSystem::reinit(), and libMesh::EigenSystem::reinit().
01444 { 01445 _sp = this->build_sparsity(mesh); 01446 01447 // It is possible that some \p SparseMatrix implementations want to 01448 // see it. Let them see it before we throw it away. 01449 std::vector<SparseMatrix<Number>* >::const_iterator 01450 pos = _matrices.begin(), 01451 end = _matrices.end(); 01452 01453 // If we need the full sparsity pattern, then we share a view of its 01454 // arrays, and we pass it in to the matrices. 01455 if (need_full_sparsity_pattern) 01456 { 01457 _n_nz = &_sp->n_nz; 01458 _n_oz = &_sp->n_oz; 01459 01460 for (; pos != end; ++pos) 01461 (*pos)->update_sparsity_pattern (_sp->sparsity_pattern); 01462 } 01463 // If we don't need the full sparsity pattern anymore, steal the 01464 // arrays we do need and free the rest of the memory 01465 else 01466 { 01467 if (!_n_nz) 01468 _n_nz = new std::vector<dof_id_type>(); 01469 _n_nz->swap(_sp->n_nz); 01470 if (!_n_oz) 01471 _n_oz = new std::vector<dof_id_type>(); 01472 _n_oz->swap(_sp->n_oz); 01473 01474 _sp.reset(); 01475 } 01476 }
| void libMesh::DofMap::constrain_element_dyad_matrix | ( | DenseVector< Number > & | v, | |
| DenseVector< Number > & | w, | |||
| std::vector< dof_id_type > & | row_dofs, | |||
| bool | asymmetric_constraint_rows = true | |||
| ) | const [inline] |
Constrains a dyadic element matrix B = v w'. This method requires the element matrix to be square, in which case the elem_dofs correspond to the global DOF indices of both the rows and columns of the element matrix. For this case the rows and columns of the matrix necessarily correspond to variables of the same approximation order.
Definition at line 1475 of file dof_map_constraints.C.
References _dof_constraints, build_constraint_matrix(), is_constrained_dof(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::size(), and libMesh::DenseMatrix< T >::vector_mult_transpose().
01479 { 01480 libmesh_assert_equal_to (v.size(), row_dofs.size()); 01481 libmesh_assert_equal_to (w.size(), row_dofs.size()); 01482 01483 // check for easy return 01484 if (this->_dof_constraints.empty()) 01485 return; 01486 01487 // The constrained RHS is built up as R^T F. 01488 DenseMatrix<Number> R; 01489 01490 this->build_constraint_matrix (R, row_dofs); 01491 01492 START_LOG("cnstrn_elem_dyad_mat()", "DofMap"); 01493 01494 // It is possible that the vector is not constrained at all. 01495 if ((R.m() == v.size()) && 01496 (R.n() == row_dofs.size())) // if the RHS is constrained 01497 { 01498 // Compute the matrix-vector products 01499 DenseVector<Number> old_v(v); 01500 DenseVector<Number> old_w(w); 01501 01502 // compute matrix/vector product 01503 R.vector_mult_transpose(v, old_v); 01504 R.vector_mult_transpose(w, old_w); 01505 01506 libmesh_assert_equal_to (row_dofs.size(), v.size()); 01507 libmesh_assert_equal_to (row_dofs.size(), w.size()); 01508 01509 /* Constrain only v, not w. */ 01510 01511 for (unsigned int i=0; i<row_dofs.size(); i++) 01512 if (this->is_constrained_dof(row_dofs[i])) 01513 { 01514 // If the DOF is constrained 01515 DofConstraints::const_iterator 01516 pos = _dof_constraints.find(row_dofs[i]); 01517 01518 libmesh_assert (pos != _dof_constraints.end()); 01519 01520 v(i) = 0; 01521 } 01522 } // end if the RHS is constrained. 01523 01524 STOP_LOG("cnstrn_elem_dyad_mat()", "DofMap"); 01525 }
| void libMesh::DofMap::constrain_element_matrix | ( | DenseMatrix< Number > & | matrix, | |
| std::vector< dof_id_type > & | row_dofs, | |||
| std::vector< dof_id_type > & | col_dofs, | |||
| bool | asymmetric_constraint_rows = true | |||
| ) | const [inline] |
Constrains the element matrix. This method allows the element matrix to be non-square, in which case the row_dofs and col_dofs may be of different size and correspond to variables approximated in different spaces.
Definition at line 1347 of file dof_map_constraints.C.
References _dof_constraints, build_constraint_matrix(), is_constrained_dof(), libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), and libMesh::DenseMatrix< T >::right_multiply().
01351 { 01352 libmesh_assert_equal_to (row_dofs.size(), matrix.m()); 01353 libmesh_assert_equal_to (col_dofs.size(), matrix.n()); 01354 01355 // check for easy return 01356 if (this->_dof_constraints.empty()) 01357 return; 01358 01359 // The constrained matrix is built up as R^T K C. 01360 DenseMatrix<Number> R; 01361 DenseMatrix<Number> C; 01362 01363 // Safeguard against the user passing us the same 01364 // object for row_dofs and col_dofs. If that is done 01365 // the calls to build_matrix would fail 01366 std::vector<dof_id_type> orig_row_dofs(row_dofs); 01367 std::vector<dof_id_type> orig_col_dofs(col_dofs); 01368 01369 this->build_constraint_matrix (R, orig_row_dofs); 01370 this->build_constraint_matrix (C, orig_col_dofs); 01371 01372 START_LOG("constrain_elem_matrix()", "DofMap"); 01373 01374 row_dofs = orig_row_dofs; 01375 col_dofs = orig_col_dofs; 01376 01377 01378 // It is possible that the matrix is not constrained at all. 01379 if ((R.m() == matrix.m()) && 01380 (R.n() == row_dofs.size()) && 01381 (C.m() == matrix.n()) && 01382 (C.n() == col_dofs.size())) // If the matrix is constrained 01383 { 01384 // K_constrained = R^T K C 01385 matrix.left_multiply_transpose (R); 01386 matrix.right_multiply (C); 01387 01388 01389 libmesh_assert_equal_to (matrix.m(), row_dofs.size()); 01390 libmesh_assert_equal_to (matrix.n(), col_dofs.size()); 01391 01392 01393 for (unsigned int i=0; i<row_dofs.size(); i++) 01394 if (this->is_constrained_dof(row_dofs[i])) 01395 { 01396 for (unsigned int j=0; j<matrix.n(); j++) 01397 { 01398 if(row_dofs[i] != col_dofs[j]) 01399 matrix(i,j) = 0.; 01400 else // If the DOF is constrained 01401 matrix(i,j) = 1.; 01402 } 01403 01404 if (asymmetric_constraint_rows) 01405 { 01406 DofConstraints::const_iterator 01407 pos = _dof_constraints.find(row_dofs[i]); 01408 01409 libmesh_assert (pos != _dof_constraints.end()); 01410 01411 const DofConstraintRow& constraint_row = pos->second.first; 01412 01413 libmesh_assert (!constraint_row.empty()); 01414 01415 for (DofConstraintRow::const_iterator 01416 it=constraint_row.begin(); it != constraint_row.end(); 01417 ++it) 01418 for (unsigned int j=0; j<col_dofs.size(); j++) 01419 if (col_dofs[j] == it->first) 01420 matrix(i,j) = -it->second; 01421 } 01422 } 01423 } // end if is constrained... 01424 01425 STOP_LOG("constrain_elem_matrix()", "DofMap"); 01426 }
| void libMesh::DofMap::constrain_element_matrix | ( | DenseMatrix< Number > & | matrix, | |
| std::vector< dof_id_type > & | elem_dofs, | |||
| bool | asymmetric_constraint_rows = true | |||
| ) | const [inline] |
Constrains the element matrix. This method requires the element matrix to be square, in which case the elem_dofs correspond to the global DOF indices of both the rows and columns of the element matrix. For this case the rows and columns of the matrix necessarily correspond to variables of the same approximation order.
If asymmetric_constraint_rows is set to true (as it is by default), constraint row equations will be reinforced in a way which breaks matrix symmetry but makes inexact linear solver solutions more likely to satisfy hanging node constraints.
Definition at line 1106 of file dof_map_constraints.C.
References _dof_constraints, build_constraint_matrix(), is_constrained_dof(), libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), and libMesh::DenseMatrix< T >::right_multiply().
01109 { 01110 libmesh_assert_equal_to (elem_dofs.size(), matrix.m()); 01111 libmesh_assert_equal_to (elem_dofs.size(), matrix.n()); 01112 01113 // check for easy return 01114 if (this->_dof_constraints.empty()) 01115 return; 01116 01117 // The constrained matrix is built up as C^T K C. 01118 DenseMatrix<Number> C; 01119 01120 01121 this->build_constraint_matrix (C, elem_dofs); 01122 01123 START_LOG("constrain_elem_matrix()", "DofMap"); 01124 01125 // It is possible that the matrix is not constrained at all. 01126 if ((C.m() == matrix.m()) && 01127 (C.n() == elem_dofs.size())) // It the matrix is constrained 01128 { 01129 // Compute the matrix-matrix-matrix product C^T K C 01130 matrix.left_multiply_transpose (C); 01131 matrix.right_multiply (C); 01132 01133 01134 libmesh_assert_equal_to (matrix.m(), matrix.n()); 01135 libmesh_assert_equal_to (matrix.m(), elem_dofs.size()); 01136 libmesh_assert_equal_to (matrix.n(), elem_dofs.size()); 01137 01138 01139 for (unsigned int i=0; i<elem_dofs.size(); i++) 01140 // If the DOF is constrained 01141 if (this->is_constrained_dof(elem_dofs[i])) 01142 { 01143 for (unsigned int j=0; j<matrix.n(); j++) 01144 matrix(i,j) = 0.; 01145 01146 matrix(i,i) = 1.; 01147 01148 if (asymmetric_constraint_rows) 01149 { 01150 DofConstraints::const_iterator 01151 pos = _dof_constraints.find(elem_dofs[i]); 01152 01153 libmesh_assert (pos != _dof_constraints.end()); 01154 01155 const DofConstraintRow& constraint_row = pos->second.first; 01156 01157 // This is an overzealous assertion in the presence of 01158 // heterogenous constraints: we now can constrain "u_i = c" 01159 // with no other u_j terms involved. 01160 // 01161 // libmesh_assert (!constraint_row.empty()); 01162 01163 for (DofConstraintRow::const_iterator 01164 it=constraint_row.begin(); it != constraint_row.end(); 01165 ++it) 01166 for (unsigned int j=0; j<elem_dofs.size(); j++) 01167 if (elem_dofs[j] == it->first) 01168 matrix(i,j) = -it->second; 01169 } 01170 } 01171 } // end if is constrained... 01172 01173 STOP_LOG("constrain_elem_matrix()", "DofMap"); 01174 }
| void libMesh::DofMap::constrain_element_matrix_and_vector | ( | DenseMatrix< Number > & | matrix, | |
| DenseVector< Number > & | rhs, | |||
| std::vector< dof_id_type > & | elem_dofs, | |||
| bool | asymmetric_constraint_rows = true | |||
| ) | const [inline] |
Constrains the element matrix and vector. This method requires the element matrix to be square, in which case the elem_dofs correspond to the global DOF indices of both the rows and columns of the element matrix. For this case the rows and columns of the matrix necessarily correspond to variables of the same approximation order.
Definition at line 1178 of file dof_map_constraints.C.
References _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(), and libMesh::DenseMatrix< T >::vector_mult_transpose().
01182 { 01183 libmesh_assert_equal_to (elem_dofs.size(), matrix.m()); 01184 libmesh_assert_equal_to (elem_dofs.size(), matrix.n()); 01185 libmesh_assert_equal_to (elem_dofs.size(), rhs.size()); 01186 01187 // check for easy return 01188 if (this->_dof_constraints.empty()) 01189 return; 01190 01191 // The constrained matrix is built up as C^T K C. 01192 // The constrained RHS is built up as C^T F 01193 DenseMatrix<Number> C; 01194 01195 this->build_constraint_matrix (C, elem_dofs); 01196 01197 START_LOG("cnstrn_elem_mat_vec()", "DofMap"); 01198 01199 // It is possible that the matrix is not constrained at all. 01200 if ((C.m() == matrix.m()) && 01201 (C.n() == elem_dofs.size())) // It the matrix is constrained 01202 { 01203 // Compute the matrix-matrix-matrix product C^T K C 01204 matrix.left_multiply_transpose (C); 01205 matrix.right_multiply (C); 01206 01207 01208 libmesh_assert_equal_to (matrix.m(), matrix.n()); 01209 libmesh_assert_equal_to (matrix.m(), elem_dofs.size()); 01210 libmesh_assert_equal_to (matrix.n(), elem_dofs.size()); 01211 01212 01213 for (unsigned int i=0; i<elem_dofs.size(); i++) 01214 if (this->is_constrained_dof(elem_dofs[i])) 01215 { 01216 for (unsigned int j=0; j<matrix.n(); j++) 01217 matrix(i,j) = 0.; 01218 01219 // If the DOF is constrained 01220 matrix(i,i) = 1.; 01221 01222 // This will put a nonsymmetric entry in the constraint 01223 // row to ensure that the linear system produces the 01224 // correct value for the constrained DOF. 01225 if (asymmetric_constraint_rows) 01226 { 01227 DofConstraints::const_iterator 01228 pos = _dof_constraints.find(elem_dofs[i]); 01229 01230 libmesh_assert (pos != _dof_constraints.end()); 01231 01232 const DofConstraintRow& constraint_row = pos->second.first; 01233 01234 // p refinement creates empty constraint rows 01235 // libmesh_assert (!constraint_row.empty()); 01236 01237 for (DofConstraintRow::const_iterator 01238 it=constraint_row.begin(); it != constraint_row.end(); 01239 ++it) 01240 for (unsigned int j=0; j<elem_dofs.size(); j++) 01241 if (elem_dofs[j] == it->first) 01242 matrix(i,j) = -it->second; 01243 } 01244 } 01245 01246 01247 // Compute the matrix-vector product C^T F 01248 DenseVector<Number> old_rhs(rhs); 01249 01250 // compute matrix/vector product 01251 C.vector_mult_transpose(rhs, old_rhs); 01252 } // end if is constrained... 01253 01254 STOP_LOG("cnstrn_elem_mat_vec()", "DofMap"); 01255 }
| void libMesh::DofMap::constrain_element_vector | ( | DenseVector< Number > & | rhs, | |
| std::vector< dof_id_type > & | dofs, | |||
| bool | asymmetric_constraint_rows = true | |||
| ) | const [inline] |
Constrains the element vector.
Definition at line 1430 of file dof_map_constraints.C.
References _dof_constraints, build_constraint_matrix(), is_constrained_dof(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::size(), and libMesh::DenseMatrix< T >::vector_mult_transpose().
01433 { 01434 libmesh_assert_equal_to (rhs.size(), row_dofs.size()); 01435 01436 // check for easy return 01437 if (this->_dof_constraints.empty()) 01438 return; 01439 01440 // The constrained RHS is built up as R^T F. 01441 DenseMatrix<Number> R; 01442 01443 this->build_constraint_matrix (R, row_dofs); 01444 01445 START_LOG("constrain_elem_vector()", "DofMap"); 01446 01447 // It is possible that the vector is not constrained at all. 01448 if ((R.m() == rhs.size()) && 01449 (R.n() == row_dofs.size())) // if the RHS is constrained 01450 { 01451 // Compute the matrix-vector product 01452 DenseVector<Number> old_rhs(rhs); 01453 R.vector_mult_transpose(rhs, old_rhs); 01454 01455 libmesh_assert_equal_to (row_dofs.size(), rhs.size()); 01456 01457 for (unsigned int i=0; i<row_dofs.size(); i++) 01458 if (this->is_constrained_dof(row_dofs[i])) 01459 { 01460 // If the DOF is constrained 01461 DofConstraints::const_iterator 01462 pos = _dof_constraints.find(row_dofs[i]); 01463 01464 libmesh_assert (pos != _dof_constraints.end()); 01465 01466 rhs(i) = 0; 01467 } 01468 } // end if the RHS is constrained. 01469 01470 STOP_LOG("constrain_elem_vector()", "DofMap"); 01471 }
| void libMesh::DofMap::constrain_nothing | ( | std::vector< dof_id_type > & | dofs | ) | const |
Does not actually constrain anything, but modifies dofs in the same way as any of the constrain functions would do, i.e. adds those dofs in terms of which any of the existing dofs is constrained.
Definition at line 1529 of file dof_map_constraints.C.
References _dof_constraints, and build_constraint_matrix().
01530 { 01531 // check for easy return 01532 if (this->_dof_constraints.empty()) 01533 return; 01534 01535 // All the work is done by \p build_constraint_matrix. We just need 01536 // a dummy matrix. 01537 DenseMatrix<Number> R; 01538 this->build_constraint_matrix (R, dofs); 01539 }
| void libMesh::DofMap::constrain_p_dofs | ( | unsigned int | var, | |
| const Elem * | elem, | |||
| unsigned int | s, | |||
| unsigned int | p | |||
| ) |
Constrains degrees of freedom on side s of element elem which correspond to variable number var and to p refinement levels above p.
Definition at line 3011 of file dof_map_constraints.C.
References _dof_constraints, libMesh::Elem::dim(), libMesh::DofObject::dof_number(), libMesh::Elem::get_node(), libMesh::Elem::is_node_on_side(), libMesh::Elem::is_vertex(), libMesh::DofObject::n_comp(), libMesh::FEInterface::n_dofs_at_node(), libMesh::Elem::n_nodes(), libMesh::Elem::n_sides(), libMesh::FEType::order, libMesh::Elem::p_level(), libMesh::Threads::spin_mtx, sys_number(), libMesh::Elem::type(), and variable_type().
Referenced by libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), and libMesh::FEGenericBase< OutputType >::compute_proj_constraints().
03015 { 03016 // We're constraining dofs on elem which correspond to p refinement 03017 // levels above p - this only makes sense if elem's p refinement 03018 // level is above p. 03019 libmesh_assert_greater (elem->p_level(), p); 03020 libmesh_assert_less (s, elem->n_sides()); 03021 03022 const unsigned int sys_num = this->sys_number(); 03023 const unsigned int dim = elem->dim(); 03024 ElemType type = elem->type(); 03025 FEType low_p_fe_type = this->variable_type(var); 03026 FEType high_p_fe_type = this->variable_type(var); 03027 low_p_fe_type.order = static_cast<Order>(low_p_fe_type.order + p); 03028 high_p_fe_type.order = static_cast<Order>(high_p_fe_type.order + 03029 elem->p_level()); 03030 03031 const unsigned int n_nodes = elem->n_nodes(); 03032 for (unsigned int n = 0; n != n_nodes; ++n) 03033 if (elem->is_node_on_side(n, s)) 03034 { 03035 const Node * const node = elem->get_node(n); 03036 const unsigned int low_nc = 03037 FEInterface::n_dofs_at_node (dim, low_p_fe_type, type, n); 03038 const unsigned int high_nc = 03039 FEInterface::n_dofs_at_node (dim, high_p_fe_type, type, n); 03040 03041 // since we may be running this method concurretly 03042 // on multiple threads we need to acquire a lock 03043 // before modifying the _dof_constraints object. 03044 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx); 03045 03046 if (elem->is_vertex(n)) 03047 { 03048 // Add "this is zero" constraint rows for high p vertex 03049 // dofs 03050 for (unsigned int i = low_nc; i != high_nc; ++i) 03051 { 03052 _dof_constraints[node->dof_number(sys_num,var,i)].first.clear(); 03053 _dof_constraints[node->dof_number(sys_num,var,i)].second = 0.; 03054 } 03055 } 03056 else 03057 { 03058 const unsigned int total_dofs = node->n_comp(sys_num, var); 03059 libmesh_assert_greater_equal (total_dofs, high_nc); 03060 // Add "this is zero" constraint rows for high p 03061 // non-vertex dofs, which are numbered in reverse 03062 for (unsigned int j = low_nc; j != high_nc; ++j) 03063 { 03064 const unsigned int i = total_dofs - j - 1; 03065 _dof_constraints[node->dof_number(sys_num,var,i)].first.clear(); 03066 _dof_constraints[node->dof_number(sys_num,var,i)].second = 0.; 03067 } 03068 } 03069 } 03070 }
| DofConstraints::const_iterator libMesh::DofMap::constraint_rows_begin | ( | ) | const [inline] |
Returns an iterator pointing to the first DoF constraint row
Definition at line 558 of file dof_map.h.
References _dof_constraints.
00559 { return _dof_constraints.begin(); }
| DofConstraints::const_iterator libMesh::DofMap::constraint_rows_end | ( | ) | const [inline] |
Returns an iterator pointing just past the last DoF constraint row
Definition at line 564 of file dof_map.h.
References _dof_constraints.
00565 { return _dof_constraints.end(); }
Rebuilds the raw degree of freedom and DofObject constraints. A time is specified for use in building time-dependent Dirichlet constraints.
Definition at line 856 of file dof_map_constraints.C.
References _dirichlet_boundaries, _dof_constraints, _node_constraints, _periodic_boundaries, libMesh::CommWorld, libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), libMesh::StoredRange< iterator_type, object_type >::empty(), libMesh::MeshBase::is_prepared(), libMesh::MeshBase::is_serial(), libMesh::MeshBase::local_elements_begin(), libMesh::MeshBase::local_elements_end(), libMesh::Parallel::Communicator::max(), libMesh::MeshBase::mesh_dimension(), n_variables(), libMesh::Threads::parallel_for(), libMesh::StoredRange< iterator_type, object_type >::reset(), libMesh::MeshBase::sub_point_locator(), and libMesh::Parallel::Communicator::verify().
Referenced by libMesh::EquationSystems::allgather(), and libMesh::EquationSystems::reinit().
00857 { 00858 parallel_only(); 00859 00860 START_LOG("create_dof_constraints()", "DofMap"); 00861 00862 libmesh_assert (mesh.is_prepared()); 00863 00864 const unsigned int dim = mesh.mesh_dimension(); 00865 00866 // We might get constraint equations from AMR hanging nodes in 2D/3D 00867 // or from boundary conditions in any dimension 00868 const bool possible_local_constraints = false 00869 #ifdef LIBMESH_ENABLE_AMR 00870 || dim > 1 00871 #endif 00872 #ifdef LIBMESH_ENABLE_PERIODIC 00873 || !_periodic_boundaries->empty() 00874 #endif 00875 #ifdef LIBMESH_ENABLE_DIRICHLET 00876 || !_dirichlet_boundaries->empty() 00877 #endif 00878 ; 00879 00880 // Even if we don't have constraints, another processor might. 00881 bool possible_global_constraints = possible_local_constraints; 00882 #if defined(LIBMESH_ENABLE_PERIODIC) || defined(LIBMESH_ENABLE_DIRICHLET) || defined(LIBMESH_ENABLE_AMR) 00883 libmesh_assert(CommWorld.verify(mesh.is_serial())); 00884 00885 if (!mesh.is_serial()) 00886 CommWorld.max(possible_global_constraints); 00887 #endif 00888 00889 if (!possible_global_constraints) 00890 { 00891 // make sure we stop logging though 00892 STOP_LOG("create_dof_constraints()", "DofMap"); 00893 return; 00894 } 00895 00896 // Here we build the hanging node constraints. This is done 00897 // by enforcing the condition u_a = u_b along hanging sides. 00898 // u_a = u_b is collocated at the nodes of side a, which gives 00899 // one row of the constraint matrix. 00900 00901 // define the range of elements of interest 00902 ConstElemRange range; 00903 if (possible_local_constraints) 00904 { 00905 // With SerialMesh or a serial ParallelMesh, every processor 00906 // computes every constraint 00907 MeshBase::const_element_iterator 00908 elem_begin = mesh.elements_begin(), 00909 elem_end = mesh.elements_end(); 00910 00911 // With a parallel ParallelMesh, processors compute only 00912 // their local constraints 00913 if (!mesh.is_serial()) 00914 { 00915 elem_begin = mesh.local_elements_begin(); 00916 elem_end = mesh.local_elements_end(); 00917 } 00918 00919 // set the range to contain the specified elements 00920 range.reset (elem_begin, elem_end); 00921 } 00922 else 00923 range.reset (mesh.elements_end(), mesh.elements_end()); 00924 00925 // compute_periodic_constraints requires a point_locator() from our 00926 // Mesh, that point_locator() construction is threaded. Rather than 00927 // nest threads within threads we'll make sure it's preconstructed. 00928 #ifdef LIBMESH_ENABLE_PERIODIC 00929 if (!_periodic_boundaries->empty() && !range.empty()) 00930 mesh.sub_point_locator(); 00931 #endif 00932 00933 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 00934 // recalculate node constraints from scratch 00935 _node_constraints.clear(); 00936 00937 Threads::parallel_for (range, 00938 ComputeNodeConstraints (_node_constraints, 00939 *this, 00940 #ifdef LIBMESH_ENABLE_PERIODIC 00941 *_periodic_boundaries, 00942 #endif 00943 mesh)); 00944 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 00945 00946 00947 // recalculate dof constraints from scratch 00948 _dof_constraints.clear(); 00949 00950 // Look at all the variables in the system. Reset the element 00951 // range at each iteration -- there is no need to reconstruct it. 00952 for (unsigned int variable_number=0; variable_number<this->n_variables(); 00953 ++variable_number, range.reset()) 00954 Threads::parallel_for (range, 00955 ComputeConstraints (_dof_constraints, 00956 *this, 00957 #ifdef LIBMESH_ENABLE_PERIODIC 00958 *_periodic_boundaries, 00959 #endif 00960 mesh, 00961 variable_number)); 00962 00963 #ifdef LIBMESH_ENABLE_DIRICHLET 00964 for (DirichletBoundaries::iterator 00965 i = _dirichlet_boundaries->begin(); 00966 i != _dirichlet_boundaries->end(); ++i, range.reset()) 00967 { 00968 Threads::parallel_for 00969 (range, 00970 ConstrainDirichlet(*this, mesh, time, **i) 00971 ); 00972 } 00973 #endif // LIBMESH_ENABLE_DIRICHLET 00974 00975 STOP_LOG("create_dof_constraints()", "DofMap"); 00976 }
| void libMesh::ReferenceCounter::disable_print_counter_info | ( | ) | [static, inherited] |
Definition at line 106 of file reference_counter.C.
References libMesh::ReferenceCounter::_enable_print_counter.
00107 { 00108 _enable_print_counter = false; 00109 return; 00110 }
| void libMesh::DofMap::distribute_dofs | ( | MeshBase & | mesh | ) |
Distrubute dofs on the current mesh. Also builds the send list for processor proc_id, which defaults to 0 for ease of use in serial applications.
Definition at line 829 of file dof_map.C.
References _end_df, _end_old_df, _first_df, _first_old_df, _n_dfs, _n_old_dfs, _send_list, add_neighbors_to_send_list(), libMesh::Parallel::Communicator::allgather(), libMesh::CommWorld, distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), elem_ptr(), libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), invalidate_dofs(), libMesh::MeshBase::is_prepared(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), libMesh::n_processors(), node_ptr(), libMesh::MeshBase::nodes_begin(), libMesh::MeshBase::nodes_end(), libMesh::on_command_line(), libMesh::processor_id(), reinit(), and set_nonlocal_dof_objects().
Referenced by libMesh::EquationSystems::allgather(), and libMesh::EquationSystems::reinit().
00830 { 00831 // This function must be run on all processors at once 00832 parallel_only(); 00833 00834 // Log how long it takes to distribute the degrees of freedom 00835 START_LOG("distribute_dofs()", "DofMap"); 00836 00837 libmesh_assert (mesh.is_prepared()); 00838 00839 const processor_id_type proc_id = libMesh::processor_id(); 00840 const processor_id_type n_proc = libMesh::n_processors(); 00841 00842 // libmesh_assert_greater (this->n_variables(), 0); 00843 libmesh_assert_less (proc_id, n_proc); 00844 00845 // re-init in case the mesh has changed 00846 this->reinit(mesh); 00847 00848 // By default distribute variables in a 00849 // var-major fashion, but allow run-time 00850 // specification 00851 bool node_major_dofs = libMesh::on_command_line ("--node_major_dofs"); 00852 00853 // The DOF counter, will be incremented as we encounter 00854 // new degrees of freedom 00855 dof_id_type next_free_dof = 0; 00856 00857 // Clear the send list before we rebuild it 00858 _send_list.clear(); 00859 00860 // Set temporary DOF indices on this processor 00861 if (node_major_dofs) 00862 this->distribute_local_dofs_node_major (next_free_dof, mesh); 00863 else 00864 this->distribute_local_dofs_var_major (next_free_dof, mesh); 00865 00866 // Get DOF counts on all processors 00867 std::vector<dof_id_type> dofs_on_proc(n_proc, 0); 00868 CommWorld.allgather(next_free_dof, dofs_on_proc); 00869 00870 // Resize and fill the _first_df and _end_df arrays 00871 #ifdef LIBMESH_ENABLE_AMR 00872 _first_old_df = _first_df; 00873 _end_old_df = _end_df; 00874 #endif 00875 00876 _first_df.resize(n_proc); 00877 _end_df.resize (n_proc); 00878 00879 // Get DOF offsets 00880 _first_df[0] = 0; 00881 for (processor_id_type i=1; i < n_proc; ++i) 00882 _first_df[i] = _end_df[i-1] = _first_df[i-1] + dofs_on_proc[i-1]; 00883 _end_df[n_proc-1] = _first_df[n_proc-1] + dofs_on_proc[n_proc-1]; 00884 00885 // Clear all the current DOF indices 00886 // (distribute_dofs expects them cleared!) 00887 this->invalidate_dofs(mesh); 00888 00889 next_free_dof = _first_df[proc_id]; 00890 00891 // Set permanent DOF indices on this processor 00892 if (node_major_dofs) 00893 this->distribute_local_dofs_node_major (next_free_dof, mesh); 00894 else 00895 this->distribute_local_dofs_var_major (next_free_dof, mesh); 00896 00897 libmesh_assert_equal_to (next_free_dof, _end_df[proc_id]); 00898 00899 //------------------------------------------------------------ 00900 // At this point, all n_comp and dof_number values on local 00901 // DofObjects should be correct, but a ParallelMesh might have 00902 // incorrect values on non-local DofObjects. Let's request the 00903 // correct values from each other processor. 00904 00905 if (libMesh::n_processors() > 1) 00906 { 00907 this->set_nonlocal_dof_objects(mesh.nodes_begin(), 00908 mesh.nodes_end(), 00909 mesh, &DofMap::node_ptr); 00910 00911 this->set_nonlocal_dof_objects(mesh.elements_begin(), 00912 mesh.elements_end(), 00913 mesh, &DofMap::elem_ptr); 00914 00915 #ifdef DEBUG 00916 MeshTools::libmesh_assert_valid_dof_ids(mesh); 00917 #endif 00918 } 00919 00920 // Set the total number of degrees of freedom 00921 #ifdef LIBMESH_ENABLE_AMR 00922 _n_old_dfs = _n_dfs; 00923 #endif 00924 _n_dfs = _end_df[n_proc-1]; 00925 00926 STOP_LOG("distribute_dofs()", "DofMap"); 00927 00928 // Note that in the add_neighbors_to_send_list nodes on processor 00929 // boundaries that are shared by multiple elements are added for 00930 // each element. 00931 this->add_neighbors_to_send_list(mesh); 00932 00933 // Here we used to clean up that data structure; now System and 00934 // EquationSystems call that for us, after we've added constraint 00935 // dependencies to the send_list too. 00936 // this->sort_send_list (); 00937 }
| void libMesh::DofMap::distribute_local_dofs_node_major | ( | dof_id_type & | next_free_dof, | |
| MeshBase & | mesh | |||
| ) | [private] |
Distributes the global degrees of freedom, for dofs on this processor. In this format all the degrees of freedom at a node/element are in contiguous blocks. Note in particular that the degrees of freedom for a given variable are not in contiguous blocks, as in the case of distribute_local_dofs_var_major. Starts at index next_free_dof, and increments it to the post-final index. If build_send_list is true, builds the send list. If false, clears and reserves the send list
Definition at line 940 of file dof_map.C.
References _n_SCALAR_dofs, libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::Elem::get_node(), libMesh::DofObject::invalid_id, libMesh::MeshTools::libmesh_assert_valid_procids< Node >(), libMesh::MeshBase::local_nodes_begin(), libMesh::MeshBase::local_nodes_end(), libMesh::DofObject::n_comp(), libMesh::DofObject::n_comp_group(), libMesh::Elem::n_nodes(), n_nodes, libMesh::n_processors(), libMesh::DofObject::n_var_groups(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::FEType::order, libMesh::processor_id(), libMesh::DofObject::processor_id(), libMeshEnums::SCALAR, libMesh::DofObject::set_vg_dof_base(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::Variable::type(), variable_group(), and libMesh::DofObject::vg_dof_base().
Referenced by distribute_dofs().
00942 { 00943 const unsigned int sys_num = this->sys_number(); 00944 const unsigned int n_var_groups = this->n_variable_groups(); 00945 00946 //------------------------------------------------------------------------- 00947 // First count and assign temporary numbers to local dofs 00948 MeshBase::element_iterator elem_it = mesh.active_local_elements_begin(); 00949 const MeshBase::element_iterator elem_end = mesh.active_local_elements_end(); 00950 00951 for ( ; elem_it != elem_end; ++elem_it) 00952 { 00953 // Only number dofs connected to active 00954 // elements on this processor. 00955 Elem* elem = *elem_it; 00956 const unsigned int n_nodes = elem->n_nodes(); 00957 00958 // First number the nodal DOFS 00959 for (unsigned int n=0; n<n_nodes; n++) 00960 { 00961 Node* node = elem->get_node(n); 00962 00963 for (unsigned vg=0; vg<n_var_groups; vg++) 00964 { 00965 const VariableGroup &vg_description(this->variable_group(vg)); 00966 00967 if( (vg_description.type().family != SCALAR) && 00968 (vg_description.active_on_subdomain(elem->subdomain_id())) ) 00969 { 00970 // assign dof numbers (all at once) if this is 00971 // our node and if they aren't already there 00972 if ((node->n_comp_group(sys_num,vg) > 0) && 00973 (node->processor_id() == libMesh::processor_id()) && 00974 (node->vg_dof_base(sys_num,vg) == 00975 DofObject::invalid_id)) 00976 { 00977 node->set_vg_dof_base(sys_num, 00978 vg, 00979 next_free_dof); 00980 next_free_dof += (vg_description.n_variables()* 00981 node->n_comp_group(sys_num,vg)); 00982 //node->debug_buffer(); 00983 } 00984 } 00985 } 00986 } 00987 00988 // Now number the element DOFS 00989 for (unsigned vg=0; vg<n_var_groups; vg++) 00990 { 00991 const VariableGroup &vg_description(this->variable_group(vg)); 00992 00993 if ( (vg_description.type().family != SCALAR) && 00994 (vg_description.active_on_subdomain(elem->subdomain_id())) ) 00995 if (elem->n_comp_group(sys_num,vg) > 0) 00996 { 00997 libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg), 00998 DofObject::invalid_id); 00999 01000 elem->set_vg_dof_base(sys_num, 01001 vg, 01002 next_free_dof); 01003 01004 next_free_dof += (vg_description.n_variables()* 01005 elem->n_comp(sys_num,vg)); 01006 } 01007 } 01008 } // done looping over elements 01009 01010 01011 // we may have missed assigning DOFs to nodes that we own 01012 // but to which we have no connected elements matching our 01013 // variable restriction criterion. this will happen, for example, 01014 // if variable V is restricted to subdomain S. We may not own 01015 // any elements which live in S, but we may own nodes which are 01016 // *connected* to elements which do. in this scenario these nodes 01017 // will presently have unnumbered DOFs. we need to take care of 01018 // them here since we own them and no other processor will touch them. 01019 { 01020 MeshBase::node_iterator node_it = mesh.local_nodes_begin(); 01021 const MeshBase::node_iterator node_end = mesh.local_nodes_end(); 01022 01023 for (; node_it != node_end; ++node_it) 01024 { 01025 Node *node = *node_it; 01026 libmesh_assert(node); 01027 01028 for (unsigned vg=0; vg<n_var_groups; vg++) 01029 { 01030 const VariableGroup &vg_description(this->variable_group(vg)); 01031 01032 if (node->n_comp_group(sys_num,vg)) 01033 if (node->vg_dof_base(sys_num,vg) == DofObject::invalid_id) 01034 { 01035 node->set_vg_dof_base (sys_num, 01036 vg, 01037 next_free_dof); 01038 01039 next_free_dof += (vg_description.n_variables()* 01040 node->n_comp(sys_num,vg)); 01041 } 01042 } 01043 } 01044 } 01045 01046 // Finally, count up the SCALAR dofs 01047 this->_n_SCALAR_dofs = 0; 01048 for (unsigned vg=0; vg<n_var_groups; vg++) 01049 { 01050 const VariableGroup &vg_description(this->variable_group(vg)); 01051 01052 if( vg_description.type().family == SCALAR ) 01053 { 01054 this->_n_SCALAR_dofs += (vg_description.n_variables()* 01055 vg_description.type().order); 01056 continue; 01057 } 01058 } 01059 01060 // Only increment next_free_dof if we're on the processor 01061 // that holds this SCALAR variable 01062 if ( libMesh::processor_id() == (libMesh::n_processors()-1) ) 01063 next_free_dof += _n_SCALAR_dofs; 01064 01065 #ifdef DEBUG 01066 { 01067 // std::cout << "next_free_dof=" << next_free_dof << std::endl 01068 // << "_n_SCALAR_dofs=" << _n_SCALAR_dofs << std::endl; 01069 01070 // Make sure we didn't miss any nodes 01071 MeshTools::libmesh_assert_valid_procids<Node>(mesh); 01072 01073 MeshBase::node_iterator node_it = mesh.local_nodes_begin(); 01074 const MeshBase::node_iterator node_end = mesh.local_nodes_end(); 01075 for (; node_it != node_end; ++node_it) 01076 { 01077 Node *obj = *node_it; 01078 libmesh_assert(obj); 01079 unsigned int n_var_g = obj->n_var_groups(this->sys_number()); 01080 for (unsigned int vg=0; vg != n_var_g; ++vg) 01081 { 01082 unsigned int n_comp_g = 01083 obj->n_comp_group(this->sys_number(), vg); 01084 dof_id_type my_first_dof = n_comp_g ? 01085 obj->vg_dof_base(this->sys_number(), vg) : 0; 01086 libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id); 01087 } 01088 } 01089 } 01090 #endif // DEBUG 01091 }
| void libMesh::DofMap::distribute_local_dofs_var_major | ( | dof_id_type & | next_free_dof, | |
| MeshBase & | mesh | |||
| ) | [private] |
Distributes the global degrees of freedom, for dofs on this processor. In this format the local degrees of freedom are in a contiguous block for each variable in the system. Starts at index next_free_dof, and increments it to the post-final index.
Definition at line 1095 of file dof_map.C.
References _n_SCALAR_dofs, libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::Elem::get_node(), libMesh::DofObject::invalid_id, libMesh::MeshTools::libmesh_assert_valid_procids< Node >(), libMesh::MeshBase::local_nodes_begin(), libMesh::MeshBase::local_nodes_end(), libMesh::DofObject::n_comp_group(), libMesh::Elem::n_nodes(), n_nodes, libMesh::n_processors(), libMesh::DofObject::n_var_groups(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::FEType::order, libMesh::processor_id(), libMesh::DofObject::processor_id(), libMeshEnums::SCALAR, libMesh::DofObject::set_vg_dof_base(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::Variable::type(), variable_group(), and libMesh::DofObject::vg_dof_base().
Referenced by distribute_dofs().
01097 { 01098 const unsigned int sys_num = this->sys_number(); 01099 const unsigned int n_var_groups = this->n_variable_groups(); 01100 01101 //------------------------------------------------------------------------- 01102 // First count and assign temporary numbers to local dofs 01103 for (unsigned vg=0; vg<n_var_groups; vg++) 01104 { 01105 const VariableGroup &vg_description(this->variable_group(vg)); 01106 01107 const unsigned int n_vars_in_group = vg_description.n_variables(); 01108 01109 // Skip the SCALAR dofs 01110 if (vg_description.type().family == SCALAR) 01111 continue; 01112 01113 MeshBase::element_iterator elem_it = mesh.active_local_elements_begin(); 01114 const MeshBase::element_iterator elem_end = mesh.active_local_elements_end(); 01115 01116 for ( ; elem_it != elem_end; ++elem_it) 01117 { 01118 // Only number dofs connected to active 01119 // elements on this processor. 01120 Elem* elem = *elem_it; 01121 01122 // ... and only variables which are active on 01123 // on this element's subdomain 01124 if (!vg_description.active_on_subdomain(elem->subdomain_id())) 01125 continue; 01126 01127 const unsigned int n_nodes = elem->n_nodes(); 01128 01129 // First number the nodal DOFS 01130 for (unsigned int n=0; n<n_nodes; n++) 01131 { 01132 Node* node = elem->get_node(n); 01133 01134 // assign dof numbers (all at once) if this is 01135 // our node and if they aren't already there 01136 if ((node->n_comp_group(sys_num,vg) > 0) && 01137 (node->processor_id() == libMesh::processor_id()) && 01138 (node->vg_dof_base(sys_num,vg) == 01139 DofObject::invalid_id)) 01140 { 01141 node->set_vg_dof_base(sys_num, 01142 vg, 01143 next_free_dof); 01144 01145 next_free_dof += (n_vars_in_group* 01146 node->n_comp_group(sys_num,vg)); 01147 } 01148 } 01149 01150 // Now number the element DOFS 01151 if (elem->n_comp_group(sys_num,vg) > 0) 01152 { 01153 libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg), 01154 DofObject::invalid_id); 01155 01156 elem->set_vg_dof_base(sys_num, 01157 vg, 01158 next_free_dof); 01159 01160 next_free_dof += (n_vars_in_group* 01161 elem->n_comp_group(sys_num,vg)); 01162 } 01163 } // end loop on elements 01164 01165 // we may have missed assigning DOFs to nodes that we own 01166 // but to which we have no connected elements matching our 01167 // variable restriction criterion. this will happen, for example, 01168 // if variable V is restricted to subdomain S. We may not own 01169 // any elements which live in S, but we may own nodes which are 01170 // *connected* to elements which do. in this scenario these nodes 01171 // will presently have unnumbered DOFs. we need to take care of 01172 // them here since we own them and no other processor will touch them. 01173 { 01174 MeshBase::node_iterator node_it = mesh.local_nodes_begin(); 01175 const MeshBase::node_iterator node_end = mesh.local_nodes_end(); 01176 01177 for (; node_it != node_end; ++node_it) 01178 { 01179 Node *node = *node_it; 01180 libmesh_assert(node); 01181 01182 if (node->n_comp_group(sys_num,vg)) 01183 if (node->vg_dof_base(sys_num,vg) == DofObject::invalid_id) 01184 { 01185 node->set_vg_dof_base (sys_num, 01186 vg, 01187 next_free_dof); 01188 01189 next_free_dof += (n_vars_in_group* 01190 node->n_comp_group(sys_num,vg)); 01191 } 01192 } 01193 } 01194 } // end loop on variable groups 01195 01196 // Finally, count up the SCALAR dofs 01197 this->_n_SCALAR_dofs = 0; 01198 for (unsigned vg=0; vg<n_var_groups; vg++) 01199 { 01200 const VariableGroup &vg_description(this->variable_group(vg)); 01201 01202 if( vg_description.type().family == SCALAR ) 01203 { 01204 this->_n_SCALAR_dofs += (vg_description.n_variables()* 01205 vg_description.type().order); 01206 continue; 01207 } 01208 } 01209 01210 // Only increment next_free_dof if we're on the processor 01211 // that holds this SCALAR variable 01212 if ( libMesh::processor_id() == (libMesh::n_processors()-1) ) 01213 next_free_dof += _n_SCALAR_dofs; 01214 01215 #ifdef DEBUG 01216 { 01217 // Make sure we didn't miss any nodes 01218 MeshTools::libmesh_assert_valid_procids<Node>(mesh); 01219 01220 MeshBase::node_iterator node_it = mesh.local_nodes_begin(); 01221 const MeshBase::node_iterator node_end = mesh.local_nodes_end(); 01222 for (; node_it != node_end; ++node_it) 01223 { 01224 Node *obj = *node_it; 01225 libmesh_assert(obj); 01226 unsigned int n_var_g = obj->n_var_groups(this->sys_number()); 01227 for (unsigned int vg=0; vg != n_var_g; ++vg) 01228 { 01229 unsigned int n_comp_g = 01230 obj->n_comp_group(this->sys_number(), vg); 01231 dof_id_type my_first_dof = n_comp_g ? 01232 obj->vg_dof_base(this->sys_number(), vg) : 0; 01233 libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id); 01234 } 01235 } 01236 } 01237 #endif // DEBUG 01238 }
| void libMesh::DofMap::dof_indices | ( | const Elem *const | elem, | |
| std::vector< dof_id_type > & | di, | |||
| const unsigned int | vn = libMesh::invalid_uint | |||
| ) | const |
Fills the vector di with the global degree of freedom indices for the element. If no variable number is specified then all variables are returned.
Definition at line 1587 of file dof_map.C.
References libMesh::Elem::active(), libMesh::Elem::dim(), libMesh::DofObject::dof_number(), libMesh::FEInterface::extra_hanging_dofs(), libMesh::FEType::family, libMesh::Elem::get_node(), libMesh::DofObject::invalid_id, libMesh::invalid_uint, libMesh::Elem::is_vertex(), libMeshEnums::LAGRANGE, libMesh::DofObject::n_comp(), n_dofs(), libMesh::FEInterface::n_dofs_at_node(), libMesh::FEInterface::n_dofs_per_elem(), libMesh::Elem::n_nodes(), n_nodes, libMesh::DofObject::n_systems(), n_variables(), n_vars, libMesh::FEType::order, libMesh::Elem::p_level(), libMeshEnums::SCALAR, SCALAR_dof_indices(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::Elem::type(), variable(), and variable_type().
Referenced by libMesh::ExactSolution::_compute_error(), add_neighbors_to_send_list(), libMesh::HPCoarsenTest::add_projection(), allgather_recursive_constraints(), libMesh::EquationSystems::build_discontinuous_solution_vector(), libMesh::EquationSystems::build_solution_vector(), libMesh::System::calculate_norm(), libMesh::FEGenericBase< OutputType >::coarsened_dof_values(), libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), libMesh::FEGenericBase< OutputType >::compute_proj_constraints(), DMCreateDomainDecomposition_libMesh(), DMCreateFieldDecomposition_libMesh(), libMesh::JumpErrorEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::EquationSystems::get_solution(), libMesh::MeshFunction::gradient(), libMesh::MeshFunction::hessian(), libMesh::SystemSubsetBySubdomain::init(), libMesh::System::local_dof_indices(), max_constraint_error(), libMesh::WeightedPatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::BoundaryProjectSolution::operator()(), libMesh::ProjectSolution::operator()(), libMesh::PatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::MeshFunction::operator()(), libMesh::SparsityPattern::Build::operator()(), libMesh::ErrorVector::plot_error(), libMesh::FEMContext::pre_fe_reinit(), scatter_constraints(), libMesh::HPCoarsenTest::select_refinement(), libMesh::EnsightIO::write_scalar_ascii(), and libMesh::EnsightIO::write_vector_ascii().
01590 { 01591 START_LOG("dof_indices()", "DofMap"); 01592 01593 libmesh_assert(elem); 01594 01595 const unsigned int n_nodes = elem->n_nodes(); 01596 const ElemType type = elem->type(); 01597 const unsigned int sys_num = this->sys_number(); 01598 const unsigned int n_vars = this->n_variables(); 01599 const unsigned int dim = elem->dim(); 01600 01601 // Clear the DOF indices vector 01602 di.clear(); 01603 01604 #ifdef DEBUG 01605 // Check that sizes match in DEBUG mode 01606 unsigned int tot_size = 0; 01607 #endif 01608 01609 // Create a vector to indicate which 01610 // SCALAR variables have been requested 01611 std::vector<unsigned int> SCALAR_var_numbers; 01612 SCALAR_var_numbers.clear(); 01613 01614 // Get the dof numbers 01615 for (unsigned int v=0; v<n_vars; v++) 01616 if ((v == vn) || (vn == libMesh::invalid_uint)) 01617 { 01618 if(this->variable(v).type().family == SCALAR) 01619 { 01620 // We asked for this variable, so add it to the vector. 01621 SCALAR_var_numbers.push_back(v); 01622 01623 #ifdef DEBUG 01624 FEType fe_type = this->variable_type(v); 01625 tot_size += FEInterface::n_dofs(dim, 01626 fe_type, 01627 type); 01628 #endif 01629 } 01630 else 01631 if (this->variable(v).active_on_subdomain(elem->subdomain_id())) 01632 { // Do this for all the variables if one was not specified 01633 // or just for the specified variable 01634 01635 // Increase the polynomial order on p refined elements 01636 FEType fe_type = this->variable_type(v); 01637 fe_type.order = static_cast<Order>(fe_type.order + 01638 elem->p_level()); 01639 01640 const bool extra_hanging_dofs = 01641 FEInterface::extra_hanging_dofs(fe_type); 01642 01643 #ifdef DEBUG 01644 tot_size += FEInterface::n_dofs(dim, 01645 fe_type, 01646 type); 01647 #endif 01648 01649 // Get the node-based DOF numbers 01650 for (unsigned int n=0; n<n_nodes; n++) 01651 { 01652 const Node* node = elem->get_node(n); 01653 01654 // There is a potential problem with h refinement. Imagine a 01655 // quad9 that has a linear FE on it. Then, on the hanging side, 01656 // it can falsely identify a DOF at the mid-edge node. This is why 01657 // we call FEInterface instead of node->n_comp() directly. 01658 const unsigned int nc = FEInterface::n_dofs_at_node (dim, 01659 fe_type, 01660 type, 01661 n); 01662 01663 // If this is a non-vertex on a hanging node with extra 01664 // degrees of freedom, we use the non-vertex dofs (which 01665 // come in reverse order starting from the end, to 01666 // simplify p refinement) 01667 if (extra_hanging_dofs && !elem->is_vertex(n)) 01668 { 01669 const int dof_offset = node->n_comp(sys_num,v) - nc; 01670 01671 // We should never have fewer dofs than necessary on a 01672 // node unless we're getting indices on a parent element, 01673 // and we should never need the indices on such a node 01674 if (dof_offset < 0) 01675 { 01676 libmesh_assert(!elem->active()); 01677 di.resize(di.size() + nc, DofObject::invalid_id); 01678 } 01679 else 01680 for (int i=node->n_comp(sys_num,v)-1; i>=dof_offset; i--) 01681 { 01682 libmesh_assert_not_equal_to (node->dof_number(sys_num,v,i), 01683 DofObject::invalid_id); 01684 di.push_back(node->dof_number(sys_num,v,i)); 01685 } 01686 } 01687 // If this is a vertex or an element without extra hanging 01688 // dofs, our dofs come in forward order coming from the 01689 // beginning 01690 else 01691 for (unsigned int i=0; i<nc; i++) 01692 { 01693 libmesh_assert_not_equal_to (node->dof_number(sys_num,v,i), 01694 DofObject::invalid_id); 01695 di.push_back(node->dof_number(sys_num,v,i)); 01696 } 01697 } 01698 01699 // If there are any element-based DOF numbers, get them 01700 const unsigned int nc = FEInterface::n_dofs_per_elem(dim, 01701 fe_type, 01702 type); 01703 // We should never have fewer dofs than necessary on an 01704 // element unless we're getting indices on a parent element, 01705 // and we should never need those indices 01706 if (nc != 0) 01707 { 01708 if (elem->n_systems() > sys_num && 01709 nc <= elem->n_comp(sys_num,v)) 01710 { 01711 for (unsigned int i=0; i<nc; i++) 01712 { 01713 libmesh_assert_not_equal_to (elem->dof_number(sys_num,v,i), 01714 DofObject::invalid_id); 01715 01716 di.push_back(elem->dof_number(sys_num,v,i)); 01717 } 01718 } 01719 else 01720 { 01721 libmesh_assert(!elem->active() || fe_type.family == LAGRANGE); 01722 di.resize(di.size() + nc, DofObject::invalid_id); 01723 } 01724 } 01725 } 01726 } // end loop over variables 01727 01728 // Finally append any SCALAR dofs that we asked for. 01729 std::vector<dof_id_type> di_new; 01730 std::vector<unsigned int>::iterator it = SCALAR_var_numbers.begin(); 01731 std::vector<unsigned int>::const_iterator it_end = SCALAR_var_numbers.end(); 01732 for( ; it != it_end; ++it) 01733 { 01734 this->SCALAR_dof_indices(di_new,*it); 01735 di.insert( di.end(), di_new.begin(), di_new.end()); 01736 } 01737 01738 #ifdef DEBUG 01739 libmesh_assert_equal_to (tot_size, di.size()); 01740 #endif 01741 01742 STOP_LOG("dof_indices()", "DofMap"); 01743 }
| DofObject * libMesh::DofMap::elem_ptr | ( | MeshBase & | mesh, | |
| dof_id_type | i | |||
| ) | const [private] |
An adapter function that returns Elem pointers by index
Definition at line 266 of file dof_map.C.
References libMesh::MeshBase::elem().
Referenced by distribute_dofs().
00267 { 00268 return mesh.elem(i); 00269 }
| void libMesh::ReferenceCounter::enable_print_counter_info | ( | ) | [static, inherited] |
Methods to enable/disable the reference counter output from print_info()
Definition at line 100 of file reference_counter.C.
References libMesh::ReferenceCounter::_enable_print_counter.
00101 { 00102 _enable_print_counter = true; 00103 return; 00104 }
| dof_id_type libMesh::DofMap::end_dof | ( | const processor_id_type | proc = libMesh::processor_id() |
) | const [inline] |
Returns the first dof index that is after all indices local to subdomain proc. Analogous to the end() member function of STL containers.
Definition at line 423 of file dof_map.h.
References _end_df.
Referenced by add_constraints_to_send_list(), add_neighbors_to_send_list(), all_semilocal_indices(), allgather_recursive_constraints(), DMCreateDomainDecomposition_libMesh(), DMCreateFieldDecomposition_libMesh(), enforce_constraints_exactly(), get_info(), get_local_constraints(), libMesh::SystemSubsetBySubdomain::init(), libMesh::CondensedEigenSystem::initialize_condensed_dofs(), libMesh::SparsityPattern::Build::join(), libMesh::System::local_dof_indices(), n_local_constrained_dofs(), libMesh::SparsityPattern::Build::operator()(), libMesh::SparsityPattern::Build::parallel_sync(), and libMesh::SparseMatrix< T >::print().
| dof_id_type libMesh::DofMap::end_old_dof | ( | const processor_id_type | proc = libMesh::processor_id() |
) | const [inline] |
Returns the first old dof index that is after all indices local to subdomain proc. Analogous to the end() member function of STL containers.
Definition at line 431 of file dof_map.h.
References _end_old_df.
00432 { libmesh_assert_less (proc, _end_old_df.size()); return _end_old_df[proc]; }
| void libMesh::DofMap::enforce_constraints_exactly | ( | const System & | system, | |
| NumericVector< Number > * | v = NULL, |
|||
| 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 == NULL, the system solution vector is constrained
If homogeneous == true, heterogeneous constraints are enforced as if they were homogeneous. This might be appropriate for e.g. a vector representing a difference between two heterogeneously-constrained solutions.
Definition at line 1543 of file dof_map_constraints.C.
References _dof_constraints, libMesh::NumericVector< T >::close(), libMesh::NumericVector< T >::closed(), end_dof(), libMesh::err, first_dof(), libMesh::AutoPtr< Tp >::get(), libMesh::System::get_dof_map(), libMeshEnums::GHOSTED, libMesh::NumericVector< T >::localize(), n_constrained_dofs(), n_dofs(), n_local_dofs(), libMeshEnums::PARALLEL, libMeshEnums::SERIAL, libMesh::NumericVector< T >::set(), libMesh::NumericVector< T >::size(), libMesh::System::solution, and libMesh::NumericVector< T >::type().
Referenced by libMesh::__libmesh_petsc_diff_solver_jacobian(), libMesh::__libmesh_petsc_diff_solver_residual(), libMesh::ImplicitSystem::adjoint_solve(), libMesh::Problem_Interface::computeF(), libMesh::Problem_Interface::computeJacobian(), libMesh::Problem_Interface::computePreconditioner(), DMFunction_libMesh(), DMJacobian_libMesh(), libMesh::System::project_vector(), libMesh::ImplicitSystem::sensitivity_solve(), libMesh::PetscDiffSolver::solve(), libMesh::NewtonSolver::solve(), libMesh::ImplicitSystem::weighted_sensitivity_adjoint_solve(), and libMesh::ImplicitSystem::weighted_sensitivity_solve().
01546 { 01547 parallel_only(); 01548 01549 if (!this->n_constrained_dofs()) 01550 return; 01551 01552 START_LOG("enforce_constraints_exactly()","DofMap"); 01553 01554 if (!v) 01555 v = system.solution.get(); 01556 01557 NumericVector<Number> *v_local = NULL; // will be initialized below 01558 NumericVector<Number> *v_global = NULL; // will be initialized below 01559 AutoPtr<NumericVector<Number> > v_built; 01560 if (v->type() == SERIAL) 01561 { 01562 v_built = NumericVector<Number>::build(); 01563 v_built->init(this->n_dofs(), this->n_local_dofs(), true, PARALLEL); 01564 v_built->close(); 01565 01566 for (dof_id_type i=v_built->first_local_index(); 01567 i<v_built->last_local_index(); i++) 01568 v_built->set(i, (*v)(i)); 01569 v_built->close(); 01570 v_global = v_built.get(); 01571 01572 v_local = v; 01573 libmesh_assert (v_local->closed()); 01574 } 01575 else if (v->type() == PARALLEL) 01576 { 01577 v_built = NumericVector<Number>::build(); 01578 v_built->init (v->size(), v->size(), true, SERIAL); 01579 v->localize(*v_built); 01580 v_built->close(); 01581 v_local = v_built.get(); 01582 01583 v_global = v; 01584 } 01585 else if (v->type() == GHOSTED) 01586 { 01587 v_local = v; 01588 v_global = v; 01589 } 01590 else // unknown v->type() 01591 { 01592 libMesh::err << "ERROR: Unknown v->type() == " << v->type() 01593 << std::endl; 01594 libmesh_error(); 01595 } 01596 01597 // We should never hit these asserts because we should error-out in 01598 // else clause above. Just to be sure we don't try to use v_local 01599 // and v_global uninitialized... 01600 libmesh_assert(v_local); 01601 libmesh_assert(v_global); 01602 libmesh_assert_equal_to (this, &(system.get_dof_map())); 01603 01604 DofConstraints::const_iterator c_it = _dof_constraints.begin(); 01605 const DofConstraints::const_iterator c_end = _dof_constraints.end(); 01606 01607 for ( ; c_it != c_end; ++c_it) 01608 { 01609 dof_id_type constrained_dof = c_it->first; 01610 if (constrained_dof < this->first_dof() || 01611 constrained_dof >= this->end_dof()) 01612 continue; 01613 01614 const DofConstraintRow constraint_row = c_it->second.first; 01615 01616 Number exact_value = homogeneous ? 01617 0 : c_it->second.second; 01618 for (DofConstraintRow::const_iterator 01619 j=constraint_row.begin(); j != constraint_row.end(); 01620 ++j) 01621 exact_value += j->second * (*v_local)(j->first); 01622 01623 v_global->set(constrained_dof, exact_value); 01624 } 01625 01626 // If the old vector was serial, we probably need to send our values 01627 // to other processors 01628 if (v->type() == SERIAL) 01629 { 01630 #ifndef NDEBUG 01631 v_global->close(); 01632 #endif 01633 v_global->localize (*v); 01634 } 01635 v->close(); 01636 01637 STOP_LOG("enforce_constraints_exactly()","DofMap"); 01638 }
| 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]] $](form_34.png)
Note that the user must ensure that the element vector Ue is properly sized when calling this method. This is because there is no resize() method in the DenseVectorBase<> class.
Definition at line 1501 of file dof_map.C.
References build_constraint_matrix_and_vector(), libMesh::DenseVectorBase< T >::el(), libMesh::NumericVector< T >::first_local_index(), is_constrained_dof(), libMesh::NumericVector< T >::last_local_index(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::NumericVector< T >::size(), libMesh::DenseVectorBase< T >::size(), and libMesh::DenseVectorBase< T >::zero().
01504 { 01505 #ifdef LIBMESH_ENABLE_AMR 01506 01507 // Trivial mapping 01508 libmesh_assert_equal_to (dof_indices_in.size(), Ue.size()); 01509 bool has_constrained_dofs = false; 01510 01511 for (unsigned int il=0; 01512 il != libmesh_cast_int<unsigned int>(dof_indices_in.size()); il++) 01513 { 01514 const dof_id_type ig = dof_indices_in[il]; 01515 01516 if (this->is_constrained_dof (ig)) has_constrained_dofs = true; 01517 01518 libmesh_assert_less (ig, Ug.size()); 01519 01520 Ue.el(il) = Ug(ig); 01521 } 01522 01523 // If the element has any constrained DOFs then we need 01524 // to account for them in the mapping. This will handle 01525 // the case that the input vector is not constrained. 01526 if (has_constrained_dofs) 01527 { 01528 // Copy the input DOF indices. 01529 std::vector<dof_id_type> constrained_dof_indices(dof_indices_in); 01530 01531 DenseMatrix<Number> C; 01532 DenseVector<Number> H; 01533 01534 this->build_constraint_matrix_and_vector (C, H, constrained_dof_indices); 01535 01536 libmesh_assert_equal_to (dof_indices_in.size(), C.m()); 01537 libmesh_assert_equal_to (constrained_dof_indices.size(), C.n()); 01538 01539 // zero-out Ue 01540 Ue.zero(); 01541 01542 // compute Ue = C Ug, with proper mapping. 01543 const unsigned int n_original_dofs = 01544 libmesh_cast_int<unsigned int>(dof_indices_in.size()); 01545 for (unsigned int i=0; i != n_original_dofs; i++) 01546 { 01547 Ue.el(i) = H(i); 01548 01549 const unsigned int n_constrained = 01550 libmesh_cast_int<unsigned int>(constrained_dof_indices.size()); 01551 for (unsigned int j=0; j<n_constrained; j++) 01552 { 01553 const dof_id_type jg = constrained_dof_indices[j]; 01554 01555 // If Ug is a serial or ghosted vector, then this assert is 01556 // overzealous. If Ug is a parallel vector, then this assert 01557 // is redundant. 01558 // libmesh_assert ((jg >= Ug.first_local_index()) && 01559 // (jg < Ug.last_local_index())); 01560 01561 Ue.el(i) += C(i,j)*Ug(jg); 01562 } 01563 } 01564 } 01565 01566 #else 01567 01568 // Trivial mapping 01569 01570 const unsigned int n_original_dofs = 01571 libmesh_cast_int<unsigned int>(dof_indices_in.size()); 01572 01573 libmesh_assert_equal_to (n_original_dofs, Ue.size()); 01574 01575 for (unsigned int il=0; il<n_original_dofs; il++) 01576 { 01577 const dof_id_type ig = dof_indices_in[il]; 01578 01579 libmesh_assert ((ig >= Ug.first_local_index()) && (ig < Ug.last_local_index())); 01580 01581 Ue.el(il) = Ug(ig); 01582 } 01583 01584 #endif 01585 }
| void libMesh::DofMap::find_connected_dof_objects | ( | std::vector< const DofObject * > & | objs | ) | const [private] |
Finds all the DofObjects associated with the set in objs. This will account for off-element couplings via hanging nodes.
| void libMesh::DofMap::find_connected_dofs | ( | std::vector< dof_id_type > & | elem_dofs | ) | const [private] |
Finds all the DOFS associated with the element DOFs elem_dofs. This will account for off-element couplings via hanging nodes.
Definition at line 2077 of file dof_map.C.
References _dof_constraints, and is_constrained_dof().
Referenced by libMesh::SparsityPattern::Build::operator()().
02078 { 02079 typedef std::set<dof_id_type> RCSet; 02080 02081 // First insert the DOFS we already depend on into the set. 02082 RCSet dof_set (elem_dofs.begin(), elem_dofs.end()); 02083 02084 bool done = true; 02085 02086 // Next insert any dofs those might be constrained in terms 02087 // of. Note that in this case we may not be done: Those may 02088 // in turn depend on others. So, we need to repeat this process 02089 // in that case until the system depends only on unconstrained 02090 // degrees of freedom. 02091 for (unsigned int i=0; i<elem_dofs.size(); i++) 02092 if (this->is_constrained_dof(elem_dofs[i])) 02093 { 02094 // If the DOF is constrained 02095 DofConstraints::const_iterator 02096 pos = _dof_constraints.find(elem_dofs[i]); 02097 02098 libmesh_assert (pos != _dof_constraints.end()); 02099 02100 const DofConstraintRow& constraint_row = pos->second.first; 02101 02102 // adaptive p refinement currently gives us lots of empty constraint 02103 // rows - we should optimize those DoFs away in the future. [RHS] 02104 // libmesh_assert (!constraint_row.empty()); 02105 02106 DofConstraintRow::const_iterator it = constraint_row.begin(); 02107 DofConstraintRow::const_iterator it_end = constraint_row.end(); 02108 02109 02110 // Add the DOFs this dof is constrained in terms of. 02111 // note that these dofs might also be constrained, so 02112 // we will need to call this function recursively. 02113 for ( ; it != it_end; ++it) 02114 if (!dof_set.count (it->first)) 02115 { 02116 dof_set.insert (it->first); 02117 done = false; 02118 } 02119 } 02120 02121 02122 // If not done then we need to do more work 02123 // (obviously :-) )! 02124 if (!done) 02125 { 02126 // Fill the vector with the contents of the set 02127 elem_dofs.clear(); 02128 elem_dofs.insert (elem_dofs.end(), 02129 dof_set.begin(), dof_set.end()); 02130 02131 02132 // May need to do this recursively. It is possible 02133 // that we just replaced a constrained DOF with another 02134 // constrained DOF. 02135 this->find_connected_dofs (elem_dofs); 02136 02137 } // end if (!done) 02138 }
| dof_id_type libMesh::DofMap::first_dof | ( | const processor_id_type | proc = libMesh::processor_id() |
) | const [inline] |
Returns the first dof index that is local to partition proc.
Definition at line 397 of file dof_map.h.
References _first_df.
Referenced by add_constraints_to_send_list(), add_neighbors_to_send_list(), all_semilocal_indices(), allgather_recursive_constraints(), DMCreateDomainDecomposition_libMesh(), DMCreateFieldDecomposition_libMesh(), enforce_constraints_exactly(), get_info(), get_local_constraints(), libMesh::SystemSubsetBySubdomain::init(), libMesh::SparsityPattern::Build::join(), libMesh::System::local_dof_indices(), n_local_constrained_dofs(), libMesh::SparsityPattern::Build::operator()(), libMesh::SparsityPattern::Build::parallel_sync(), and libMesh::SparseMatrix< T >::print().
| dof_id_type libMesh::DofMap::first_old_dof | ( | const processor_id_type | proc = libMesh::processor_id() |
) | const [inline] |
Returns the first old dof index that is local to partition proc.
Definition at line 404 of file dof_map.h.
References _first_old_df.
00405 { libmesh_assert_less (proc, _first_old_df.size()); return _first_old_df[proc]; }
| DirichletBoundaries* libMesh::DofMap::get_dirichlet_boundaries | ( | ) | [inline] |
Definition at line 786 of file dof_map.h.
References _dirichlet_boundaries.
00787 { 00788 return _dirichlet_boundaries; 00789 }
| std::string libMesh::ReferenceCounter::get_info | ( | ) | [static, inherited] |
Gets a string containing the reference information.
Definition at line 47 of file reference_counter.C.
References libMesh::ReferenceCounter::_counts, and libMesh::Quality::name().
Referenced by libMesh::ReferenceCounter::print_info().
00048 { 00049 #if defined(LIBMESH_ENABLE_REFERENCE_COUNTING) && defined(DEBUG) 00050 00051 std::ostringstream oss; 00052 00053 oss << '\n' 00054 << " ---------------------------------------------------------------------------- \n" 00055 << "| Reference count information |\n" 00056 << " ---------------------------------------------------------------------------- \n"; 00057 00058 for (Counts::iterator it = _counts.begin(); 00059 it != _counts.end(); ++it) 00060 { 00061 const std::string name(it->first); 00062 const unsigned int creations = it->second.first; 00063 const unsigned int destructions = it->second.second; 00064 00065 oss << "| " << name << " reference count information:\n" 00066 << "| Creations: " << creations << '\n' 00067 << "| Destructions: " << destructions << '\n'; 00068 } 00069 00070 oss << " ---------------------------------------------------------------------------- \n"; 00071 00072 return oss.str(); 00073 00074 #else 00075 00076 return ""; 00077 00078 #endif 00079 }
| std::string libMesh::DofMap::get_info | ( | ) | const |
Gets summary info about the sparsity bandwidth and constraints.
Definition at line 2780 of file dof_map.C.
References _dof_constraints, _matrices, _n_nz, _n_oz, _node_constraints, libMesh::CommWorld, end, end_dof(), first_dof(), libMesh::Parallel::Communicator::max(), std::max(), libMesh::processor_id(), libMesh::DofObject::processor_id(), and libMesh::Parallel::Communicator::sum().
Referenced by libMesh::System::get_info(), and print_info().
02781 { 02782 std::ostringstream os; 02783 02784 // If we didn't calculate the exact sparsity pattern, the threaded 02785 // sparsity pattern assembly may have just given us an upper bound 02786 // on sparsity. 02787 const char* may_equal = " <= "; 02788 02789 // If we calculated the exact sparsity pattern, then we can report 02790 // exact bandwidth figures: 02791 std::vector<SparseMatrix<Number>* >::const_iterator 02792 pos = _matrices.begin(), 02793 end = _matrices.end(); 02794 02795 for (; pos != end; ++pos) 02796 if ((*pos)->need_full_sparsity_pattern()) 02797 may_equal = " = "; 02798 02799 dof_id_type max_n_nz = 0, max_n_oz = 0; 02800 long double avg_n_nz = 0, avg_n_oz = 0; 02801 02802 if (_n_nz) 02803 { 02804 for (std::size_t i = 0; i != _n_nz->size(); ++i) 02805 { 02806 max_n_nz = std::max(max_n_nz, (*_n_nz)[i]); 02807 avg_n_nz += (*_n_nz)[i]; 02808 } 02809 02810 std::size_t n_nz_size = _n_nz->size(); 02811 02812 CommWorld.max(max_n_nz); 02813 CommWorld.sum(avg_n_nz); 02814 CommWorld.sum(n_nz_size); 02815 02816 avg_n_nz /= std::max(n_nz_size,std::size_t(1)); 02817 02818 libmesh_assert(_n_oz); 02819 02820 for (std::size_t i = 0; i != (*_n_oz).size(); ++i) 02821 { 02822 max_n_oz = std::max(max_n_oz, (*_n_oz)[i]); 02823 avg_n_oz += (*_n_oz)[i]; 02824 } 02825 02826 std::size_t n_oz_size = _n_oz->size(); 02827 02828 CommWorld.max(max_n_oz); 02829 CommWorld.sum(avg_n_oz); 02830 CommWorld.sum(n_oz_size); 02831 02832 avg_n_oz /= std::max(n_oz_size,std::size_t(1)); 02833 } 02834 02835 os << " DofMap Sparsity\n Average On-Processor Bandwidth" 02836 << may_equal << avg_n_nz << '\n'; 02837 02838 os << " Average Off-Processor Bandwidth" 02839 << may_equal << avg_n_oz << '\n'; 02840 02841 os << " Maximum On-Processor Bandwidth" 02842 << may_equal << max_n_nz << '\n'; 02843 02844 os << " Maximum Off-Processor Bandwidth" 02845 << may_equal << max_n_oz << std::endl; 02846 02847 #ifdef LIBMESH_ENABLE_CONSTRAINTS 02848 02849 std::size_t n_constraints = 0, max_constraint_length = 0, 02850 n_rhss = 0; 02851 long double avg_constraint_length = 0.; 02852 02853 for (DofConstraints::const_iterator it=_dof_constraints.begin(); 02854 it != _dof_constraints.end(); ++it) 02855 { 02856 // Only count local constraints, then sum later 02857 const dof_id_type constrained_dof = it->first; 02858 if (constrained_dof < this->first_dof() || 02859 constrained_dof >= this->end_dof()) 02860 continue; 02861 02862 const DofConstraintRow& row = it->second.first; 02863 std::size_t rowsize = row.size(); 02864 02865 max_constraint_length = std::max(max_constraint_length, 02866 rowsize); 02867 avg_constraint_length += rowsize; 02868 n_constraints++; 02869 02870 if (it->second.second != Number(0)) 02871 n_rhss++; 02872 } 02873 02874 CommWorld.sum(n_constraints); 02875 CommWorld.sum(n_rhss); 02876 CommWorld.sum(avg_constraint_length); 02877 CommWorld.max(max_constraint_length); 02878 02879 os << " DofMap Constraints\n Number of DoF Constraints = " 02880 << n_constraints; 02881 if (n_rhss) 02882 os << '\n' 02883 << " Number of Heterogenous Constraints= " << n_rhss; 02884 if (n_constraints) 02885 { 02886 avg_constraint_length /= n_constraints; 02887 02888 os << '\n' 02889 << " Average DoF Constraint Length= " << avg_constraint_length; 02890 } 02891 02892 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02893 std::size_t n_node_constraints = 0, max_node_constraint_length = 0, 02894 n_node_rhss = 0; 02895 long double avg_node_constraint_length = 0.; 02896 02897 for (NodeConstraints::const_iterator it=_node_constraints.begin(); 02898 it != _node_constraints.end(); ++it) 02899 { 02900 // Only count local constraints, then sum later 02901 const Node *node = it->first; 02902 if (node->processor_id() != libMesh::processor_id()) 02903 continue; 02904 02905 const NodeConstraintRow& row = it->second.first; 02906 std::size_t rowsize = row.size(); 02907 02908 max_node_constraint_length = std::max(max_node_constraint_length, 02909 rowsize); 02910 avg_node_constraint_length += rowsize; 02911 n_node_constraints++; 02912 02913 if (it->second.second != Point(0)) 02914 n_node_rhss++; 02915 } 02916 02917 CommWorld.sum(n_node_constraints); 02918 CommWorld.sum(n_node_rhss); 02919 CommWorld.sum(avg_node_constraint_length); 02920 CommWorld.max(max_node_constraint_length); 02921 02922 os << "\n Number of Node Constraints = " << n_node_constraints; 02923 if (n_node_rhss) 02924 os << '\n' 02925 << " Number of Heterogenous Node Constraints= " << n_node_rhss; 02926 if (n_node_constraints) 02927 { 02928 avg_node_constraint_length /= n_node_constraints; 02929 os << "\n Maximum Node Constraint Length= " << max_node_constraint_length 02930 << '\n' 02931 << " Average Node Constraint Length= " << avg_node_constraint_length; 02932 } 02933 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02934 02935 os << std::endl; 02936 02937 #endif // LIBMESH_ENABLE_CONSTRAINTS 02938 02939 return os.str(); 02940 }
| std::string libMesh::DofMap::get_local_constraints | ( | bool | print_nonlocal = false |
) | const |
Gets a string reporting all DoF and Node constraints local to this processor. If print_nonlocal is true, then nonlocal constraints which are locally known are included.
Definition at line 1027 of file dof_map_constraints.C.
References _dof_constraints, _node_constraints, end_dof(), first_dof(), libMesh::DofObject::id(), libMesh::processor_id(), and libMesh::DofObject::processor_id().
Referenced by print_dof_constraints().
01028 { 01029 std::ostringstream os; 01030 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 01031 if (print_nonlocal) 01032 os << "All "; 01033 else 01034 os << "Local "; 01035 01036 os << "Node Constraints:" 01037 << std::endl; 01038 01039 for (NodeConstraints::const_iterator it=_node_constraints.begin(); 01040 it != _node_constraints.end(); ++it) 01041 { 01042 const Node *node = it->first; 01043 01044 // Skip non-local nodes if requested 01045 if (!print_nonlocal && 01046 node->processor_id() != libMesh::processor_id()) 01047 continue; 01048 01049 const NodeConstraintRow& row = it->second.first; 01050 const Point& offset = it->second.second; 01051 01052 os << "Constraints for Node id " << node->id() 01053 << ": \t"; 01054 01055 for (NodeConstraintRow::const_iterator pos=row.begin(); 01056 pos != row.end(); ++pos) 01057 os << " (" << pos->first->id() << "," 01058 << pos->second << ")\t"; 01059 01060 os << "rhs: " << offset; 01061 01062 os << std::endl; 01063 } 01064 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 01065 01066 if (print_nonlocal) 01067 os << "All "; 01068 else 01069 os << "Local "; 01070 01071 os << "DoF Constraints:" 01072 << std::endl; 01073 01074 for (DofConstraints::const_iterator it=_dof_constraints.begin(); 01075 it != _dof_constraints.end(); ++it) 01076 { 01077 const dof_id_type i = it->first; 01078 01079 // Skip non-local dofs if requested 01080 if (!print_nonlocal && 01081 ((i < this->first_dof()) || 01082 (i >= this->end_dof()))) 01083 continue; 01084 01085 const DofConstraintRow& row = it->second.first; 01086 const Number rhs = it->second.second; 01087 01088 os << "Constraints for DoF " << i 01089 << ": \t"; 01090 01091 for (DofConstraintRow::const_iterator pos=row.begin(); 01092 pos != row.end(); ++pos) 01093 os << " (" << pos->first << "," 01094 << pos->second << ")\t"; 01095 01096 os << "rhs: " << rhs; 01097 01098 os << std::endl; 01099 } 01100 01101 return os.str(); 01102 }
| const std::vector<dof_id_type>& libMesh::DofMap::get_n_nz | ( | ) | const [inline] |
Returns a constant reference to the _n_nz list for this processor. The vector contains the bandwidth of the on-processor coupling for each row of the global matrix that the current processor owns. This information can be used to preallocate space for a parallel sparse matrix.
Definition at line 296 of file dof_map.h.
References _n_nz.
Referenced by libMesh::PetscMatrix< T >::init(), libMesh::LaspackMatrix< T >::init(), and libMesh::EpetraMatrix< T >::update_sparsity_pattern().
| const std::vector<dof_id_type>& libMesh::DofMap::get_n_oz | ( | ) | const [inline] |
Returns a constant reference to the _n_oz list for this processor. The vector contains the bandwidth of the off-processor coupling for each row of the global matrix that the current processor owns. This information can be used to preallocate space for a parallel sparse matrix.
Definition at line 307 of file dof_map.h.
References _n_oz.
Referenced by libMesh::PetscMatrix< T >::init(), libMesh::LaspackMatrix< T >::init(), and libMesh::EpetraMatrix< T >::update_sparsity_pattern().
| PeriodicBoundaries* libMesh::DofMap::get_periodic_boundaries | ( | ) | [inline] |
Definition at line 763 of file dof_map.h.
References _periodic_boundaries.
00764 { 00765 return _periodic_boundaries; 00766 }
| const std::vector<dof_id_type>& libMesh::DofMap::get_send_list | ( | ) | const [inline] |
Returns a constant reference to the _send_list for this processor. The _send_list contains the global indices of all the variables in the global solution vector that influence the current processor. This information can be used for gathers at each solution step to retrieve solution values needed for computation.
Definition at line 288 of file dof_map.h.
References _send_list.
Referenced by libMesh::UnsteadySolver::adjoint_advance_timestep(), libMesh::UnsteadySolver::advance_timestep(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::UnsteadySolver::init_data(), libMesh::System::re_update(), libMesh::UnsteadySolver::reinit(), and libMesh::UnsteadySolver::retrieve_timestep().
00288 { return _send_list; }
| 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 | |||
| ) | const |
Constrains the element matrix and vector. This method requires the element matrix to be square, in which case the elem_dofs correspond to the global DOF indices of both the rows and columns of the element matrix. For this case the rows and columns of the matrix necessarily correspond to variables of the same approximation order.
The heterogenous version of this method creates linear systems in which heterogenously constrained degrees of freedom will solve to their correct offset values, as would be appropriate for finding a solution to a linear problem in a single algebraic solve. The non-heterogenous version of this method creates linear systems in which even heterogenously constrained degrees of freedom are solved without offset values taken into account, as would be appropriate for finding linearized updates to a solution in which heterogenous constraints are already satisfied.
Definition at line 1260 of file dof_map_constraints.C.
References libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::right_multiply(), libMesh::DenseVector< T >::size(), libMesh::DenseMatrix< T >::vector_mult(), and libMesh::DenseMatrix< T >::vector_mult_transpose().
01264 { 01265 libmesh_assert_equal_to (elem_dofs.size(), matrix.m()); 01266 libmesh_assert_equal_to (elem_dofs.size(), matrix.n()); 01267 libmesh_assert_equal_to (elem_dofs.size(), rhs.size()); 01268 01269 // check for easy return 01270 if (this->_dof_constraints.empty()) 01271 return; 01272 01273 // The constrained matrix is built up as C^T K C. 01274 // The constrained RHS is built up as C^T (F - K H) 01275 DenseMatrix<Number> C; 01276 DenseVector<Number> H; 01277 01278 this->build_constraint_matrix_and_vector (C, H, elem_dofs); 01279 01280 START_LOG("hetero_cnstrn_elem_mat_vec()", "DofMap"); 01281 01282 // It is possible that the matrix is not constrained at all. 01283 if ((C.m() == matrix.m()) && 01284 (C.n() == elem_dofs.size())) // It the matrix is constrained 01285 { 01286 // Compute matrix/vector product K H 01287 DenseVector<Number> KH; 01288 matrix.vector_mult(KH, H); 01289 01290 // Compute the matrix-vector product C^T (F - KH) 01291 DenseVector<Number> F_minus_KH(rhs); 01292 F_minus_KH -= KH; 01293 C.vector_mult_transpose(rhs, F_minus_KH); 01294 01295 // Compute the matrix-matrix-matrix product C^T K C 01296 matrix.left_multiply_transpose (C); 01297 matrix.right_multiply (C); 01298 01299 libmesh_assert_equal_to (matrix.m(), matrix.n()); 01300 libmesh_assert_equal_to (matrix.m(), elem_dofs.size()); 01301 libmesh_assert_equal_to (matrix.n(), elem_dofs.size()); 01302 01303 for (unsigned int i=0; i<elem_dofs.size(); i++) 01304 if (this->is_constrained_dof(elem_dofs[i])) 01305 { 01306 for (unsigned int j=0; j<matrix.n(); j++) 01307 matrix(i,j) = 0.; 01308 01309 // If the DOF is constrained 01310 matrix(i,i) = 1.; 01311 01312 // This will put a nonsymmetric entry in the constraint 01313 // row to ensure that the linear system produces the 01314 // correct value for the constrained DOF. 01315 if (asymmetric_constraint_rows) 01316 { 01317 DofConstraints::const_iterator 01318 pos = _dof_constraints.find(elem_dofs[i]); 01319 01320 libmesh_assert (pos != _dof_constraints.end()); 01321 01322 const DofConstraintRow& constraint_row = pos->second.first; 01323 01324 // p refinement creates empty constraint rows 01325 // libmesh_assert (!constraint_row.empty()); 01326 01327 for (DofConstraintRow::const_iterator 01328 it=constraint_row.begin(); it != constraint_row.end(); 01329 ++it) 01330 for (unsigned int j=0; j<elem_dofs.size(); j++) 01331 if (elem_dofs[j] == it->first) 01332 matrix(i,j) = -it->second; 01333 01334 rhs(i) = pos->second.second; 01335 } 01336 else 01337 rhs(i) = 0.; 01338 } 01339 01340 } // end if is constrained... 01341 01342 STOP_LOG("hetero_cnstrn_elem_mat_vec()", "DofMap"); 01343 }
| void libMesh::ReferenceCounter::increment_constructor_count | ( | const std::string & | name | ) | [inline, protected, inherited] |
Increments the construction counter. Should be called in the constructor of any derived class that will be reference counted.
Definition at line 163 of file reference_counter.h.
References libMesh::ReferenceCounter::_counts, and libMesh::Threads::spin_mtx.
Referenced by libMesh::ReferenceCountedObject< RBParametrized >::ReferenceCountedObject().
00164 { 00165 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx); 00166 std::pair<unsigned int, unsigned int>& p = _counts[name]; 00167 00168 p.first++; 00169 }
| void libMesh::ReferenceCounter::increment_destructor_count | ( | const std::string & | name | ) | [inline, protected, inherited] |
Increments the destruction counter. Should be called in the destructor of any derived class that will be reference counted.
Definition at line 176 of file reference_counter.h.
References libMesh::ReferenceCounter::_counts, and libMesh::Threads::spin_mtx.
Referenced by libMesh::ReferenceCountedObject< RBParametrized >::~ReferenceCountedObject().
00177 { 00178 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx); 00179 std::pair<unsigned int, unsigned int>& p = _counts[name]; 00180 00181 p.second++; 00182 }
| void libMesh::DofMap::invalidate_dofs | ( | MeshBase & | mesh | ) | const [private] |
Invalidates all active DofObject dofs for this system
Definition at line 777 of file dof_map.C.
References libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::MeshBase::nodes_begin(), libMesh::MeshBase::nodes_end(), and sys_number().
Referenced by distribute_dofs(), and reinit().
00778 { 00779 const unsigned int sys_num = this->sys_number(); 00780 00781 // All the nodes 00782 MeshBase::node_iterator node_it = mesh.nodes_begin(); 00783 const MeshBase::node_iterator node_end = mesh.nodes_end(); 00784 00785 for ( ; node_it != node_end; ++node_it) 00786 (*node_it)->invalidate_dofs(sys_num); 00787 00788 // All the elements 00789 MeshBase::element_iterator elem_it = mesh.active_elements_begin(); 00790 const MeshBase::element_iterator elem_end = mesh.active_elements_end(); 00791 00792 for ( ; elem_it != elem_end; ++elem_it) 00793 (*elem_it)->invalidate_dofs(sys_num); 00794 }
| bool libMesh::DofMap::is_attached | ( | SparseMatrix< Number > & | matrix | ) |
Matrices should not be attached more than once. We can test for an already-attached matrix if necessary using is_attached
Definition at line 251 of file dof_map.C.
References _matrices.
Referenced by libMesh::ImplicitSystem::init_matrices().
| bool libMesh::DofMap::is_constrained_dof | ( | const dof_id_type | dof | ) | const [inline] |
- Returns:
- true if the degree of freedom dof is constrained, false otherwise.
Definition at line 1247 of file dof_map.h.
References _dof_constraints.
Referenced by add_constraint_row(), allgather_recursive_constraints(), build_constraint_matrix(), libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), libMesh::FEGenericBase< OutputType >::compute_proj_constraints(), constrain_element_dyad_matrix(), constrain_element_matrix(), constrain_element_matrix_and_vector(), constrain_element_vector(), extract_local_vector(), find_connected_dofs(), max_constraint_error(), and scatter_constraints().
01248 { 01249 if (_dof_constraints.count(dof)) 01250 return true; 01251 01252 return false; 01253 }
| bool libMesh::DofMap::is_constrained_node | ( | const Node * | node | ) | const |
- Returns:
- true if the Node is constrained, false otherwise.
Referenced by allgather_recursive_constraints(), and scatter_constraints().
| bool libMesh::DofMap::is_periodic_boundary | ( | const boundary_id_type | boundaryid | ) | const |
- Returns:
- true if the boundary given by
boundaryidis periodic, false otherwise
Definition at line 183 of file dof_map.C.
References _periodic_boundaries.
00184 { 00185 if (_periodic_boundaries->count(boundaryid) != 0) 00186 return true; 00187 00188 return false; 00189 }
| dof_id_type libMesh::DofMap::last_dof | ( | const processor_id_type | proc = libMesh::processor_id() |
) | const [inline] |
| std::pair< Real, Real > libMesh::DofMap::max_constraint_error | ( | const System & | system, | |
| NumericVector< Number > * | v = NULL | |||
| ) | 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 == NULL, the system solution vector is tested.
Definition at line 1643 of file dof_map_constraints.C.
References _dof_constraints, std::abs(), libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), build_constraint_matrix(), libMesh::NumericVector< T >::closed(), dof_indices(), libMesh::NumericVector< T >::first_local_index(), libMesh::AutoPtr< Tp >::get(), libMesh::System::get_dof_map(), libMesh::System::get_mesh(), is_constrained_dof(), libMesh::NumericVector< T >::last_local_index(), libMesh::DenseMatrixBase< T >::m(), std::max(), mesh, libMesh::DenseMatrixBase< T >::n(), libMesh::Real, and libMesh::System::solution.
01645 { 01646 if (!v) 01647 v = system.solution.get(); 01648 NumericVector<Number> &vec = *v; 01649 01650 // We'll assume the vector is closed 01651 libmesh_assert (vec.closed()); 01652 01653 Real max_absolute_error = 0., max_relative_error = 0.; 01654 01655 const MeshBase &mesh = system.get_mesh(); 01656 01657 libmesh_assert_equal_to (this, &(system.get_dof_map())); 01658 01659 // indices on each element 01660 std::vector<dof_id_type> local_dof_indices; 01661 01662 MeshBase::const_element_iterator elem_it = 01663 mesh.active_local_elements_begin(); 01664 const MeshBase::const_element_iterator elem_end = 01665 mesh.active_local_elements_end(); 01666 01667 for ( ; elem_it != elem_end; ++elem_it) 01668 { 01669 const Elem* elem = *elem_it; 01670 01671 this->dof_indices(elem, local_dof_indices); 01672 std::vector<dof_id_type> raw_dof_indices = local_dof_indices; 01673 01674 // Constraint matrix for each element 01675 DenseMatrix<Number> C; 01676 01677 this->build_constraint_matrix (C, local_dof_indices); 01678 01679 // Continue if the element is unconstrained 01680 if (!C.m()) 01681 continue; 01682 01683 libmesh_assert_equal_to (C.m(), raw_dof_indices.size()); 01684 libmesh_assert_equal_to (C.n(), local_dof_indices.size()); 01685 01686 for (unsigned int i=0; i!=C.m(); ++i) 01687 { 01688 // Recalculate any constrained dof owned by this processor 01689 dof_id_type global_dof = raw_dof_indices[i]; 01690 if (this->is_constrained_dof(global_dof) && 01691 global_dof >= vec.first_local_index() && 01692 global_dof < vec.last_local_index()) 01693 { 01694 DofConstraints::const_iterator 01695 pos = _dof_constraints.find(global_dof); 01696 01697 libmesh_assert (pos != _dof_constraints.end()); 01698 01699 Number exact_value = pos->second.second; 01700 for (unsigned int j=0; j!=C.n(); ++j) 01701 { 01702 if (local_dof_indices[j] != global_dof) 01703 exact_value += C(i,j) * 01704 vec(local_dof_indices[j]); 01705 } 01706 01707 max_absolute_error = std::max(max_absolute_error, 01708 std::abs(vec(global_dof) - exact_value)); 01709 max_relative_error = std::max(max_relative_error, 01710 std::abs(vec(global_dof) - exact_value) 01711 / std::abs(exact_value)); 01712 } 01713 } 01714 } 01715 01716 return std::pair<Real, Real>(max_absolute_error, max_relative_error); 01717 }
| dof_id_type libMesh::DofMap::n_constrained_dofs | ( | ) | const |
- Returns:
- the total number of constrained degrees of freedom in the problem.
Definition at line 835 of file dof_map_constraints.C.
References libMesh::CommWorld, n_local_constrained_dofs(), and libMesh::Parallel::Communicator::sum().
Referenced by enforce_constraints_exactly().
00836 { 00837 parallel_only(); 00838 00839 dof_id_type nc_dofs = this->n_local_constrained_dofs(); 00840 CommWorld.sum(nc_dofs); 00841 return nc_dofs; 00842 }
| dof_id_type libMesh::DofMap::n_constrained_nodes | ( | ) | const [inline] |
- Returns:
- the total number of constrained Nodes in the mesh.
Definition at line 506 of file dof_map.h.
References _node_constraints.
00507 { return libmesh_cast_int<dof_id_type>(_node_constraints.size()); }
| dof_id_type libMesh::DofMap::n_dofs | ( | ) | const [inline] |
- Returns:
- the total number of degrees of freedom in the problem.
Definition at line 373 of file dof_map.h.
References _n_dfs.
Referenced by dof_indices(), enforce_constraints_exactly(), libMesh::PetscMatrix< T >::init(), libMesh::LaspackMatrix< T >::init(), libMesh::SparsityPattern::Build::join(), old_dof_indices(), libMesh::UnsteadySolver::old_nonlinear_solution(), libMesh::SparsityPattern::Build::parallel_sync(), and libMesh::EpetraMatrix< T >::update_sparsity_pattern().
00373 { return _n_dfs; }
| dof_id_type libMesh::DofMap::n_dofs_on_processor | ( | const processor_id_type | proc | ) | const [inline] |
Returns the number of degrees of freedom on partition proc.
Definition at line 389 of file dof_map.h.
References _end_df, and _first_df.
Referenced by libMesh::PetscMatrix< T >::init(), libMesh::LaspackMatrix< T >::init(), libMesh::SparsityPattern::Build::join(), n_local_dofs(), libMesh::SparsityPattern::Build::operator()(), libMesh::SparsityPattern::Build::parallel_sync(), and libMesh::EpetraMatrix< T >::update_sparsity_pattern().
| dof_id_type libMesh::DofMap::n_local_constrained_dofs | ( | ) | const |
- Returns:
- the number of constrained degrees of freedom on this processor.
Definition at line 845 of file dof_map_constraints.C.
References _dof_constraints, end_dof(), and first_dof().
Referenced by n_constrained_dofs().
00846 { 00847 const DofConstraints::const_iterator lower = 00848 _dof_constraints.lower_bound(this->first_dof()), 00849 upper = 00850 _dof_constraints.upper_bound(this->end_dof()-1); 00851 00852 return std::distance(lower, upper); 00853 }
| dof_id_type libMesh::DofMap::n_local_dofs | ( | ) | const [inline] |
- Returns:
- the number of degrees of freedom on this processor.
Definition at line 383 of file dof_map.h.
References n_dofs_on_processor(), and libMesh::processor_id().
Referenced by enforce_constraints_exactly().
00384 { return this->n_dofs_on_processor (libMesh::processor_id()); }
| static unsigned int libMesh::ReferenceCounter::n_objects | ( | ) | [inline, static, inherited] |
Prints the number of outstanding (created, but not yet destroyed) objects.
Definition at line 79 of file reference_counter.h.
References libMesh::ReferenceCounter::_n_objects.
00080 { return _n_objects; }
| dof_id_type libMesh::DofMap::n_old_dofs | ( | ) | const [inline] |
- Returns:
- the total number of degrees of freedom on old_dof_objects
Definition at line 822 of file dof_map.h.
References _n_old_dfs.
00822 { return _n_old_dfs; }
| dof_id_type libMesh::DofMap::n_SCALAR_dofs | ( | ) | const [inline] |
- Returns:
- the number of SCALAR dofs.
Definition at line 378 of file dof_map.h.
References _n_SCALAR_dofs.
00378 { return _n_SCALAR_dofs; }
| unsigned int libMesh::DofMap::n_variable_groups | ( | ) | const [inline] |
Returns the number of variables in the global solution vector. Defaults to 1, should be 1 for a scalar equation, 3 for 2D incompressible Navier Stokes (u,v,p), etc...
Definition at line 359 of file dof_map.h.
References _variable_groups.
Referenced by distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), reinit(), and set_nonlocal_dof_objects().
00360 { return libmesh_cast_int<unsigned int>(_variable_groups.size()); }
| unsigned int libMesh::DofMap::n_variables | ( | ) | const [inline] |
Returns the number of variables in the global solution vector. Defaults to 1, should be 1 for a scalar equation, 3 for 2D incompressible Navier Stokes (u,v,p), etc...
Definition at line 367 of file dof_map.h.
References _variables.
Referenced by create_dof_constraints(), DMLibMeshSetSystem(), dof_indices(), old_dof_indices(), libMesh::SparsityPattern::Build::operator()(), and use_coupled_neighbor_dofs().
00368 { return libmesh_cast_int<unsigned int>(_variables.size()); }
| NodeConstraints::const_iterator libMesh::DofMap::node_constraint_rows_begin | ( | ) | const [inline] |
Returns an iterator pointing to the first Node constraint row
Definition at line 571 of file dof_map.h.
References _node_constraints.
00572 { return _node_constraints.begin(); }
| NodeConstraints::const_iterator libMesh::DofMap::node_constraint_rows_end | ( | ) | const [inline] |
Returns an iterator pointing just past the last Node constraint row
Definition at line 577 of file dof_map.h.
References _node_constraints.
00578 { return _node_constraints.end(); }
| DofObject * libMesh::DofMap::node_ptr | ( | MeshBase & | mesh, | |
| dof_id_type | i | |||
| ) | const [private] |
An adapter function that returns Node pointers by index
Definition at line 259 of file dof_map.C.
References libMesh::MeshBase::node_ptr().
Referenced by distribute_dofs().
00260 { 00261 return mesh.node_ptr(i); 00262 }
| void libMesh::DofMap::old_dof_indices | ( | const Elem *const | elem, | |
| std::vector< dof_id_type > & | di, | |||
| const unsigned int | vn = libMesh::invalid_uint | |||
| ) | const |
After a mesh is refined and repartitioned it is possible that the _send_list will need to be augmented. This is the case when an element is refined and its children end up on different processors than the parent. These children will need values from the parent when projecting the solution onto the refined mesh, hence the parent's DOF indices need to be included in the _send_list. Fills the vector di with the global degree of freedom indices for the element using the DofMap::old_dof_object. If no variable number is specified then all variables are returned.
Definition at line 1835 of file dof_map.C.
References libMesh::Elem::active(), libMesh::Elem::dim(), libMesh::DofObject::dof_number(), libMesh::FEInterface::extra_hanging_dofs(), libMesh::FEType::family, libMesh::Elem::get_node(), libMesh::DofObject::invalid_id, libMesh::invalid_uint, libMesh::Elem::is_vertex(), libMesh::Elem::JUST_COARSENED, libMesh::Elem::JUST_REFINED, libMeshEnums::LAGRANGE, libMesh::DofObject::n_comp(), n_dofs(), libMesh::FEInterface::n_dofs_at_node(), libMesh::FEInterface::n_dofs_per_elem(), libMesh::Elem::n_nodes(), n_nodes, libMesh::DofObject::n_systems(), n_variables(), n_vars, libMesh::DofObject::old_dof_object, libMesh::FEType::order, libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::Elem::refinement_flag(), libMeshEnums::SCALAR, SCALAR_dof_indices(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::Elem::type(), variable(), and variable_type().
Referenced by libMesh::FEGenericBase< OutputType >::coarsened_dof_values().
01838 { 01839 START_LOG("old_dof_indices()", "DofMap"); 01840 01841 libmesh_assert(elem); 01842 libmesh_assert(elem->old_dof_object); 01843 01844 01845 const unsigned int n_nodes = elem->n_nodes(); 01846 const ElemType type = elem->type(); 01847 const unsigned int sys_num = this->sys_number(); 01848 const unsigned int n_vars = this->n_variables(); 01849 const unsigned int dim = elem->dim(); 01850 01851 // Clear the DOF indices vector. 01852 di.clear(); 01853 01854 #ifdef DEBUG 01855 // Check that sizes match 01856 unsigned int tot_size = 0; 01857 #endif 01858 01859 // Create a vector to indicate which 01860 // SCALAR variables have been requested 01861 std::vector<unsigned int> SCALAR_var_numbers; 01862 SCALAR_var_numbers.clear(); 01863 01864 // Get the dof numbers 01865 for (unsigned int v=0; v<n_vars; v++) 01866 if ((v == vn) || (vn == libMesh::invalid_uint)) 01867 { 01868 if(this->variable(v).type().family == SCALAR) 01869 { 01870 // We asked for this variable, so add it to the vector. 01871 SCALAR_var_numbers.push_back(v); 01872 01873 #ifdef DEBUG 01874 FEType fe_type = this->variable_type(v); 01875 tot_size += FEInterface::n_dofs(dim, 01876 fe_type, 01877 type); 01878 #endif 01879 } 01880 else 01881 if (this->variable(v).active_on_subdomain(elem->subdomain_id())) 01882 { // Do this for all the variables if one was not specified 01883 // or just for the specified variable 01884 01885 // Increase the polynomial order on p refined elements, 01886 // but make sure you get the right polynomial order for 01887 // the OLD degrees of freedom 01888 int p_adjustment = 0; 01889 if (elem->p_refinement_flag() == Elem::JUST_REFINED) 01890 { 01891 libmesh_assert_greater (elem->p_level(), 0); 01892 p_adjustment = -1; 01893 } 01894 else if (elem->p_refinement_flag() == Elem::JUST_COARSENED) 01895 { 01896 p_adjustment = 1; 01897 } 01898 FEType fe_type = this->variable_type(v); 01899 fe_type.order = static_cast<Order>(fe_type.order + 01900 elem->p_level() + 01901 p_adjustment); 01902 01903 const bool extra_hanging_dofs = 01904 FEInterface::extra_hanging_dofs(fe_type); 01905 01906 #ifdef DEBUG 01907 tot_size += FEInterface::n_dofs(dim, 01908 fe_type, 01909 type); 01910 #endif 01911 01912 // Get the node-based DOF numbers 01913 for (unsigned int n=0; n<n_nodes; n++) 01914 { 01915 const Node* node = elem->get_node(n); 01916 01917 // There is a potential problem with h refinement. Imagine a 01918 // quad9 that has a linear FE on it. Then, on the hanging side, 01919 // it can falsely identify a DOF at the mid-edge node. This is why 01920 // we call FEInterface instead of node->n_comp() directly. 01921 const unsigned int nc = FEInterface::n_dofs_at_node (dim, 01922 fe_type, 01923 type, 01924 n); 01925 libmesh_assert(node->old_dof_object); 01926 01927 // If this is a non-vertex on a hanging node with extra 01928 // degrees of freedom, we use the non-vertex dofs (which 01929 // come in reverse order starting from the end, to 01930 // simplify p refinement) 01931 if (extra_hanging_dofs && !elem->is_vertex(n)) 01932 { 01933 const int dof_offset = 01934 node->old_dof_object->n_comp(sys_num,v) - nc; 01935 01936 // We should never have fewer dofs than necessary on a 01937 // node unless we're getting indices on a parent element 01938 // or a just-coarsened element 01939 if (dof_offset < 0) 01940 { 01941 libmesh_assert(!elem->active() || elem->refinement_flag() == 01942 Elem::JUST_COARSENED); 01943 di.resize(di.size() + nc, DofObject::invalid_id); 01944 } 01945 else 01946 for (int i=node->old_dof_object->n_comp(sys_num,v)-1; 01947 i>=dof_offset; i--) 01948 { 01949 libmesh_assert_not_equal_to (node->old_dof_object->dof_number(sys_num,v,i), 01950 DofObject::invalid_id); 01951 di.push_back(node->old_dof_object->dof_number(sys_num,v,i)); 01952 } 01953 } 01954 // If this is a vertex or an element without extra hanging 01955 // dofs, our dofs come in forward order coming from the 01956 // beginning 01957 else 01958 for (unsigned int i=0; i<nc; i++) 01959 { 01960 libmesh_assert_not_equal_to (node->old_dof_object->dof_number(sys_num,v,i), 01961 DofObject::invalid_id); 01962 di.push_back(node->old_dof_object->dof_number(sys_num,v,i)); 01963 } 01964 } 01965 01966 // If there are any element-based DOF numbers, get them 01967 const unsigned int nc = FEInterface::n_dofs_per_elem(dim, 01968 fe_type, 01969 type); 01970 01971 // We should never have fewer dofs than necessary on an 01972 // element unless we're getting indices on a parent element 01973 // or a just-coarsened element 01974 if (nc != 0) 01975 { 01976 if (elem->old_dof_object->n_systems() > sys_num && 01977 nc <= elem->old_dof_object->n_comp(sys_num,v)) 01978 { 01979 libmesh_assert(elem->old_dof_object); 01980 01981 for (unsigned int i=0; i<nc; i++) 01982 { 01983 libmesh_assert_not_equal_to (elem->old_dof_object->dof_number(sys_num,v,i), 01984 DofObject::invalid_id); 01985 01986 di.push_back(elem->old_dof_object->dof_number(sys_num,v,i)); 01987 } 01988 } 01989 else 01990 { 01991 libmesh_assert(!elem->active() || fe_type.family == LAGRANGE || 01992 elem->refinement_flag() == Elem::JUST_COARSENED); 01993 di.resize(di.size() + nc, DofObject::invalid_id); 01994 } 01995 } 01996 } 01997 } // end loop over variables 01998 01999 // Finally append any SCALAR dofs that we asked for. 02000 std::vector<dof_id_type> di_new; 02001 std::vector<unsigned int>::iterator it = SCALAR_var_numbers.begin(); 02002 std::vector<unsigned int>::const_iterator it_end = SCALAR_var_numbers.end(); 02003 for( ; it != it_end; ++it) 02004 { 02005 this->SCALAR_dof_indices(di_new,*it,true); 02006 di.insert( di.end(), di_new.begin(), di_new.end()); 02007 } 02008 02009 #ifdef DEBUG 02010 libmesh_assert_equal_to (tot_size, di.size()); 02011 #endif 02012 02013 STOP_LOG("old_dof_indices()", "DofMap"); 02014 }
| void libMesh::DofMap::prepare_send_list | ( | ) |
Takes the _send_list vector (which may have duplicate entries) and sorts it. The duplicate entries are then removed, resulting in a sorted _send_list with unique entries. Also calls any user-provided methods for adding to the send list.
Definition at line 1377 of file dof_map.C.
References _augment_send_list, _extra_send_list_context, _extra_send_list_function, _send_list, libMesh::DofMap::AugmentSendList::augment_send_list(), libMesh::out, and swap().
Referenced by libMesh::EquationSystems::allgather(), and libMesh::EquationSystems::reinit().
01378 { 01379 START_LOG("prepare_send_list()", "DofMap"); 01380 01381 // Check to see if we have any extra stuff to add to the send_list 01382 if (_extra_send_list_function) 01383 { 01384 if (_augment_send_list) 01385 { 01386 libmesh_here(); 01387 libMesh::out << "WARNING: You have specified both an extra send list function and object.\n" 01388 << " Are you sure this is what you meant to do??" 01389 << std::endl; 01390 } 01391 01392 _extra_send_list_function(_send_list, _extra_send_list_context); 01393 } 01394 01395 if (_augment_send_list) 01396 _augment_send_list->augment_send_list (_send_list); 01397 01398 // First sort the send list. After this 01399 // duplicated elements will be adjacent in the 01400 // vector 01401 std::sort(_send_list.begin(), _send_list.end()); 01402 01403 // Now use std::unique to remove duplicate entries 01404 std::vector<dof_id_type>::iterator new_end = 01405 std::unique (_send_list.begin(), _send_list.end()); 01406 01407 // Remove the end of the send_list. Use the "swap trick" 01408 // from Effective STL 01409 std::vector<dof_id_type> (_send_list.begin(), new_end).swap (_send_list); 01410 01411 STOP_LOG("prepare_send_list()", "DofMap"); 01412 }
| 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 ParallelMesh debugging.
Definition at line 1001 of file dof_map_constraints.C.
References libMesh::CommWorld, get_local_constraints(), libMesh::n_processors(), libMesh::processor_id(), libMesh::Parallel::Communicator::receive(), and libMesh::Parallel::Communicator::send().
01003 { 01004 parallel_only(); 01005 01006 std::string local_constraints = 01007 this->get_local_constraints(print_nonlocal); 01008 01009 if (libMesh::processor_id()) 01010 { 01011 CommWorld.send(0, local_constraints); 01012 } 01013 else 01014 { 01015 os << "Processor 0:\n"; 01016 os << local_constraints; 01017 01018 for (processor_id_type i=1; i<libMesh::n_processors(); ++i) 01019 { 01020 CommWorld.receive(i, local_constraints); 01021 os << "Processor " << i << ":\n"; 01022 os << local_constraints; 01023 } 01024 } 01025 }
| void libMesh::ReferenceCounter::print_info | ( | std::ostream & | out = libMesh::out |
) | [static, inherited] |
Prints the reference information, by default to libMesh::out.
Definition at line 88 of file reference_counter.C.
References libMesh::ReferenceCounter::_enable_print_counter, and libMesh::ReferenceCounter::get_info().
00089 { 00090 if( _enable_print_counter ) out_stream << ReferenceCounter::get_info(); 00091 }
| void libMesh::DofMap::print_info | ( | std::ostream & | os = libMesh::out |
) | const |
Prints summary info about the sparsity bandwidth and constraints.
Definition at line 2773 of file dof_map.C.
References get_info().
02774 { 02775 os << this->get_info(); 02776 }
| void libMesh::DofMap::process_constraints | ( | MeshBase & | mesh | ) |
Postprocesses any constrained degrees of freedom to be constrained only in terms of unconstrained dofs, then adds unconstrained dofs to the send_list and prepares that for use. This should be run after both system (create_dof_constraints) and user constraints have all been added.
Definition at line 2484 of file dof_map_constraints.C.
References _dof_constraints, add_constraints_to_send_list(), allgather_recursive_constraints(), libMesh::MeshBase::is_serial(), libMesh::Real, and scatter_constraints().
Referenced by libMesh::EquationSystems::allgather(), and libMesh::EquationSystems::reinit().
02485 { 02486 // With a parallelized Mesh, we've computed our local constraints, 02487 // but they may depend on non-local constraints that we'll need to 02488 // take into account. 02489 if (!mesh.is_serial()) 02490 this->allgather_recursive_constraints(mesh); 02491 02492 // Create a set containing the DOFs we already depend on 02493 typedef std::set<dof_id_type> RCSet; 02494 RCSet unexpanded_set; 02495 02496 for (DofConstraints::iterator i = _dof_constraints.begin(); 02497 i != _dof_constraints.end(); ++i) 02498 unexpanded_set.insert(i->first); 02499 02500 while (!unexpanded_set.empty()) 02501 for (RCSet::iterator i = unexpanded_set.begin(); 02502 i != unexpanded_set.end(); /* nothing */) 02503 { 02504 // If the DOF is constrained 02505 DofConstraints::iterator 02506 pos = _dof_constraints.find(*i); 02507 02508 libmesh_assert (pos != _dof_constraints.end()); 02509 02510 DofConstraintRow& constraint_row = pos->second.first; 02511 02512 Number& constraint_rhs = pos->second.second; 02513 02514 std::vector<dof_id_type> constraints_to_expand; 02515 02516 for (DofConstraintRow::const_iterator 02517 it=constraint_row.begin(); it != constraint_row.end(); 02518 ++it) 02519 if (it->first != *i && this->is_constrained_dof(it->first)) 02520 { 02521 unexpanded_set.insert(it->first); 02522 constraints_to_expand.push_back(it->first); 02523 } 02524 02525 for (std::size_t j = 0; j != constraints_to_expand.size(); 02526 ++j) 02527 { 02528 dof_id_type expandable = constraints_to_expand[j]; 02529 02530 const Real this_coef = constraint_row[expandable]; 02531 02532 DofConstraints::const_iterator 02533 subpos = _dof_constraints.find(expandable); 02534 02535 libmesh_assert (subpos != _dof_constraints.end()); 02536 02537 const DofConstraintRow& subconstraint_row = subpos->second.first; 02538 02539 for (DofConstraintRow::const_iterator 02540 it=subconstraint_row.begin(); 02541 it != subconstraint_row.end(); ++it) 02542 { 02543 constraint_row[it->first] += it->second * this_coef; 02544 } 02545 constraint_rhs += subpos->second.second * this_coef; 02546 02547 constraint_row.erase(expandable); 02548 } 02549 02550 if (constraints_to_expand.empty()) 02551 unexpanded_set.erase(i++); 02552 else 02553 i++; 02554 } 02555 02556 // In parallel we can't guarantee that nodes/dofs which constrain 02557 // others are on processors which are aware of that constraint, yet 02558 // we need such awareness for sparsity pattern generation. So send 02559 // other processors any constraints they might need to know about. 02560 if (!mesh.is_serial()) 02561 this->scatter_constraints(mesh); 02562 02563 // Now that we have our root constraint dependencies sorted out, add 02564 // them to the send_list 02565 this->add_constraints_to_send_list(); 02566 }
| void libMesh::DofMap::reinit | ( | MeshBase & | mesh | ) |
Reinitialize the underlying data strucures conformal to the current mesh.
Definition at line 422 of file dof_map.C.
References _n_SCALAR_dofs, libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::Variable::active_on_subdomain(), libMesh::Elem::dim(), libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), libMesh::Utility::enum_to_string(), libMesh::err, libMesh::FEInterface::extra_hanging_dofs(), libMesh::FEType::family, libMesh::Elem::get_node(), libMesh::DofObject::has_dofs(), invalidate_dofs(), libMesh::MeshBase::is_prepared(), libMesh::Elem::is_vertex(), libMesh::Elem::JUST_REFINED, std::max(), libMesh::FEInterface::max_order(), libMesh::DofObject::n_comp_group(), libMesh::FEInterface::n_dofs_at_node(), libMesh::FEInterface::n_dofs_per_elem(), libMesh::Elem::n_nodes(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::MeshBase::nodes_begin(), libMesh::MeshBase::nodes_end(), libMesh::DofObject::old_dof_object, libMesh::FEType::order, libMesh::Elem::p_level(), libMesh::Elem::refinement_flag(), libMeshEnums::SCALAR, libMesh::DofObject::set_n_comp_group(), libMesh::DofObject::set_old_dof_object(), libMesh::Elem::set_p_level(), libMesh::DofObject::set_vg_dof_base(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::Elem::type(), libMesh::Variable::type(), variable_group(), and libMesh::DofObject::vg_dof_base().
Referenced by distribute_dofs().
00423 { 00424 libmesh_assert (mesh.is_prepared()); 00425 00426 START_LOG("reinit()", "DofMap"); 00427 00428 const unsigned int 00429 sys_num = this->sys_number(), 00430 n_var_groups = this->n_variable_groups(); 00431 00432 // The DofObjects need to know how many variable groups we have, and 00433 // how many variables there are in each group. 00434 std::vector<unsigned int> n_vars_per_group; n_vars_per_group.reserve (n_var_groups); 00435 00436 for (unsigned int vg=0; vg<n_var_groups; vg++) 00437 n_vars_per_group.push_back (this->variable_group(vg).n_variables()); 00438 00439 #ifdef LIBMESH_ENABLE_AMR 00440 00441 //------------------------------------------------------------ 00442 // Clear the old_dof_objects for all the nodes 00443 // and elements so that we can overwrite them 00444 { 00445 MeshBase::node_iterator node_it = mesh.nodes_begin(); 00446 const MeshBase::node_iterator node_end = mesh.nodes_end(); 00447 00448 for ( ; node_it != node_end; ++node_it) 00449 { 00450 (*node_it)->clear_old_dof_object(); 00451 libmesh_assert (!(*node_it)->old_dof_object); 00452 } 00453 00454 MeshBase::element_iterator elem_it = mesh.elements_begin(); 00455 const MeshBase::element_iterator elem_end = mesh.elements_end(); 00456 00457 for ( ; elem_it != elem_end; ++elem_it) 00458 { 00459 (*elem_it)->clear_old_dof_object(); 00460 libmesh_assert (!(*elem_it)->old_dof_object); 00461 } 00462 } 00463 00464 00465 //------------------------------------------------------------ 00466 // Set the old_dof_objects for the elements that 00467 // weren't just created, if these old dof objects 00468 // had variables 00469 { 00470 MeshBase::element_iterator elem_it = mesh.elements_begin(); 00471 const MeshBase::element_iterator elem_end = mesh.elements_end(); 00472 00473 for ( ; elem_it != elem_end; ++elem_it) 00474 { 00475 Elem* elem = *elem_it; 00476 00477 // Skip the elements that were just refined 00478 if (elem->refinement_flag() == Elem::JUST_REFINED) continue; 00479 00480 for (unsigned int n=0; n<elem->n_nodes(); n++) 00481 { 00482 Node* node = elem->get_node(n); 00483 00484 if (node->old_dof_object == NULL) 00485 if (node->has_dofs(sys_num)) 00486 node->set_old_dof_object(); 00487 } 00488 00489 libmesh_assert (!elem->old_dof_object); 00490 00491 if (elem->has_dofs(sys_num)) 00492 elem->set_old_dof_object(); 00493 } 00494 } 00495 00496 #endif // #ifdef LIBMESH_ENABLE_AMR 00497 00498 00499 //------------------------------------------------------------ 00500 // Then set the number of variables for each \p DofObject 00501 // equal to n_variables() for this system. This will 00502 // handle new \p DofObjects that may have just been created 00503 { 00504 // All the nodes 00505 MeshBase::node_iterator node_it = mesh.nodes_begin(); 00506 const MeshBase::node_iterator node_end = mesh.nodes_end(); 00507 00508 for ( ; node_it != node_end; ++node_it) 00509 (*node_it)->set_n_vars_per_group(sys_num, n_vars_per_group); 00510 00511 // All the elements 00512 MeshBase::element_iterator elem_it = mesh.elements_begin(); 00513 const MeshBase::element_iterator elem_end = mesh.elements_end(); 00514 00515 for ( ; elem_it != elem_end; ++elem_it) 00516 (*elem_it)->set_n_vars_per_group(sys_num, n_vars_per_group); 00517 } 00518 00519 00520 // Zero _n_SCALAR_dofs, it will be updated below. 00521 this->_n_SCALAR_dofs = 0; 00522 00523 //------------------------------------------------------------ 00524 // Next allocate space for the DOF indices 00525 for (unsigned int vg=0; vg<n_var_groups; vg++) 00526 { 00527 const VariableGroup &vg_description = this->variable_group(vg); 00528 00529 const unsigned int n_var_in_group = vg_description.n_variables(); 00530 const FEType& base_fe_type = vg_description.type(); 00531 00532 // Don't need to loop over elements for a SCALAR variable 00533 // Just increment _n_SCALAR_dofs 00534 if(base_fe_type.family == SCALAR) 00535 { 00536 this->_n_SCALAR_dofs += base_fe_type.order*n_var_in_group; 00537 continue; 00538 } 00539 00540 // This should be constant even on p-refined elements 00541 const bool extra_hanging_dofs = 00542 FEInterface::extra_hanging_dofs(base_fe_type); 00543 00544 // For all the active elements 00545 MeshBase::element_iterator elem_it = mesh.active_elements_begin(); 00546 const MeshBase::element_iterator elem_end = mesh.active_elements_end(); 00547 00548 // Count vertex degrees of freedom first 00549 for ( ; elem_it != elem_end; ++elem_it) 00550 { 00551 Elem* elem = *elem_it; 00552 libmesh_assert(elem); 00553 00554 // Skip the numbering if this variable is 00555 // not active on this element's subdomain 00556 if (!vg_description.active_on_subdomain(elem->subdomain_id())) 00557 continue; 00558 00559 const ElemType type = elem->type(); 00560 const unsigned int dim = elem->dim(); 00561 00562 FEType fe_type = base_fe_type; 00563 00564 #ifdef LIBMESH_ENABLE_AMR 00565 // Make sure we haven't done more p refinement than we can 00566 // handle 00567 if (elem->p_level() + base_fe_type.order > 00568 FEInterface::max_order(base_fe_type, type)) 00569 { 00570 # ifdef DEBUG 00571 if (FEInterface::max_order(base_fe_type,type) < 00572 static_cast<unsigned int>(base_fe_type.order)) 00573 { 00574 libMesh::err 00575 << "ERROR: Finite element " 00576 << Utility::enum_to_string(base_fe_type.family) 00577 << " on geometric element " 00578 << Utility::enum_to_string(type) << std::endl 00579 << "only supports FEInterface::max_order = " 00580 << FEInterface::max_order(base_fe_type,type) 00581 << ", not fe_type.order = " << base_fe_type.order 00582 << std::endl; 00583 00584 libmesh_error(); 00585 } 00586 00587 libMesh::err 00588 << "WARNING: Finite element " 00589 << Utility::enum_to_string(base_fe_type.family) 00590 << " on geometric element " 00591 << Utility::enum_to_string(type) << std::endl 00592 << "could not be p refined past FEInterface::max_order = " 00593 << FEInterface::max_order(base_fe_type,type) 00594 << std::endl; 00595 # endif 00596 elem->set_p_level(FEInterface::max_order(base_fe_type,type) 00597 - base_fe_type.order); 00598 } 00599 #endif 00600 00601 fe_type.order = static_cast<Order>(fe_type.order + 00602 elem->p_level()); 00603 00604 // Allocate the vertex DOFs 00605 for (unsigned int n=0; n<elem->n_nodes(); n++) 00606 { 00607 Node* node = elem->get_node(n); 00608 00609 if (elem->is_vertex(n)) 00610 { 00611 const unsigned int old_node_dofs = 00612 node->n_comp_group(sys_num, vg); 00613 00614 const unsigned int vertex_dofs = 00615 std::max(FEInterface::n_dofs_at_node(dim, fe_type, 00616 type, n), 00617 old_node_dofs); 00618 00619 // Some discontinuous FEs have no vertex dofs 00620 if (vertex_dofs > old_node_dofs) 00621 { 00622 node->set_n_comp_group(sys_num, vg, 00623 vertex_dofs); 00624 00625 // Abusing dof_number to set a "this is a 00626 // vertex" flag 00627 node->set_vg_dof_base(sys_num, vg, 00628 vertex_dofs); 00629 00630 // std::cout << "sys_num,vg,old_node_dofs,vertex_dofs=" 00631 // << sys_num << "," 00632 // << vg << "," 00633 // << old_node_dofs << "," 00634 // << vertex_dofs << '\n', 00635 // node->debug_buffer(); 00636 00637 // libmesh_assert_equal_to (vertex_dofs, node->n_comp(sys_num, vg)); 00638 // libmesh_assert_equal_to (vertex_dofs, node->vg_dof_base(sys_num, vg)); 00639 } 00640 } 00641 } 00642 } // done counting vertex dofs 00643 00644 // count edge & face dofs next 00645 elem_it = mesh.active_elements_begin(); 00646 00647 for ( ; elem_it != elem_end; ++elem_it) 00648 { 00649 Elem* elem = *elem_it; 00650 libmesh_assert(elem); 00651 00652 // Skip the numbering if this variable is 00653 // not active on this element's subdomain 00654 if (!vg_description.active_on_subdomain(elem->subdomain_id())) 00655 continue; 00656 00657 const ElemType type = elem->type(); 00658 const unsigned int dim = elem->dim(); 00659 00660 FEType fe_type = base_fe_type; 00661 fe_type.order = static_cast<Order>(fe_type.order + 00662 elem->p_level()); 00663 00664 // Allocate the edge and face DOFs 00665 for (unsigned int n=0; n<elem->n_nodes(); n++) 00666 { 00667 Node* node = elem->get_node(n); 00668 00669 const unsigned int old_node_dofs = 00670 node->n_comp_group(sys_num, vg); 00671 00672 const unsigned int vertex_dofs = old_node_dofs? 00673 libmesh_cast_int<unsigned int>(node->vg_dof_base (sys_num,vg)):0; 00674 00675 const unsigned int new_node_dofs = 00676 FEInterface::n_dofs_at_node(dim, fe_type, type, n); 00677 00678 // We've already allocated vertex DOFs 00679 if (elem->is_vertex(n)) 00680 { 00681 libmesh_assert_greater_equal (old_node_dofs, vertex_dofs); 00682 // //if (vertex_dofs < new_node_dofs) 00683 // std::cout << "sys_num,vg,old_node_dofs,vertex_dofs,new_node_dofs=" 00684 // << sys_num << "," 00685 // << vg << "," 00686 // << old_node_dofs << "," 00687 // << vertex_dofs << "," 00688 // << new_node_dofs << '\n', 00689 // node->debug_buffer(); 00690 00691 libmesh_assert_greater_equal (vertex_dofs, new_node_dofs); 00692 } 00693 // We need to allocate the rest 00694 else 00695 { 00696 // If this has no dofs yet, it needs no vertex 00697 // dofs, so we just give it edge or face dofs 00698 if (!old_node_dofs) 00699 { 00700 node->set_n_comp_group(sys_num, vg, 00701 new_node_dofs); 00702 // Abusing dof_number to set a "this has no 00703 // vertex dofs" flag 00704 if (new_node_dofs) 00705 node->set_vg_dof_base(sys_num, vg, 00706 0); 00707 } 00708 00709 // If this has dofs, but has no vertex dofs, 00710 // it may still need more edge or face dofs if 00711 // we're p-refined. 00712 else if (vertex_dofs == 0) 00713 { 00714 if (new_node_dofs > old_node_dofs) 00715 { 00716 node->set_n_comp_group(sys_num, vg, 00717 new_node_dofs); 00718 00719 node->set_vg_dof_base(sys_num, vg, 00720 vertex_dofs); 00721 } 00722 } 00723 // If this is another element's vertex, 00724 // add more (non-overlapping) edge/face dofs if 00725 // necessary 00726 else if (extra_hanging_dofs) 00727 { 00728 if (new_node_dofs > old_node_dofs - vertex_dofs) 00729 { 00730 node->set_n_comp_group(sys_num, vg, 00731 vertex_dofs + new_node_dofs); 00732 00733 node->set_vg_dof_base(sys_num, vg, 00734 vertex_dofs); 00735 } 00736 } 00737 // If this is another element's vertex, add any 00738 // (overlapping) edge/face dofs if necessary 00739 else 00740 { 00741 libmesh_assert_greater_equal (old_node_dofs, vertex_dofs); 00742 if (new_node_dofs > old_node_dofs) 00743 { 00744 node->set_n_comp_group(sys_num, vg, 00745 new_node_dofs); 00746 00747 node->set_vg_dof_base (sys_num, vg, 00748 vertex_dofs); 00749 } 00750 } 00751 } 00752 } 00753 // Allocate the element DOFs 00754 const unsigned int dofs_per_elem = 00755 FEInterface::n_dofs_per_elem(dim, fe_type, 00756 type); 00757 00758 elem->set_n_comp_group(sys_num, vg, dofs_per_elem); 00759 00760 } 00761 } // end loop over variable groups 00762 00763 // Calling DofMap::reinit() by itself makes little sense, 00764 // so we won't bother with nonlocal DofObjects. 00765 // Those will be fixed by distribute_dofs 00766 00767 //------------------------------------------------------------ 00768 // Finally, clear all the current DOF indices 00769 // (distribute_dofs expects them cleared!) 00770 this->invalidate_dofs(mesh); 00771 00772 STOP_LOG("reinit()", "DofMap"); 00773 }
| void libMesh::DofMap::remove_dirichlet_boundary | ( | const DirichletBoundary & | dirichlet_boundary | ) |
Removes the specified Dirichlet boundary from the system.
Definition at line 3082 of file dof_map_constraints.C.
References _dirichlet_boundaries, libMesh::DirichletBoundary::b, end, and libMesh::DirichletBoundary::variables.
03083 { 03084 // Find a boundary condition matching the one to be removed 03085 std::vector<DirichletBoundary *>::iterator it = _dirichlet_boundaries->begin(); 03086 std::vector<DirichletBoundary *>::iterator end = _dirichlet_boundaries->end(); 03087 for (; it != end; ++it) 03088 { 03089 DirichletBoundary *bdy = *it; 03090 03091 if ((bdy->b == boundary_to_remove.b) && 03092 bdy->variables == boundary_to_remove.variables) 03093 break; 03094 } 03095 03096 // Delete it and remove it 03097 libmesh_assert (it != end); 03098 delete *it; 03099 _dirichlet_boundaries->erase(it); 03100 }
| void libMesh::DofMap::SCALAR_dof_indices | ( | std::vector< dof_id_type > & | di, | |
| const unsigned int | vn, | |||
| const bool | old_dofs = false | |||
| ) | const |
Fills the vector di with the global degree of freedom indices corresponding to the SCALAR variable vn. If old_dofs=true, the old SCALAR dof indices are returned. Note that we do not need to pass in an element since SCALARs are global variables.
Referenced by dof_indices(), old_dof_indices(), libMesh::System::project_vector(), libMesh::System::read_parallel_data(), libMesh::System::read_SCALAR_dofs(), libMesh::System::write_parallel_data(), and libMesh::System::write_SCALAR_dofs().
| void libMesh::DofMap::scatter_constraints | ( | MeshBase & | mesh | ) |
Sends constraint equations to constraining processors
Definition at line 2569 of file dof_map_constraints.C.
References _dof_constraints, _end_df, _node_constraints, libMesh::MeshBase::active_not_local_elements_begin(), libMesh::MeshBase::active_not_local_elements_end(), libMesh::CommWorld, dof_indices(), end, libMesh::DofObject::id(), is_constrained_dof(), is_constrained_node(), libMesh::Parallel::Communicator::max(), libMesh::n_processors(), libMesh::MeshBase::node_ptr(), libMesh::DofObject::processor_id(), libMesh::processor_id(), libMesh::Parallel::Communicator::send_receive(), and libMesh::Parallel::Communicator::send_receive_packed_range().
Referenced by process_constraints().
02570 { 02571 // At this point each processor with a constrained node knows 02572 // the corresponding constraint row, but we also need each processor 02573 // with a constrainer node to know the corresponding row(s). 02574 02575 // This function must be run on all processors at once 02576 parallel_only(); 02577 02578 // Return immediately if there's nothing to gather 02579 if (libMesh::n_processors() == 1) 02580 return; 02581 02582 // We might get to return immediately if none of the processors 02583 // found any constraints 02584 unsigned int has_constraints = !_dof_constraints.empty() 02585 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02586 || !_node_constraints.empty() 02587 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02588 ; 02589 CommWorld.max(has_constraints); 02590 if (!has_constraints) 02591 return; 02592 02593 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02594 std::vector<std::set<dof_id_type> > pushed_node_ids(libMesh::n_processors()); 02595 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02596 02597 std::vector<std::set<dof_id_type> > pushed_ids(libMesh::n_processors()); 02598 02599 // Collect the dof constraints I need to push to each processor 02600 dof_id_type constrained_proc_id = 0; 02601 for (DofConstraints::iterator i = _dof_constraints.begin(); 02602 i != _dof_constraints.end(); ++i) 02603 { 02604 const dof_id_type constrained = i->first; 02605 while (constrained >= _end_df[constrained_proc_id]) 02606 constrained_proc_id++; 02607 02608 if (constrained_proc_id != libMesh::processor_id()) 02609 continue; 02610 02611 DofConstraintRow &row = i->second.first; 02612 for (DofConstraintRow::iterator j = row.begin(); 02613 j != row.end(); ++j) 02614 { 02615 const dof_id_type constraining = j->first; 02616 02617 processor_id_type constraining_proc_id = 0; 02618 while (constraining >= _end_df[constraining_proc_id]) 02619 constraining_proc_id++; 02620 02621 if (constraining_proc_id != libMesh::processor_id() && 02622 constraining_proc_id != constrained_proc_id) 02623 pushed_ids[constraining_proc_id].insert(constrained); 02624 } 02625 } 02626 02627 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02628 // Collect the node constraints to push to each processor 02629 for (NodeConstraints::iterator i = _node_constraints.begin(); 02630 i != _node_constraints.end(); ++i) 02631 { 02632 const Node *constrained = i->first; 02633 02634 if (constrained->processor_id() != libMesh::processor_id()) 02635 continue; 02636 02637 NodeConstraintRow &row = i->second.first; 02638 for (NodeConstraintRow::iterator j = row.begin(); 02639 j != row.end(); ++j) 02640 { 02641 const Node *constraining = j->first; 02642 02643 if (constraining->processor_id() != libMesh::processor_id() && 02644 constraining->processor_id() != constrained->processor_id()) 02645 pushed_node_ids[constraining->processor_id()].insert(constrained->id()); 02646 } 02647 } 02648 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02649 02650 // Now trade constraint rows 02651 for (processor_id_type p = 0; p != libMesh::n_processors(); ++p) 02652 { 02653 // Push to processor procup while receiving from procdown 02654 processor_id_type procup = (libMesh::processor_id() + p) % 02655 libMesh::n_processors(); 02656 processor_id_type procdown = (libMesh::n_processors() + 02657 libMesh::processor_id() - p) % 02658 libMesh::n_processors(); 02659 02660 // Pack the dof constraint rows and rhs's to push to procup 02661 const std::size_t pushed_ids_size = pushed_ids[procup].size(); 02662 std::vector<std::vector<dof_id_type> > pushed_keys(pushed_ids_size); 02663 std::vector<std::vector<Real> > pushed_vals(pushed_ids_size); 02664 std::vector<Number> pushed_rhss(pushed_ids_size); 02665 02666 std::set<dof_id_type>::const_iterator it; 02667 std::size_t push_i; 02668 for (push_i = 0, it = pushed_ids[procup].begin(); 02669 it != pushed_ids[procup].end(); ++push_i, ++it) 02670 { 02671 const dof_id_type constrained = *it; 02672 DofConstraintRow &row = _dof_constraints[constrained].first; 02673 std::size_t row_size = row.size(); 02674 pushed_keys[push_i].reserve(row_size); 02675 pushed_vals[push_i].reserve(row_size); 02676 for (DofConstraintRow::iterator j = row.begin(); 02677 j != row.end(); ++j) 02678 { 02679 pushed_keys[push_i].push_back(j->first); 02680 pushed_vals[push_i].push_back(j->second); 02681 } 02682 pushed_rhss[push_i] = _dof_constraints[constrained].second; 02683 } 02684 02685 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02686 // Pack the node constraint rows to push to procup 02687 const std::size_t pushed_node_ids_size = pushed_node_ids[procup].size(); 02688 std::vector<std::vector<dof_id_type> > pushed_node_keys(pushed_node_ids_size); 02689 std::vector<std::vector<Real> > pushed_node_vals(pushed_node_ids_size); 02690 std::vector<Point> pushed_node_offsets(pushed_node_ids_size); 02691 std::set<const Node*> pushed_nodes; 02692 02693 for (push_i = 0, it = pushed_node_ids[procup].begin(); 02694 it != pushed_node_ids[procup].end(); ++push_i, ++it) 02695 { 02696 const Node *constrained = mesh.node_ptr(*it); 02697 02698 if (constrained->processor_id() != procdown) 02699 pushed_nodes.insert(constrained); 02700 02701 NodeConstraintRow &row = _node_constraints[constrained].first; 02702 std::size_t row_size = row.size(); 02703 pushed_node_keys[push_i].reserve(row_size); 02704 pushed_node_vals[push_i].reserve(row_size); 02705 for (NodeConstraintRow::iterator j = row.begin(); 02706 j != row.end(); ++j) 02707 { 02708 const Node* constraining = j->first; 02709 02710 pushed_node_keys[push_i].push_back(constraining->id()); 02711 pushed_node_vals[push_i].push_back(j->second); 02712 02713 if (constraining->processor_id() != procup) 02714 pushed_nodes.insert(constraining); 02715 } 02716 pushed_node_offsets[push_i] = _node_constraints[constrained].second; 02717 } 02718 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02719 02720 // Trade pushed dof constraint rows 02721 std::vector<dof_id_type> pushed_ids_from_me 02722 (pushed_ids[procup].begin(), pushed_ids[procup].end()); 02723 std::vector<dof_id_type> pushed_ids_to_me; 02724 std::vector<std::vector<dof_id_type> > pushed_keys_to_me; 02725 std::vector<std::vector<Real> > pushed_vals_to_me; 02726 std::vector<Number> pushed_rhss_to_me; 02727 CommWorld.send_receive(procup, pushed_ids_from_me, 02728 procdown, pushed_ids_to_me); 02729 CommWorld.send_receive(procup, pushed_keys, 02730 procdown, pushed_keys_to_me); 02731 CommWorld.send_receive(procup, pushed_vals, 02732 procdown, pushed_vals_to_me); 02733 CommWorld.send_receive(procup, pushed_rhss, 02734 procdown, pushed_rhss_to_me); 02735 libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_keys_to_me.size()); 02736 libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_vals_to_me.size()); 02737 libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_rhss_to_me.size()); 02738 02739 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02740 // Trade pushed node constraint rows 02741 std::vector<dof_id_type> pushed_node_ids_from_me 02742 (pushed_node_ids[procup].begin(), pushed_node_ids[procup].end()); 02743 std::vector<dof_id_type> pushed_node_ids_to_me; 02744 std::vector<std::vector<dof_id_type> > pushed_node_keys_to_me; 02745 std::vector<std::vector<Real> > pushed_node_vals_to_me; 02746 std::vector<Point> pushed_node_offsets_to_me; 02747 CommWorld.send_receive(procup, pushed_node_ids_from_me, 02748 procdown, pushed_node_ids_to_me); 02749 CommWorld.send_receive(procup, pushed_node_keys, 02750 procdown, pushed_node_keys_to_me); 02751 CommWorld.send_receive(procup, pushed_node_vals, 02752 procdown, pushed_node_vals_to_me); 02753 CommWorld.send_receive(procup, pushed_node_offsets, 02754 procdown, pushed_node_offsets_to_me); 02755 02756 // Constraining nodes might not even exist on our subset of 02757 // a distributed mesh, so let's make them exist. 02758 CommWorld.send_receive_packed_range 02759 (procup, &mesh, pushed_nodes.begin(), pushed_nodes.end(), 02760 procdown, &mesh, mesh_inserter_iterator<Node>(mesh)); 02761 02762 libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_keys_to_me.size()); 02763 libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_vals_to_me.size()); 02764 libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_offsets_to_me.size()); 02765 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02766 02767 // Add the dof constraints that I've been sent 02768 for (std::size_t i = 0; i != pushed_ids_to_me.size(); ++i) 02769 { 02770 libmesh_assert_equal_to (pushed_keys_to_me[i].size(), pushed_vals_to_me[i].size()); 02771 02772 dof_id_type constrained = pushed_ids_to_me[i]; 02773 02774 // If we don't already have a constraint for this dof, 02775 // add the one we were sent 02776 if (!this->is_constrained_dof(constrained)) 02777 { 02778 DofConstraintRow &row = _dof_constraints[constrained].first; 02779 for (std::size_t j = 0; j != pushed_keys_to_me[i].size(); ++j) 02780 { 02781 row[pushed_keys_to_me[i][j]] = pushed_vals_to_me[i][j]; 02782 } 02783 _dof_constraints[constrained].second = pushed_rhss_to_me[i]; 02784 } 02785 } 02786 02787 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 02788 // Add the node constraints that I've been sent 02789 for (std::size_t i = 0; i != pushed_node_ids_to_me.size(); ++i) 02790 { 02791 libmesh_assert_equal_to (pushed_node_keys_to_me[i].size(), pushed_node_vals_to_me[i].size()); 02792 02793 dof_id_type constrained_id = pushed_node_ids_to_me[i]; 02794 02795 // If we don't already have a constraint for this node, 02796 // add the one we were sent 02797 const Node *constrained = mesh.node_ptr(constrained_id); 02798 if (!this->is_constrained_node(constrained)) 02799 { 02800 NodeConstraintRow &row = _node_constraints[constrained].first; 02801 for (std::size_t j = 0; j != pushed_node_keys_to_me[i].size(); ++j) 02802 { 02803 const Node *key_node = mesh.node_ptr(pushed_node_keys_to_me[i][j]); 02804 libmesh_assert(key_node); 02805 row[key_node] = pushed_node_vals_to_me[i][j]; 02806 } 02807 _node_constraints[constrained].second = pushed_node_offsets_to_me[i]; 02808 } 02809 } 02810 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 02811 } 02812 02813 // Next we need to push constraints to processors which don't own 02814 // the constrained dof, don't own the constraining dof, but own an 02815 // element supporting the constraining dof. 02816 // 02817 // We need to be able to quickly look up constrained dof ids by what 02818 // constrains them, so that we can handle the case where we see a 02819 // foreign element containing one of our constraining DoF ids and we 02820 // need to push that constraint. 02821 // 02822 // Getting distributed adaptive sparsity patterns right is hard. 02823 02824 typedef std::map<dof_id_type, std::set<dof_id_type> > DofConstrainsMap; 02825 DofConstrainsMap dof_id_constrains; 02826 02827 for (DofConstraints::iterator i = _dof_constraints.begin(); 02828 i != _dof_constraints.end(); ++i) 02829 { 02830 const dof_id_type constrained = i->first; 02831 DofConstraintRow &row = i->second.first; 02832 for (DofConstraintRow::iterator j = row.begin(); 02833 j != row.end(); ++j) 02834 { 02835 const dof_id_type constraining = j->first; 02836 02837 dof_id_type constraining_proc_id = 0; 02838 while (constraining >= _end_df[constraining_proc_id]) 02839 constraining_proc_id++; 02840 02841 if (constraining_proc_id == libMesh::processor_id()) 02842 dof_id_constrains[constraining].insert(constrained); 02843 } 02844 } 02845 02846 // Loop over all foreign elements, find any supporting our 02847 // constrained dof indices. 02848 pushed_ids.clear(); 02849 pushed_ids.resize(libMesh::n_processors()); 02850 02851 MeshBase::const_element_iterator it = mesh.active_not_local_elements_begin(), 02852 end = mesh.active_not_local_elements_end(); 02853 for (; it != end; ++it) 02854 { 02855 const Elem *elem = *it; 02856 02857 std::vector<dof_id_type> my_dof_indices; 02858 this->dof_indices (elem, my_dof_indices); 02859 02860 for (std::size_t i=0; i != my_dof_indices.size(); ++i) 02861 { 02862 DofConstrainsMap::const_iterator dcmi = 02863 dof_id_constrains.find(my_dof_indices[i]); 02864 if (dcmi != dof_id_constrains.end()) 02865 { 02866 for (DofConstrainsMap::mapped_type::const_iterator mti = 02867 dcmi->second.begin(); 02868 mti != dcmi->second.end(); ++mti) 02869 { 02870 const dof_id_type constrained = *mti; 02871 02872 dof_id_type the_constrained_proc_id = 0; 02873 while (constrained >= _end_df[the_constrained_proc_id]) 02874 the_constrained_proc_id++; 02875 02876 const dof_id_type elemproc = elem->processor_id(); 02877 if (elemproc != the_constrained_proc_id) 02878 pushed_ids[elemproc].insert(constrained); 02879 } 02880 } 02881 } 02882 } 02883 02884 // One last trade of constraint rows 02885 for (processor_id_type p = 0; p != libMesh::n_processors(); ++p) 02886 { 02887 // Push to processor procup while receiving from procdown 02888 processor_id_type procup = (libMesh::processor_id() + p) % 02889 libMesh::n_processors(); 02890 processor_id_type procdown = (libMesh::n_processors() + 02891 libMesh::processor_id() - p) % 02892 libMesh::n_processors(); 02893 02894 // Pack the dof constraint rows and rhs's to push to procup 02895 const std::size_t pushed_ids_size = pushed_ids[procup].size(); 02896 std::vector<std::vector<dof_id_type> > pushed_keys(pushed_ids_size); 02897 std::vector<std::vector<Real> > pushed_vals(pushed_ids_size); 02898 std::vector<Number> pushed_rhss(pushed_ids_size); 02899 02900 // As long as we're declaring them outside the loop, let's initialize them too! 02901 std::set<dof_id_type>::const_iterator pushed_ids_iter = pushed_ids[procup].begin(); 02902 std::size_t push_i = 0; 02903 for ( ; pushed_ids_iter != pushed_ids[procup].end(); ++push_i, ++pushed_ids_iter) 02904 { 02905 const dof_id_type constrained = *pushed_ids_iter; 02906 DofConstraintRow &row = _dof_constraints[constrained].first; 02907 std::size_t row_size = row.size(); 02908 pushed_keys[push_i].reserve(row_size); 02909 pushed_vals[push_i].reserve(row_size); 02910 for (DofConstraintRow::iterator j = row.begin(); 02911 j != row.end(); ++j) 02912 { 02913 pushed_keys[push_i].push_back(j->first); 02914 pushed_vals[push_i].push_back(j->second); 02915 } 02916 pushed_rhss[push_i] = _dof_constraints[constrained].second; 02917 } 02918 02919 // Trade pushed dof constraint rows 02920 std::vector<dof_id_type> pushed_ids_from_me 02921 (pushed_ids[procup].begin(), pushed_ids[procup].end()); 02922 std::vector<dof_id_type> pushed_ids_to_me; 02923 std::vector<std::vector<dof_id_type> > pushed_keys_to_me; 02924 std::vector<std::vector<Real> > pushed_vals_to_me; 02925 std::vector<Number> pushed_rhss_to_me; 02926 CommWorld.send_receive(procup, pushed_ids_from_me, 02927 procdown, pushed_ids_to_me); 02928 CommWorld.send_receive(procup, pushed_keys, 02929 procdown, pushed_keys_to_me); 02930 CommWorld.send_receive(procup, pushed_vals, 02931 procdown, pushed_vals_to_me); 02932 CommWorld.send_receive(procup, pushed_rhss, 02933 procdown, pushed_rhss_to_me); 02934 libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_keys_to_me.size()); 02935 libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_vals_to_me.size()); 02936 libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_rhss_to_me.size()); 02937 02938 // Add the dof constraints that I've been sent 02939 for (std::size_t i = 0; i != pushed_ids_to_me.size(); ++i) 02940 { 02941 libmesh_assert_equal_to (pushed_keys_to_me[i].size(), pushed_vals_to_me[i].size()); 02942 02943 dof_id_type constrained = pushed_ids_to_me[i]; 02944 02945 // If we don't already have a constraint for this dof, 02946 // add the one we were sent 02947 if (!this->is_constrained_dof(constrained)) 02948 { 02949 DofConstraintRow &row = _dof_constraints[constrained].first; 02950 for (std::size_t j = 0; j != pushed_keys_to_me[i].size(); ++j) 02951 { 02952 row[pushed_keys_to_me[i][j]] = pushed_vals_to_me[i][j]; 02953 } 02954 _dof_constraints[constrained].second = pushed_rhss_to_me[i]; 02955 } 02956 } 02957 } 02958 }
| void libMesh::DofMap::set_nonlocal_dof_objects | ( | iterator_type | objects_begin, | |
| iterator_type | objects_end, | |||
| MeshBase & | mesh, | |||
| dofobject_accessor | objects | |||
| ) | [inline, private] |
Helper function for distributing dofs in parallel
Definition at line 274 of file dof_map.C.
References libMesh::Parallel::Communicator::allgather(), libMesh::CommWorld, 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::n_processors(), libMesh::DofObject::n_var_groups(), n_variable_groups(), libMesh::DofObject::n_vars(), libMesh::processor_id(), libMesh::DofObject::processor_id(), libMesh::Parallel::Communicator::send_receive(), libMesh::DofObject::set_n_comp_group(), libMesh::DofObject::set_vg_dof_base(), sys_number(), and libMesh::DofObject::vg_dof_base().
Referenced by distribute_dofs().
00278 { 00279 // This function must be run on all processors at once 00280 parallel_only(); 00281 00282 // First, iterate over local objects to find out how many 00283 // are on each processor 00284 std::vector<dof_id_type> 00285 ghost_objects_from_proc(libMesh::n_processors(), 0); 00286 00287 iterator_type it = objects_begin; 00288 00289 for (; it != objects_end; ++it) 00290 { 00291 DofObject *obj = *it; 00292 00293 if (obj) 00294 { 00295 processor_id_type obj_procid = obj->processor_id(); 00296 // We'd better be completely partitioned by now 00297 libmesh_assert_not_equal_to (obj_procid, DofObject::invalid_processor_id); 00298 ghost_objects_from_proc[obj_procid]++; 00299 } 00300 } 00301 00302 std::vector<dof_id_type> objects_on_proc(libMesh::n_processors(), 0); 00303 CommWorld.allgather(ghost_objects_from_proc[libMesh::processor_id()], 00304 objects_on_proc); 00305 00306 #ifdef DEBUG 00307 for (processor_id_type p=0; p != libMesh::n_processors(); ++p) 00308 libmesh_assert_less_equal (ghost_objects_from_proc[p], objects_on_proc[p]); 00309 #endif 00310 00311 // Request sets to send to each processor 00312 std::vector<std::vector<dof_id_type> > 00313 requested_ids(libMesh::n_processors()); 00314 00315 // We know how many of our objects live on each processor, so 00316 // reserve() space for requests from each. 00317 for (processor_id_type p=0; p != libMesh::n_processors(); ++p) 00318 if (p != libMesh::processor_id()) 00319 requested_ids[p].reserve(ghost_objects_from_proc[p]); 00320 00321 for (it = objects_begin; it != objects_end; ++it) 00322 { 00323 DofObject *obj = *it; 00324 if (obj->processor_id() != DofObject::invalid_processor_id) 00325 requested_ids[obj->processor_id()].push_back(obj->id()); 00326 } 00327 #ifdef DEBUG 00328 for (processor_id_type p=0; p != libMesh::n_processors(); ++p) 00329 libmesh_assert_equal_to (requested_ids[p].size(), ghost_objects_from_proc[p]); 00330 #endif 00331 00332 // Next set ghost object n_comps from other processors 00333 for (processor_id_type p=1; p != libMesh::n_processors(); ++p) 00334 { 00335 // Trade my requests with processor procup and procdown 00336 processor_id_type procup = (libMesh::processor_id() + p) % 00337 libMesh::n_processors(); 00338 processor_id_type procdown = (libMesh::n_processors() + 00339 libMesh::processor_id() - p) % 00340 libMesh::n_processors(); 00341 std::vector<dof_id_type> request_to_fill; 00342 CommWorld.send_receive(procup, requested_ids[procup], 00343 procdown, request_to_fill); 00344 00345 // Fill those requests 00346 const unsigned int 00347 sys_num = this->sys_number(), 00348 n_var_groups = this->n_variable_groups(); 00349 00350 std::vector<dof_id_type> ghost_data 00351 (request_to_fill.size() * 2 * n_var_groups); 00352 00353 for (std::size_t i=0; i != request_to_fill.size(); ++i) 00354 { 00355 DofObject *requested = (this->*objects)(mesh, request_to_fill[i]); 00356 libmesh_assert(requested); 00357 libmesh_assert_equal_to (requested->processor_id(), libMesh::processor_id()); 00358 libmesh_assert_equal_to (requested->n_var_groups(sys_num), n_var_groups); 00359 for (unsigned int vg=0; vg != n_var_groups; ++vg) 00360 { 00361 unsigned int n_comp_g = 00362 requested->n_comp_group(sys_num, vg); 00363 ghost_data[i*2*n_var_groups+vg] = n_comp_g; 00364 dof_id_type my_first_dof = n_comp_g ? 00365 requested->vg_dof_base(sys_num, vg) : 0; 00366 libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id); 00367 ghost_data[i*2*n_var_groups+n_var_groups+vg] = my_first_dof; 00368 } 00369 } 00370 00371 // Trade back the results 00372 std::vector<dof_id_type> filled_request; 00373 CommWorld.send_receive(procdown, ghost_data, 00374 procup, filled_request); 00375 00376 // And copy the id changes we've now been informed of 00377 libmesh_assert_equal_to (filled_request.size(), 00378 requested_ids[procup].size() * 2 * n_var_groups); 00379 for (std::size_t i=0; i != requested_ids[procup].size(); ++i) 00380 { 00381 DofObject *requested = (this->*objects)(mesh, requested_ids[procup][i]); 00382 libmesh_assert(requested); 00383 libmesh_assert_equal_to (requested->processor_id(), procup); 00384 for (unsigned int vg=0; vg != n_var_groups; ++vg) 00385 { 00386 unsigned int n_comp_g = 00387 libmesh_cast_int<unsigned int>(filled_request[i*2*n_var_groups+vg]); 00388 requested->set_n_comp_group(sys_num, vg, n_comp_g); 00389 if (n_comp_g) 00390 { 00391 dof_id_type my_first_dof = 00392 filled_request[i*2*n_var_groups+n_var_groups+vg]; 00393 libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id); 00394 requested->set_vg_dof_base 00395 (sys_num, vg, my_first_dof); 00396 } 00397 } 00398 } 00399 } 00400 00401 #ifdef DEBUG 00402 // Double check for invalid dofs 00403 for (it = objects_begin; it != objects_end; ++it) 00404 { 00405 DofObject *obj = *it; 00406 libmesh_assert (obj); 00407 unsigned int num_variables = obj->n_vars(this->sys_number()); 00408 for (unsigned int v=0; v != num_variables; ++v) 00409 { 00410 unsigned int n_comp = 00411 obj->n_comp(this->sys_number(), v); 00412 dof_id_type my_first_dof = n_comp ? 00413 obj->dof_number(this->sys_number(), v, 0) : 0; 00414 libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id); 00415 } 00416 } 00417 #endif 00418 }
| unsigned int libMesh::DofMap::sys_number | ( | ) | const [inline] |
- Returns:
- the number of the system we are responsible for.
Definition at line 1162 of file dof_map.h.
References _sys_number.
Referenced by add_neighbors_to_send_list(), libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), constrain_p_dofs(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), dof_indices(), invalidate_dofs(), old_dof_indices(), reinit(), and set_nonlocal_dof_objects().
01163 { 01164 return _sys_number; 01165 }
| bool libMesh::DofMap::use_coupled_neighbor_dofs | ( | const MeshBase & | mesh | ) | const |
Tells other library functions whether or not this problem includes coupling between dofs in neighboring cells, as can currently be specified on the command line or inferred from the use of all discontinuous variables.
Definition at line 1416 of file dof_map.C.
References libMesh::FEAbstract::build(), libMeshEnums::DISCONTINUOUS, libMesh::MeshBase::mesh_dimension(), n_variables(), libMesh::on_command_line(), and variable_type().
01417 { 01418 // If we were asked on the command line, then we need to 01419 // include sensitivities between neighbor degrees of freedom 01420 bool implicit_neighbor_dofs = 01421 libMesh::on_command_line ("--implicit_neighbor_dofs"); 01422 01423 // look at all the variables in this system. If every one is 01424 // discontinuous then the user must be doing DG/FVM, so be nice 01425 // and force implicit_neighbor_dofs=true 01426 { 01427 bool all_discontinuous_dofs = true; 01428 01429 for (unsigned int var=0; var<this->n_variables(); var++) 01430 if (FEAbstract::build (mesh.mesh_dimension(), 01431 this->variable_type(var))->get_continuity() != DISCONTINUOUS) 01432 all_discontinuous_dofs = false; 01433 01434 if (all_discontinuous_dofs) 01435 implicit_neighbor_dofs = true; 01436 } 01437 01438 return implicit_neighbor_dofs; 01439 }
| const Variable & libMesh::DofMap::variable | ( | const unsigned int | c | ) | const [inline] |
- Returns:
- the variable description object for variable
c.
Definition at line 1180 of file dof_map.h.
References _variables.
Referenced by DMLibMeshSetSystem(), dof_indices(), old_dof_indices(), libMesh::BoundaryProjectSolution::operator()(), libMesh::ProjectFEMSolution::operator()(), and libMesh::ProjectSolution::operator()().
01181 { 01182 libmesh_assert_less (c, _variables.size()); 01183 01184 return _variables[c]; 01185 }
| const VariableGroup & libMesh::DofMap::variable_group | ( | const unsigned int | c | ) | const [inline] |
- Returns:
- the
VariableGroupdescription object for groupg.
Definition at line 1170 of file dof_map.h.
References _variable_groups.
Referenced by distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), libMesh::System::get_info(), and reinit().
01171 { 01172 libmesh_assert_less (g, _variable_groups.size()); 01173 01174 return _variable_groups[g]; 01175 }
| Order libMesh::DofMap::variable_group_order | ( | const unsigned int | vg | ) | const [inline] |
- Returns:
- the approximation order for
VariableGroupvg.
Definition at line 1200 of file dof_map.h.
References _variable_groups.
01201 { 01202 libmesh_assert_less (vg, _variable_groups.size()); 01203 01204 return _variable_groups[vg].type().order; 01205 }
| const FEType & libMesh::DofMap::variable_group_type | ( | const unsigned int | vg | ) | const [inline] |
- Returns:
- the finite element type for
VariableGroupvg.
Definition at line 1220 of file dof_map.h.
References _variable_groups.
01221 { 01222 libmesh_assert_less (vg, _variable_groups.size()); 01223 01224 return _variable_groups[vg].type(); 01225 }
| Order libMesh::DofMap::variable_order | ( | const unsigned int | c | ) | const [inline] |
- Returns:
- the approximation order for variable
c.
Definition at line 1190 of file dof_map.h.
References _variables.
01191 { 01192 libmesh_assert_less (c, _variables.size()); 01193 01194 return _variables[c].type().order; 01195 }
| const FEType & libMesh::DofMap::variable_type | ( | const unsigned int | c | ) | const [inline] |
- Returns:
- the finite element type for variable
c.
Definition at line 1210 of file dof_map.h.
References _variables.
Referenced by libMesh::ExactSolution::_compute_error(), libMesh::HPCoarsenTest::add_projection(), libMesh::System::calculate_norm(), libMesh::FEGenericBase< OutputType >::coarsened_dof_values(), libMesh::FEInterface::compute_constraints(), libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), libMesh::FEGenericBase< OutputType >::compute_proj_constraints(), constrain_p_dofs(), dof_indices(), libMesh::JumpErrorEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::MeshFunction::gradient(), libMesh::MeshFunction::hessian(), old_dof_indices(), libMesh::WeightedPatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::PatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::MeshFunction::operator()(), libMesh::HPCoarsenTest::select_refinement(), and use_coupled_neighbor_dofs().
01211 { 01212 libmesh_assert_less (c, _variables.size()); 01213 01214 return _variables[c].type(); 01215 }
Friends And Related Function Documentation
friend class SparsityPattern::Build [friend] |
Member Data Documentation
Function object to call to add extra entries to the send list
Definition at line 1055 of file dof_map.h.
Referenced by attach_extra_send_list_object(), and prepare_send_list().
Funtion object to call to add extra entries to the sparsity pattern
Definition at line 1038 of file dof_map.h.
Referenced by attach_extra_sparsity_object().
ReferenceCounter::Counts libMesh::ReferenceCounter::_counts [static, protected, inherited] |
Actually holds the data.
Definition at line 118 of file reference_counter.h.
Referenced by libMesh::ReferenceCounter::get_info(), libMesh::ReferenceCounter::increment_constructor_count(), and libMesh::ReferenceCounter::increment_destructor_count().
Data structure containing Dirichlet functions. The ith entry is the constraint matrix row for boundaryid i.
Definition at line 1152 of file dof_map.h.
Referenced by add_dirichlet_boundary(), create_dof_constraints(), get_dirichlet_boundaries(), remove_dirichlet_boundary(), and ~DofMap().
Data structure containing DOF constraints. The ith entry is the constraint matrix row for DOF i.
Definition at line 1128 of file dof_map.h.
Referenced by add_constraint_row(), add_constraints_to_send_list(), allgather_recursive_constraints(), build_constraint_matrix(), clear(), constrain_element_dyad_matrix(), constrain_element_matrix(), constrain_element_matrix_and_vector(), constrain_element_vector(), constrain_nothing(), constrain_p_dofs(), constraint_rows_begin(), constraint_rows_end(), create_dof_constraints(), enforce_constraints_exactly(), find_connected_dofs(), get_info(), get_local_constraints(), is_constrained_dof(), max_constraint_error(), n_local_constrained_dofs(), process_constraints(), and scatter_constraints().
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.
bool libMesh::ReferenceCounter::_enable_print_counter = true [static, protected, inherited] |
Flag to control whether reference count information is printed when print_info is called.
Definition at line 137 of file reference_counter.h.
Referenced by libMesh::ReferenceCounter::disable_print_counter_info(), libMesh::ReferenceCounter::enable_print_counter_info(), and libMesh::ReferenceCounter::print_info().
std::vector<dof_id_type> libMesh::DofMap::_end_df [private] |
Last DOF index (plus 1) on processor p.
Definition at line 1027 of file dof_map.h.
Referenced by allgather_recursive_constraints(), clear(), distribute_dofs(), end_dof(), last_dof(), n_dofs_on_processor(), and scatter_constraints().
std::vector<dof_id_type> libMesh::DofMap::_end_old_df [private] |
Last old DOF index (plus 1) on processor p.
Definition at line 1119 of file dof_map.h.
Referenced by clear(), distribute_dofs(), and end_old_dof().
void* libMesh::DofMap::_extra_send_list_context [private] |
A pointer associcated with the extra send list that can optionally be passed in
Definition at line 1065 of file dof_map.h.
Referenced by attach_extra_send_list_function(), and 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
Referenced by attach_extra_send_list_function(), and prepare_send_list().
void* libMesh::DofMap::_extra_sparsity_context [private] |
A pointer associcated with the extra sparsity that can optionally be passed in
Definition at line 1050 of file dof_map.h.
Referenced by attach_extra_sparsity_function().
void(* libMesh::DofMap::_extra_sparsity_function)(SparsityPattern::Graph &, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *) [private] |
A function pointer to a function to call to add extra entries to the sparsity pattern
Referenced by attach_extra_sparsity_function().
std::vector<dof_id_type> libMesh::DofMap::_first_df [private] |
First DOF index on processor p.
Definition at line 1022 of file dof_map.h.
Referenced by clear(), distribute_dofs(), first_dof(), and n_dofs_on_processor().
std::vector<dof_id_type> libMesh::DofMap::_first_old_df [private] |
First old DOF index on processor p.
Definition at line 1114 of file dof_map.h.
Referenced by clear(), distribute_dofs(), and first_old_dof().
std::vector<SparseMatrix<Number>* > libMesh::DofMap::_matrices [private] |
Additional matrices handled by this object. These pointers do not handle the memory, instead, System, who told DofMap about them, owns them.
Definition at line 1017 of file dof_map.h.
Referenced by attach_matrix(), clear(), compute_sparsity(), DofMap(), get_info(), and is_attached().
Threads::spin_mutex libMesh::ReferenceCounter::_mutex [static, protected, inherited] |
Mutual exclusion object to enable thread-safe reference counting.
Definition at line 131 of file reference_counter.h.
dof_id_type libMesh::DofMap::_n_dfs [private] |
Total number of degrees of freedom.
Definition at line 1096 of file dof_map.h.
Referenced by clear(), distribute_dofs(), and n_dofs().
std::vector<dof_id_type>* libMesh::DofMap::_n_nz [private] |
The number of on-processor nonzeros in my portion of the global matrix. If need_full_sparsity_pattern is true, this will just be a pointer into the corresponding sparsity pattern vector. Otherwise we have to new/delete it ourselves.
Definition at line 1085 of file dof_map.h.
Referenced by attach_matrix(), clear_sparsity(), compute_sparsity(), get_info(), and get_n_nz().
Threads::atomic< unsigned int > libMesh::ReferenceCounter::_n_objects [static, protected, inherited] |
The number of objects. Print the reference count information when the number returns to 0.
Definition at line 126 of file reference_counter.h.
Referenced by libMesh::ReferenceCounter::n_objects(), libMesh::ReferenceCounter::ReferenceCounter(), and libMesh::ReferenceCounter::~ReferenceCounter().
dof_id_type libMesh::DofMap::_n_old_dfs [private] |
Total number of degrees of freedom on old dof objects
Definition at line 1109 of file dof_map.h.
Referenced by clear(), distribute_dofs(), and n_old_dofs().
std::vector<dof_id_type>* libMesh::DofMap::_n_oz [private] |
The number of off-processor nonzeros in my portion of the global matrix; allocated similar to _n_nz.
Definition at line 1091 of file dof_map.h.
Referenced by attach_matrix(), clear_sparsity(), compute_sparsity(), get_info(), and get_n_oz().
dof_id_type libMesh::DofMap::_n_SCALAR_dofs [private] |
The total number of SCALAR dofs associated to all SCALAR variables.
Definition at line 1102 of file dof_map.h.
Referenced by distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), n_SCALAR_dofs(), and reinit().
Data structure containing DofObject constraints.
Definition at line 1135 of file dof_map.h.
Referenced by allgather_recursive_constraints(), create_dof_constraints(), get_info(), get_local_constraints(), n_constrained_nodes(), node_constraint_rows_begin(), node_constraint_rows_end(), and scatter_constraints().
Data structure containing periodic boundaries. The ith entry is the constraint matrix row for boundaryid i.
Definition at line 1144 of file dof_map.h.
Referenced by add_periodic_boundary(), create_dof_constraints(), get_periodic_boundaries(), is_periodic_boundary(), and ~DofMap().
std::vector<dof_id_type> libMesh::DofMap::_send_list [private] |
A list containing all the global DOF indicies that affect the solution on my subdomain.
Definition at line 1033 of file dof_map.h.
Referenced by add_constraints_to_send_list(), add_neighbors_to_send_list(), all_semilocal_indices(), clear(), distribute_dofs(), get_send_list(), and prepare_send_list().
AutoPtr<SparsityPattern::Build> libMesh::DofMap::_sp [private] |
The sparsity pattern of the global matrix, kept around if it might be needed by future additions of the same type of matrix.
Definition at line 1077 of file dof_map.h.
Referenced by attach_matrix(), clear_sparsity(), and compute_sparsity().
const unsigned int libMesh::DofMap::_sys_number [private] |
The number of the system we manage DOFs for.
Definition at line 1010 of file dof_map.h.
Referenced by sys_number().
std::vector<VariableGroup> libMesh::DofMap::_variable_groups [private] |
The finite element type for each variable.
Definition at line 1005 of file dof_map.h.
Referenced by add_variable_group(), clear(), n_variable_groups(), variable_group(), variable_group_order(), and variable_group_type().
std::vector<Variable> libMesh::DofMap::_variables [private] |
The finite element type for each variable.
Definition at line 1000 of file dof_map.h.
Referenced by add_variable_group(), clear(), n_variables(), variable(), variable_order(), and variable_type().
bool libMesh::DofMap::need_full_sparsity_pattern [private] |
Default false; set to true if any attached matrix requires a full sparsity pattern.
Definition at line 1071 of file dof_map.h.
Referenced by attach_matrix(), clear(), clear_sparsity(), and compute_sparsity().
The documentation for this class was generated from the following files:
Site Created By: libMesh Developers
Last modified: February 05 2013 19:55:15 UTC
Hosted By: