DofMap Class Reference
#include <dof_map.h>

Public Member Functions | |
| DofMap (const unsigned int sys_number) | |
| ~DofMap () | |
| void | attach_matrix (SparseMatrix< Number > &matrix) |
| void | distribute_dofs (MeshBase &) |
| void | compute_sparsity (const MeshBase &) |
| void | prepare_send_list () |
| const std::vector< unsigned int > & | get_send_list () const |
| const std::vector< unsigned int > & | get_n_nz () const |
| const std::vector< unsigned int > & | get_n_oz () const |
| void | add_variable (const System::Variable &var) |
| const System::Variable & | variable (const unsigned int c) const |
| Order | variable_order (const unsigned int c) const |
| const FEType & | variable_type (const unsigned int c) const |
| unsigned int | n_variables () const |
| unsigned int | n_dofs () const |
| unsigned int | n_SCALAR_dofs () const |
| unsigned int | n_local_dofs () const |
| unsigned int | n_dofs_on_processor (const unsigned int proc) const |
| unsigned int | first_dof (const unsigned int proc=libMesh::processor_id()) const |
| unsigned int | last_dof (const unsigned int proc=libMesh::processor_id()) const |
| unsigned int | end_dof (const unsigned int proc=libMesh::processor_id()) const |
| unsigned int | variable_first_local_dof (const unsigned int var) const |
| unsigned int | variable_last_local_dof (const unsigned int var) const |
| void | dof_indices (const Elem *const elem, std::vector< unsigned int > &di, const unsigned int vn=libMesh::invalid_uint) const |
| void | SCALAR_dof_indices (std::vector< unsigned int > &di, const unsigned int vn, const bool old_dofs=false) const |
| bool | use_coupled_neighbor_dofs (const MeshBase &mesh) const |
| void | extract_local_vector (const NumericVector< Number > &Ug, const std::vector< unsigned int > &dof_indices, DenseVectorBase< Number > &Ue) const |
| unsigned int | n_constrained_dofs () const |
| void | create_dof_constraints (const MeshBase &mesh) |
| void | allgather_recursive_constraints () |
| void | process_constraints () |
| void | add_constraint_row (const unsigned int dof_number, const DofConstraintRow &constraint_row, const bool forbid_constraint_overwrite=true) |
| bool | is_constrained_dof (const unsigned int dof) const |
| void | print_dof_constraints (std::ostream &os=std::cout) 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< unsigned int > &elem_dofs, bool asymmetric_constraint_rows=true) const |
| void | constrain_element_matrix (DenseMatrix< Number > &matrix, std::vector< unsigned int > &row_dofs, std::vector< unsigned int > &col_dofs, bool asymmetric_constraint_rows=true) const |
| void | constrain_element_vector (DenseVector< Number > &rhs, std::vector< unsigned int > &dofs, bool asymmetric_constraint_rows=true) const |
| void | constrain_element_matrix_and_vector (DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< unsigned int > &elem_dofs, bool asymmetric_constraint_rows=true) const |
| void | constrain_element_dyad_matrix (DenseVector< Number > &v, DenseVector< Number > &w, std::vector< unsigned int > &row_dofs, bool asymmetric_constraint_rows=true) const |
| void | constrain_nothing (std::vector< unsigned int > &dofs) const |
| void | enforce_constraints_exactly (const System &system, NumericVector< Number > *v=NULL) const |
| void | add_periodic_boundary (const PeriodicBoundary &periodic_boundary) |
| bool | is_periodic_boundary (const unsigned int boundaryid) const |
| void | old_dof_indices (const Elem *const elem, std::vector< unsigned int > &di, const unsigned int vn=libMesh::invalid_uint) const |
| unsigned int | 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 () |
Static Public Member Functions | |
| static std::string | get_info () |
| static void | print_info () |
| static unsigned int | n_objects () |
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 |
Private Types | |
| typedef DofObject *(DofMap::* | dofobject_accessor )(MeshBase &mesh, unsigned int i) const |
Private Member Functions | |
| unsigned int | sys_number () const |
| void | invalidate_dofs (MeshBase &mesh) const |
| DofObject * | node_ptr (MeshBase &mesh, unsigned int i) const |
| DofObject * | elem_ptr (MeshBase &mesh, unsigned int 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 (unsigned int &next_free_dof, MeshBase &mesh) |
| void | distribute_local_dofs_node_major (unsigned int &next_free_dof, MeshBase &mesh) |
| void | add_neighbors_to_send_list (MeshBase &mesh) |
| void | build_constraint_matrix (DenseMatrix< Number > &C, std::vector< unsigned int > &elem_dofs, const bool called_recursively=false) const |
| void | find_connected_dofs (std::vector< unsigned int > &elem_dofs) const |
| void | add_constraints_to_send_list () |
Private Attributes | |
| std::vector< System::Variable > | _variables |
| const unsigned int | _sys_number |
| std::vector< SparseMatrix < Number > * > | _matrices |
| std::vector< unsigned int > | _first_df |
| std::vector< unsigned int > | _end_df |
| std::vector< unsigned int > | _var_first_local_df |
| std::vector< unsigned int > | _send_list |
| std::vector< unsigned int > | _n_nz |
| std::vector< unsigned int > | _n_oz |
| unsigned int | _n_dfs |
| unsigned int | _n_SCALAR_dofs |
| unsigned int | _n_old_dfs |
| DofConstraints | _dof_constraints |
| PeriodicBoundaries | _periodic_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 241 of file dof_map.h.
Member Typedef Documentation
typedef std::map<std::string, std::pair<unsigned int, unsigned int> > ReferenceCounter::Counts [protected, inherited] |
Data structure to log the information. The log is identified by the class name.
Definition at line 105 of file reference_counter.h.
typedef DofObject*(DofMap::* DofMap::dofobject_accessor)(MeshBase &mesh, unsigned int i) const [private] |
A member function type like node_ptr or elem_ptr
Constructor & Destructor Documentation
| DofMap::DofMap | ( | const unsigned int | sys_number | ) | [inline] |
Constructor. Requires the number of the system for which we will be numbering degrees of freedom.
Definition at line 878 of file dof_map.h.
References _matrices.
00878 : 00879 _dof_coupling(NULL), 00880 _sys_number(number), 00881 // _matrix(NULL), 00882 _n_dfs(0), 00883 _n_SCALAR_dofs(0) 00884 #ifdef LIBMESH_ENABLE_AMR 00885 , _n_old_dfs(0) 00886 #endif 00887 { 00888 _matrices.clear(); 00889 }
| DofMap::~DofMap | ( | ) |
Member Function Documentation
| void DofMap::add_constraint_row | ( | const unsigned int | dof_number, | |
| const DofConstraintRow & | constraint_row, | |||
| const bool | forbid_constraint_overwrite = true | |||
| ) |
Adds a copy of the user-defined row to the constraint matrix. By default, produces an error if the DOF was already constrained.
Definition at line 181 of file dof_map_constraints.C.
References _dof_constraints, and is_constrained_dof().
00184 { 00185 // Optionally allow the user to overwrite constraints. Defaults to false. 00186 if (forbid_constraint_overwrite) 00187 if (this->is_constrained_dof(dof_number)) 00188 { 00189 std::cerr << "ERROR: DOF " << dof_number << " was already constrained!" 00190 << std::endl; 00191 libmesh_error(); 00192 } 00193 00194 std::pair<unsigned int, DofConstraintRow> kv(dof_number, constraint_row); 00195 00196 _dof_constraints.insert(kv); 00197 }
| void 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 1192 of file dof_map_constraints.C.
References _dof_constraints, _send_list, end_dof(), first_dof(), std::max(), and libMesh::n_processors().
Referenced by process_constraints().
01193 { 01194 // This function must be run on all processors at once 01195 parallel_only(); 01196 01197 // Return immediately if there's nothing to gather 01198 if (libMesh::n_processors() == 1) 01199 return; 01200 01201 // We might get to return immediately if none of the processors 01202 // found any constraints 01203 unsigned int has_constraints = !_dof_constraints.empty(); 01204 Parallel::max(has_constraints); 01205 if (!has_constraints) 01206 return; 01207 01208 for (DofConstraints::iterator i = _dof_constraints.begin(); 01209 i != _dof_constraints.end(); ++i) 01210 { 01211 unsigned int constrained_dof = i->first; 01212 01213 // We only need the dependencies of our own constrained dofs 01214 if (constrained_dof < this->first_dof() || 01215 constrained_dof >= this->end_dof()) 01216 continue; 01217 01218 DofConstraintRow& constraint_row = i->second; 01219 for (DofConstraintRow::const_iterator 01220 j=constraint_row.begin(); j != constraint_row.end(); 01221 ++j) 01222 { 01223 unsigned int constraint_dependency = j->first; 01224 01225 // No point in adding one of our own dofs to the send_list 01226 if (constraint_dependency >= this->first_dof() && 01227 constraint_dependency < this->end_dof()) 01228 continue; 01229 01230 _send_list.push_back(constraint_dependency); 01231 } 01232 } 01233 }
| void 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 987 of file dof_map.C.
References _send_list, Elem::active(), MeshBase::active_elements_begin(), MeshBase::active_elements_end(), Elem::active_family_tree_by_neighbor(), MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), dof_indices(), end_dof(), first_dof(), MeshBase::max_node_id(), Elem::n_neighbors(), Elem::n_nodes(), Elem::neighbor(), Elem::node(), DofObject::processor_id(), and libMesh::processor_id().
Referenced by distribute_dofs().
00988 { 00989 START_LOG("add_neighbors_to_send_list()", "DofMap"); 00990 00991 //------------------------------------------------------------------------- 00992 // We need to add the DOFs from elements that live on neighboring processors 00993 // that are neighbors of the elements on the local processor 00994 //------------------------------------------------------------------------- 00995 00996 MeshBase::const_element_iterator local_elem_it 00997 = mesh.active_local_elements_begin(); 00998 const MeshBase::const_element_iterator local_elem_end 00999 = mesh.active_local_elements_end(); 01000 01001 std::vector<bool> node_on_processor(mesh.max_node_id(), false); 01002 std::vector<unsigned int> di; 01003 std::vector<const Elem *> family; 01004 01005 // Loop over the active local elements, adding all active elements 01006 // that neighbor an active local element to the send list. 01007 for ( ; local_elem_it != local_elem_end; ++local_elem_it) 01008 { 01009 const Elem* elem = *local_elem_it; 01010 01011 // Flag all the nodes of active local elements as seen 01012 for (unsigned int n=0; n!=elem->n_nodes(); n++) 01013 node_on_processor[elem->node(n)] = true; 01014 01015 // Loop over the neighbors of those elements 01016 for (unsigned int s=0; s<elem->n_neighbors(); s++) 01017 if (elem->neighbor(s) != NULL) 01018 { 01019 family.clear(); 01020 01021 // Find all the active elements that neighbor elem 01022 #ifdef LIBMESH_ENABLE_AMR 01023 if (!elem->neighbor(s)->active()) 01024 elem->neighbor(s)->active_family_tree_by_neighbor(family, elem); 01025 else 01026 #endif 01027 family.push_back(elem->neighbor(s)); 01028 01029 for (unsigned int i=0; i!=family.size(); ++i) 01030 // If the neighbor lives on a different processor 01031 if (family[i]->processor_id() != libMesh::processor_id()) 01032 { 01033 // Get the DOF indices for this neighboring element 01034 this->dof_indices (family[i], di); 01035 01036 // Insert the remote DOF indices into the send list 01037 for (unsigned int j=0; j != di.size(); ++j) 01038 if (di[j] < this->first_dof() || 01039 di[j] >= this->end_dof()) 01040 _send_list.push_back(di[j]); 01041 } 01042 } 01043 } 01044 01045 // Now loop over all non_local active elements and add any missing 01046 // nodal-only neighbors 01047 MeshBase::const_element_iterator elem_it 01048 = mesh.active_elements_begin(); 01049 const MeshBase::const_element_iterator elem_end 01050 = mesh.active_elements_end(); 01051 01052 for ( ; elem_it != elem_end; ++elem_it) 01053 { 01054 const Elem* elem = *elem_it; 01055 01056 // If this is one of our elements, we've already added it 01057 if (elem->processor_id() == libMesh::processor_id()) 01058 continue; 01059 01060 // Do we need to add the element DOFs? 01061 bool add_elem_dofs = false; 01062 01063 // Check all the nodes of the element to see if it 01064 // shares a node with us 01065 for (unsigned int n=0; n!=elem->n_nodes(); n++) 01066 if (node_on_processor[elem->node(n)]) 01067 add_elem_dofs = true; 01068 01069 // Add the element degrees of freedom if it shares at 01070 // least one node. 01071 if (add_elem_dofs) 01072 { 01073 // Get the DOF indices for this neighboring element 01074 this->dof_indices (elem, di); 01075 01076 // Insert the remote DOF indices into the send list 01077 for (unsigned int j=0; j != di.size(); ++j) 01078 if (di[j] < this->first_dof() || 01079 di[j] >= this->end_dof()) 01080 _send_list.push_back(di[j]); 01081 } 01082 } 01083 01084 STOP_LOG("add_neighbors_to_send_list()", "DofMap"); 01085 }
| void DofMap::add_periodic_boundary | ( | const PeriodicBoundary & | periodic_boundary | ) |
Adds a copy of the specified periodic boundary to the system.
Definition at line 1304 of file dof_map_constraints.C.
References _periodic_boundaries, PeriodicBoundary::myboundary, PeriodicBoundary::pairedboundary, and PeriodicBoundary::translation_vector.
01305 { 01306 PeriodicBoundary boundary = periodic_boundary; 01307 PeriodicBoundary inverse_boundary; 01308 inverse_boundary.myboundary = boundary.pairedboundary; 01309 inverse_boundary.pairedboundary = boundary.myboundary; 01310 inverse_boundary.translation_vector = -boundary.translation_vector; 01311 01312 std::pair<unsigned int, PeriodicBoundary> bp 01313 (boundary.myboundary, boundary); 01314 std::pair<unsigned int, PeriodicBoundary> ibp 01315 (boundary.pairedboundary, inverse_boundary); 01316 01317 _periodic_boundaries.insert(bp); 01318 _periodic_boundaries.insert(ibp); 01319 }
| void DofMap::add_variable | ( | const System::Variable & | var | ) |
Add an unknown of order order and finite element type type to the system of equations.
Definition at line 56 of file dof_map.C.
References _variables.
00057 { 00058 _variables.push_back (var); 00059 }
| void DofMap::allgather_recursive_constraints | ( | ) |
Gathers any relevant constraint equations from other processors
Definition at line 881 of file dof_map_constraints.C.
References _dof_constraints, _end_df, is_constrained_dof(), std::max(), libMesh::n_processors(), and libMesh::processor_id().
Referenced by create_dof_constraints().
00882 { 00883 // This function must be run on all processors at once 00884 parallel_only(); 00885 00886 // Return immediately if there's nothing to gather 00887 if (libMesh::n_processors() == 1) 00888 return; 00889 00890 // We might get to return immediately if none of the processors 00891 // found any constraints 00892 unsigned int has_constraints = !_dof_constraints.empty(); 00893 Parallel::max(has_constraints); 00894 if (!has_constraints) 00895 return; 00896 00897 // We might have calculated constraints for constrained dofs 00898 // which live on other processors. 00899 // Push these out first. 00900 { 00901 std::vector<std::vector<unsigned int> > pushed_ids(libMesh::n_processors()); 00902 std::vector<unsigned int> pushed_on_proc(libMesh::n_processors(), 0); 00903 00904 // Count the constraints to push to each processor 00905 unsigned int push_proc_id = 0; 00906 for (DofConstraints::iterator i = _dof_constraints.begin(); 00907 i != _dof_constraints.end(); ++i) 00908 { 00909 unsigned int constrained = i->first; 00910 while (constrained >= _end_df[push_proc_id]) 00911 push_proc_id++; 00912 pushed_on_proc[push_proc_id]++; 00913 } 00914 for (unsigned int p = 0; p != libMesh::n_processors(); ++p) 00915 pushed_ids[p].reserve(pushed_on_proc[p]); 00916 00917 // Collect the constraints to push to each processor 00918 push_proc_id = 0; 00919 for (DofConstraints::iterator i = _dof_constraints.begin(); 00920 i != _dof_constraints.end(); ++i) 00921 { 00922 unsigned int constrained = i->first; 00923 while (constrained >= _end_df[push_proc_id]) 00924 push_proc_id++; 00925 pushed_ids[push_proc_id].push_back(constrained); 00926 } 00927 00928 // Now trade constraint rows 00929 for (unsigned int p = 0; p != libMesh::n_processors(); ++p) 00930 { 00931 // Push to processor procup while receiving from procdown 00932 unsigned int procup = (libMesh::processor_id() + p) % 00933 libMesh::n_processors(); 00934 unsigned int procdown = (libMesh::n_processors() + 00935 libMesh::processor_id() - p) % 00936 libMesh::n_processors(); 00937 00938 // Pack the constraint rows to push to procup 00939 std::vector<std::vector<unsigned int> > pushed_keys(pushed_ids[procup].size()); 00940 std::vector<std::vector<Real> > pushed_vals(pushed_ids[procup].size()); 00941 for (unsigned int i = 0; i != pushed_ids[procup].size(); ++i) 00942 { 00943 DofConstraintRow &row = _dof_constraints[pushed_ids[procup][i]]; 00944 unsigned int row_size = row.size(); 00945 pushed_keys[i].reserve(row_size); 00946 pushed_vals[i].reserve(row_size); 00947 for (DofConstraintRow::iterator j = row.begin(); 00948 j != row.end(); ++j) 00949 { 00950 pushed_keys[i].push_back(j->first); 00951 pushed_vals[i].push_back(j->second); 00952 } 00953 } 00954 00955 // Trade pushed constraint rows 00956 std::vector<unsigned int> pushed_ids_to_me; 00957 std::vector<std::vector<unsigned int> > pushed_keys_to_me; 00958 std::vector<std::vector<Real> > pushed_vals_to_me; 00959 Parallel::send_receive(procup, pushed_ids[procup], 00960 procdown, pushed_ids_to_me); 00961 Parallel::send_receive(procup, pushed_keys, 00962 procdown, pushed_keys_to_me); 00963 Parallel::send_receive(procup, pushed_vals, 00964 procdown, pushed_vals_to_me); 00965 libmesh_assert (pushed_ids_to_me.size() == pushed_keys_to_me.size()); 00966 libmesh_assert (pushed_ids_to_me.size() == pushed_vals_to_me.size()); 00967 00968 // Add the constraints that I've been sent 00969 for (unsigned int i = 0; i != pushed_ids_to_me.size(); ++i) 00970 { 00971 libmesh_assert (pushed_keys_to_me[i].size() == pushed_vals_to_me[i].size()); 00972 00973 unsigned int constrained = pushed_ids_to_me[i]; 00974 00975 // If we don't already have a constraint for this dof, 00976 // add the one we were sent 00977 if (!this->is_constrained_dof(constrained)) 00978 { 00979 DofConstraintRow &row = _dof_constraints[constrained]; 00980 for (unsigned int j = 0; j != pushed_keys_to_me[i].size(); ++j) 00981 { 00982 row[pushed_keys_to_me[i][j]] = pushed_vals_to_me[i][j]; 00983 } 00984 } 00985 } 00986 } 00987 } 00988 00989 // Now start checking for any other constraints we need 00990 // to know about, requesting them recursively. 00991 00992 // Create a set containing the DOFs we already depend on 00993 typedef std::set<unsigned int> RCSet; 00994 RCSet unexpanded_set; 00995 00996 for (DofConstraints::iterator i = _dof_constraints.begin(); 00997 i != _dof_constraints.end(); ++i) 00998 { 00999 unexpanded_set.insert(i->first); 01000 } 01001 01002 // We have to keep recursing while the unexpanded set is 01003 // nonempty on *any* processor 01004 unsigned int unexpanded_set_nonempty = !unexpanded_set.empty(); 01005 Parallel::max(unexpanded_set_nonempty); 01006 01007 while (unexpanded_set_nonempty) 01008 { 01009 // Request set 01010 RCSet request_set; 01011 01012 // Request sets to send to each processor 01013 std::vector<std::vector<unsigned int> > 01014 requested_ids(libMesh::n_processors()); 01015 01016 // And the sizes of each 01017 std::vector<unsigned int> ids_on_proc(libMesh::n_processors(), 0); 01018 01019 // Fill (and thereby sort and uniq!) the main request set 01020 for (RCSet::iterator i = unexpanded_set.begin(); 01021 i != unexpanded_set.end(); ++i) 01022 { 01023 DofConstraintRow &row = _dof_constraints[*i]; 01024 for (DofConstraintRow::iterator j = row.begin(); 01025 j != row.end(); ++j) 01026 request_set.insert(j->first); 01027 } 01028 01029 // Clear the unexpanded constraint set; we're about to expand it 01030 unexpanded_set.clear(); 01031 01032 // Count requests by processor 01033 unsigned int proc_id = 0; 01034 for (RCSet::iterator i = request_set.begin(); 01035 i != request_set.end(); ++i) 01036 { 01037 while (*i >= _end_df[proc_id]) 01038 proc_id++; 01039 ids_on_proc[proc_id]++; 01040 } 01041 for (unsigned int p = 0; p != libMesh::n_processors(); ++p) 01042 requested_ids[p].reserve(ids_on_proc[p]); 01043 01044 // Prepare each processor's request set 01045 proc_id = 0; 01046 for (RCSet::iterator i = request_set.begin(); 01047 i != request_set.end(); ++i) 01048 { 01049 while (*i >= _end_df[proc_id]) 01050 proc_id++; 01051 requested_ids[proc_id].push_back(*i); 01052 } 01053 01054 // Now request constraint rows from other processors 01055 for (unsigned int p=1; p != libMesh::n_processors(); ++p) 01056 { 01057 // Trade my requests with processor procup and procdown 01058 unsigned int procup = (libMesh::processor_id() + p) % 01059 libMesh::n_processors(); 01060 unsigned int procdown = (libMesh::n_processors() + 01061 libMesh::processor_id() - p) % 01062 libMesh::n_processors(); 01063 std::vector<unsigned int> request_to_fill; 01064 Parallel::send_receive(procup, requested_ids[procup], 01065 procdown, request_to_fill); 01066 01067 // Fill those requests 01068 std::vector<std::vector<unsigned int> > row_keys(request_to_fill.size()); 01069 std::vector<std::vector<Real> > row_vals(request_to_fill.size()); 01070 for (unsigned int i=0; i != request_to_fill.size(); ++i) 01071 { 01072 unsigned int constrained = request_to_fill[i]; 01073 if (_dof_constraints.count(constrained)) 01074 { 01075 DofConstraintRow &row = _dof_constraints[constrained]; 01076 unsigned int row_size = row.size(); 01077 row_keys[i].reserve(row_size); 01078 row_vals[i].reserve(row_size); 01079 for (DofConstraintRow::iterator j = row.begin(); 01080 j != row.end(); ++j) 01081 { 01082 row_keys[i].push_back(j->first); 01083 row_vals[i].push_back(j->second); 01084 } 01085 } 01086 } 01087 01088 // Trade back the results 01089 std::vector<std::vector<unsigned int> > filled_keys; 01090 std::vector<std::vector<Real> > filled_vals; 01091 Parallel::send_receive(procdown, row_keys, 01092 procup, filled_keys); 01093 Parallel::send_receive(procdown, row_vals, 01094 procup, filled_vals); 01095 libmesh_assert (filled_keys.size() == requested_ids[procup].size()); 01096 libmesh_assert (filled_vals.size() == requested_ids[procup].size()); 01097 01098 // Add any new constraint rows we've found 01099 for (unsigned int i=0; i != requested_ids[procup].size(); ++i) 01100 { 01101 libmesh_assert (filled_keys[i].size() == filled_vals[i].size()); 01102 if (!filled_keys[i].empty()) 01103 { 01104 unsigned int constrained = requested_ids[procup][i]; 01105 DofConstraintRow &row = _dof_constraints[constrained]; 01106 for (unsigned int j = 0; j != filled_keys[i].size(); ++j) 01107 row[filled_keys[i][j]] = filled_vals[i][j]; 01108 01109 // And prepare to check for more recursive constraints 01110 unexpanded_set.insert(constrained); 01111 } 01112 } 01113 } 01114 01115 // We have to keep recursing while the unexpanded set is 01116 // nonempty on *any* processor 01117 unexpanded_set_nonempty = !unexpanded_set.empty(); 01118 Parallel::max(unexpanded_set_nonempty); 01119 } 01120 }
| void 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 90 of file dof_map.C.
References _matrices, and SparseMatrix< T >::attach_dof_map().
Referenced by EigenSystem::init_data(), and ImplicitSystem::init_matrices().
00091 { 00092 _matrices.push_back(&matrix); 00093 00094 matrix.attach_dof_map (*this); 00095 }
| void DofMap::build_constraint_matrix | ( | DenseMatrix< Number > & | C, | |
| std::vector< unsigned int > & | 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 761 of file dof_map_constraints.C.
References _dof_constraints, is_constrained_dof(), DenseMatrixBase< T >::m(), DenseMatrixBase< T >::n(), DenseMatrix< T >::resize(), and DenseMatrix< T >::right_multiply().
Referenced by constrain_element_dyad_matrix(), constrain_element_matrix(), constrain_element_matrix_and_vector(), constrain_element_vector(), constrain_nothing(), extract_local_vector(), and max_constraint_error().
00764 { 00765 if (!called_recursively) START_LOG("build_constraint_matrix()", "DofMap"); 00766 00767 // Create a set containing the DOFs we already depend on 00768 typedef std::set<unsigned int> RCSet; 00769 RCSet dof_set; 00770 00771 bool we_have_constraints = false; 00772 00773 // Next insert any other dofs the current dofs might be constrained 00774 // in terms of. Note that in this case we may not be done: Those 00775 // may in turn depend on others. So, we need to repeat this process 00776 // in that case until the system depends only on unconstrained 00777 // degrees of freedom. 00778 for (unsigned int i=0; i<elem_dofs.size(); i++) 00779 if (this->is_constrained_dof(elem_dofs[i])) 00780 { 00781 we_have_constraints = true; 00782 00783 // If the DOF is constrained 00784 DofConstraints::const_iterator 00785 pos = _dof_constraints.find(elem_dofs[i]); 00786 00787 libmesh_assert (pos != _dof_constraints.end()); 00788 00789 const DofConstraintRow& constraint_row = pos->second; 00790 00791 // Constraint rows in p refinement may be empty 00792 // libmesh_assert (!constraint_row.empty()); 00793 00794 for (DofConstraintRow::const_iterator 00795 it=constraint_row.begin(); it != constraint_row.end(); 00796 ++it) 00797 dof_set.insert (it->first); 00798 } 00799 00800 // May be safe to return at this point 00801 // (but remember to stop the perflog) 00802 if (!we_have_constraints) 00803 { 00804 STOP_LOG("build_constraint_matrix()", "DofMap"); 00805 return; 00806 } 00807 00808 // delay inserting elem_dofs for efficiency in the case of 00809 // no constraints. In that case we don't get here! 00810 dof_set.insert (elem_dofs.begin(), 00811 elem_dofs.end()); 00812 00813 // If we added any DOFS then we need to do this recursively. 00814 // It is possible that we just added a DOF that is also 00815 // constrained! 00816 // 00817 // Also, we need to handle the special case of an element having DOFs 00818 // constrained in terms of other, local DOFs 00819 if ((dof_set.size() != elem_dofs.size()) || // case 1: constrained in terms of other DOFs 00820 !called_recursively) // case 2: constrained in terms of our own DOFs 00821 { 00822 // Create a new list of element DOFs containing the 00823 // contents of the current dof_set. 00824 std::vector<unsigned int> new_elem_dofs (dof_set.begin(), 00825 dof_set.end()); 00826 00827 // Now we can build the constraint matrix. 00828 // Note that resize also zeros for a DenseMatrix<Number>. 00829 C.resize (elem_dofs.size(), new_elem_dofs.size()); 00830 00831 // Create the C constraint matrix. 00832 for (unsigned int i=0; i<elem_dofs.size(); i++) 00833 if (this->is_constrained_dof(elem_dofs[i])) 00834 { 00835 // If the DOF is constrained 00836 DofConstraints::const_iterator 00837 pos = _dof_constraints.find(elem_dofs[i]); 00838 00839 libmesh_assert (pos != _dof_constraints.end()); 00840 00841 const DofConstraintRow& constraint_row = pos->second; 00842 00843 // p refinement creates empty constraint rows 00844 // libmesh_assert (!constraint_row.empty()); 00845 00846 for (DofConstraintRow::const_iterator 00847 it=constraint_row.begin(); it != constraint_row.end(); 00848 ++it) 00849 for (unsigned int j=0; j<new_elem_dofs.size(); j++) 00850 if (new_elem_dofs[j] == it->first) 00851 C(i,j) = it->second; 00852 } 00853 else 00854 { 00855 for (unsigned int j=0; j<new_elem_dofs.size(); j++) 00856 if (new_elem_dofs[j] == elem_dofs[i]) 00857 C(i,j) = 1.; 00858 } 00859 00860 // May need to do this recursively. It is possible 00861 // that we just replaced a constrained DOF with another 00862 // constrained DOF. 00863 elem_dofs = new_elem_dofs; 00864 00865 DenseMatrix<Number> Cnew; 00866 00867 this->build_constraint_matrix (Cnew, elem_dofs, true); 00868 00869 if ((C.n() == Cnew.m()) && 00870 (Cnew.n() == elem_dofs.size())) // If the constraint matrix 00871 C.right_multiply(Cnew); // is constrained... 00872 00873 libmesh_assert (C.n() == elem_dofs.size()); 00874 } 00875 00876 if (!called_recursively) STOP_LOG("build_constraint_matrix()", "DofMap"); 00877 }
| void DofMap::clear | ( | ) |
Free all memory associated with the object, but keep the mesh pointer.
Definition at line 622 of file dof_map.C.
References _dof_constraints, _end_df, _first_df, _matrices, _n_dfs, _n_nz, _n_old_dfs, _n_oz, _send_list, _var_first_local_df, and _variables.
Referenced by ~DofMap().
00623 { 00624 // we don't want to clear 00625 // the coupling matrix! 00626 // It should not change... 00627 //_dof_coupling->clear(); 00628 00629 _variables.clear(); 00630 _first_df.clear(); 00631 _end_df.clear(); 00632 _var_first_local_df.clear(); 00633 _send_list.clear(); 00634 _n_nz.clear(); 00635 _n_oz.clear(); 00636 00637 00638 #ifdef LIBMESH_ENABLE_AMR 00639 00640 _dof_constraints.clear(); 00641 _n_old_dfs = 0; 00642 00643 #endif 00644 00645 _matrices.clear(); 00646 00647 _n_dfs = 0; 00648 }
| void DofMap::compute_sparsity | ( | const MeshBase & | mesh | ) |
Computes the sparsity pattern for the matrix corresponding to proc_id. Produces data that can be fed to Petsc for preallocation of sparse matrices.
Definition at line 1138 of file dof_map.C.
References _dof_coupling, _matrices, _n_nz, _n_oz, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), MeshBase::is_prepared(), n_dofs_on_processor(), SparsityPattern::Build::n_nz, SparsityPattern::Build::n_oz, n_variables(), Threads::parallel_reduce(), MeshBase::processor_id(), SparsityPattern::Build::sparsity_pattern, and use_coupled_neighbor_dofs().
Referenced by EigenSystem::init_data(), and ImplicitSystem::init_matrices().
01139 { 01140 libmesh_assert (mesh.is_prepared()); 01141 libmesh_assert (this->n_variables()); 01142 01143 START_LOG("compute_sparsity()", "DofMap"); 01144 01145 // Compute the sparsity structure of the global matrix. This can be 01146 // fed into a PetscMatrix to allocate exacly the number of nonzeros 01147 // necessary to store the matrix. This algorithm should be linear 01148 // in the (# of elements)*(# nodes per element) 01149 01150 // We can be more efficient in the threaded sparsity pattern assembly 01151 // if we don't need the exact pattern. For some sparse matrix formats 01152 // a good upper bound will suffice. 01153 bool need_full_sparsity_pattern=false; 01154 std::vector<SparseMatrix<Number>* >::iterator 01155 pos = _matrices.begin(), 01156 end = _matrices.end(); 01157 01158 for (; pos != end; ++pos) 01159 if ((*pos)->need_full_sparsity_pattern()) 01160 need_full_sparsity_pattern = true; 01161 01162 // See if we need to include sparsity pattern entries for coupling 01163 // between neighbor dofs 01164 bool implicit_neighbor_dofs = this->use_coupled_neighbor_dofs(mesh); 01165 01166 // We can compute the sparsity pattern in parallel on multiple 01167 // threads. The goal is for each thread to compute the full sparsity 01168 // pattern for a subset of elements. These sparsity patterns can 01169 // be efficiently merged in the SparsityPattern::Build::join() 01170 // method, especially if there is not too much overlap between them. 01171 // Even better, if the full sparsity pattern is not needed then 01172 // the number of nonzeros per row can be estimated from the 01173 // sparsity patterns created on each thread. 01174 SparsityPattern::Build sp (mesh, 01175 *this, 01176 _dof_coupling, 01177 implicit_neighbor_dofs, 01178 need_full_sparsity_pattern); 01179 01180 Threads::parallel_reduce (ConstElemRange (mesh.active_elements_begin(), 01181 mesh.active_elements_end()), sp); 01182 01183 #ifndef NDEBUG 01184 // Avoid declaring these variables unless asserts are enabled. 01185 const unsigned int proc_id = mesh.processor_id(); 01186 const unsigned int n_dofs_on_proc = this->n_dofs_on_processor(proc_id); 01187 #endif 01188 libmesh_assert (sp.sparsity_pattern.size() == n_dofs_on_proc); 01189 01190 // steal the n_nz and n_oz arrays from sp -- it won't need them any more, 01191 // and this is more efficient than copying them. 01192 _n_nz.swap(sp.n_nz); 01193 _n_oz.swap(sp.n_oz); 01194 01195 STOP_LOG("compute_sparsity()", "DofMap"); 01196 01197 // We are done with the sparsity_pattern. However, quite a 01198 // lot has gone into computing it. It is possible that some 01199 // \p SparseMatrix implementations want to see it. Let them 01200 // see it before we throw it away. 01201 pos = _matrices.begin(); 01202 end = _matrices.end(); 01203 01204 for (; pos != end; ++pos) 01205 (*pos)->update_sparsity_pattern (sp.sparsity_pattern); 01206 }
| void DofMap::constrain_element_dyad_matrix | ( | DenseVector< Number > & | v, | |
| DenseVector< Number > & | w, | |||
| std::vector< unsigned int > & | 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 520 of file dof_map_constraints.C.
References build_constraint_matrix(), is_constrained_dof(), DenseMatrixBase< T >::m(), DenseMatrixBase< T >::n(), n_constrained_dofs(), DenseVector< T >::resize(), DenseVector< T >::size(), and DenseMatrix< T >::transpose().
00524 { 00525 libmesh_assert (v.size() == row_dofs.size()); 00526 libmesh_assert (w.size() == row_dofs.size()); 00527 00528 // check for easy return 00529 if (this->n_constrained_dofs() == 0) 00530 return; 00531 00532 // The constrained RHS is built up as R^T F. 00533 DenseMatrix<Number> R; 00534 00535 this->build_constraint_matrix (R, row_dofs); 00536 00537 START_LOG("cnstrn_elem_dyad_mat()", "DofMap"); 00538 00539 // It is possible that the vector is not constrained at all. 00540 if ((R.m() == v.size()) && 00541 (R.n() == row_dofs.size())) // if the RHS is constrained 00542 { 00543 // Compute the matrix-vector products 00544 DenseVector<Number> old_v(v); 00545 DenseVector<Number> old_w(w); 00546 00547 // resize RHS & zero before summation 00548 v.resize(row_dofs.size()); 00549 w.resize(row_dofs.size()); 00550 00551 // compute matrix/vector product 00552 for (unsigned int i=0; i<row_dofs.size(); i++) 00553 for (unsigned int j=0; j<old_v.size(); j++) 00554 { 00555 v(i) += R.transpose(i,j)*old_v(j); 00556 w(i) += R.transpose(i,j)*old_w(j); 00557 } 00558 00559 libmesh_assert (row_dofs.size() == v.size()); 00560 libmesh_assert (row_dofs.size() == w.size()); 00561 00562 /* Constrain only v, not w. */ 00563 00564 for (unsigned int i=0; i<row_dofs.size(); i++) 00565 if (this->is_constrained_dof(row_dofs[i])) 00566 { 00567 // If the DOF is constrained 00568 v(i) = 0.; 00569 } 00570 } // end if the RHS is constrained. 00571 00572 STOP_LOG("cnstrn_elem_dyad_mat()", "DofMap"); 00573 }
| void DofMap::constrain_element_matrix | ( | DenseMatrix< Number > & | matrix, | |
| std::vector< unsigned int > & | row_dofs, | |||
| std::vector< unsigned int > & | 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 391 of file dof_map_constraints.C.
References _dof_constraints, build_constraint_matrix(), is_constrained_dof(), DenseMatrix< T >::left_multiply_transpose(), DenseMatrixBase< T >::m(), DenseMatrixBase< T >::n(), n_constrained_dofs(), and DenseMatrix< T >::right_multiply().
00395 { 00396 libmesh_assert (row_dofs.size() == matrix.m()); 00397 libmesh_assert (col_dofs.size() == matrix.n()); 00398 00399 // check for easy return 00400 if (this->n_constrained_dofs() == 0) 00401 return; 00402 00403 // The constrained matrix is built up as R^T K C. 00404 DenseMatrix<Number> R; 00405 DenseMatrix<Number> C; 00406 00407 // Safeguard against the user passing us the same 00408 // object for row_dofs and col_dofs. If that is done 00409 // the calls to build_matrix would fail 00410 std::vector<unsigned int> orig_row_dofs(row_dofs); 00411 std::vector<unsigned int> orig_col_dofs(col_dofs); 00412 00413 this->build_constraint_matrix (R, orig_row_dofs); 00414 this->build_constraint_matrix (C, orig_col_dofs); 00415 00416 START_LOG("constrain_elem_matrix()", "DofMap"); 00417 00418 row_dofs = orig_row_dofs; 00419 col_dofs = orig_col_dofs; 00420 00421 00422 // It is possible that the matrix is not constrained at all. 00423 if ((R.m() == matrix.m()) && 00424 (R.n() == row_dofs.size()) && 00425 (C.m() == matrix.n()) && 00426 (C.n() == col_dofs.size())) // If the matrix is constrained 00427 { 00428 // K_constrained = R^T K C 00429 matrix.left_multiply_transpose (R); 00430 matrix.right_multiply (C); 00431 00432 00433 libmesh_assert (matrix.m() == row_dofs.size()); 00434 libmesh_assert (matrix.n() == col_dofs.size()); 00435 00436 00437 for (unsigned int i=0; i<row_dofs.size(); i++) 00438 if (this->is_constrained_dof(row_dofs[i])) 00439 { 00440 for (unsigned int j=0; j<matrix.n(); j++) 00441 matrix(i,j) = 0.; 00442 00443 // If the DOF is constrained 00444 matrix(i,i) = 1.; 00445 00446 if (asymmetric_constraint_rows) 00447 { 00448 DofConstraints::const_iterator 00449 pos = _dof_constraints.find(row_dofs[i]); 00450 00451 libmesh_assert (pos != _dof_constraints.end()); 00452 00453 const DofConstraintRow& constraint_row = pos->second; 00454 00455 libmesh_assert (!constraint_row.empty()); 00456 00457 for (DofConstraintRow::const_iterator 00458 it=constraint_row.begin(); it != constraint_row.end(); 00459 ++it) 00460 for (unsigned int j=0; j<col_dofs.size(); j++) 00461 if (col_dofs[j] == it->first) 00462 matrix(i,j) = -it->second; 00463 } 00464 } 00465 } // end if is constrained... 00466 00467 STOP_LOG("constrain_elem_matrix()", "DofMap"); 00468 }
| void DofMap::constrain_element_matrix | ( | DenseMatrix< Number > & | matrix, | |
| std::vector< unsigned int > & | 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 226 of file dof_map_constraints.C.
References _dof_constraints, build_constraint_matrix(), is_constrained_dof(), DenseMatrix< T >::left_multiply_transpose(), DenseMatrixBase< T >::m(), DenseMatrixBase< T >::n(), n_constrained_dofs(), and DenseMatrix< T >::right_multiply().
Referenced by FEMSystem::assembly().
00229 { 00230 libmesh_assert (elem_dofs.size() == matrix.m()); 00231 libmesh_assert (elem_dofs.size() == matrix.n()); 00232 00233 // check for easy return 00234 if (this->n_constrained_dofs() == 0) 00235 return; 00236 00237 // The constrained matrix is built up as C^T K C. 00238 DenseMatrix<Number> C; 00239 00240 00241 this->build_constraint_matrix (C, elem_dofs); 00242 00243 START_LOG("constrain_elem_matrix()", "DofMap"); 00244 00245 // It is possible that the matrix is not constrained at all. 00246 if ((C.m() == matrix.m()) && 00247 (C.n() == elem_dofs.size())) // It the matrix is constrained 00248 { 00249 // Compute the matrix-matrix-matrix product C^T K C 00250 matrix.left_multiply_transpose (C); 00251 matrix.right_multiply (C); 00252 00253 00254 libmesh_assert (matrix.m() == matrix.n()); 00255 libmesh_assert (matrix.m() == elem_dofs.size()); 00256 libmesh_assert (matrix.n() == elem_dofs.size()); 00257 00258 00259 for (unsigned int i=0; i<elem_dofs.size(); i++) 00260 // If the DOF is constrained 00261 if (this->is_constrained_dof(elem_dofs[i])) 00262 { 00263 for (unsigned int j=0; j<matrix.n(); j++) 00264 matrix(i,j) = 0.; 00265 00266 matrix(i,i) = 1.; 00267 00268 if (asymmetric_constraint_rows) 00269 { 00270 DofConstraints::const_iterator 00271 pos = _dof_constraints.find(elem_dofs[i]); 00272 00273 libmesh_assert (pos != _dof_constraints.end()); 00274 00275 const DofConstraintRow& constraint_row = pos->second; 00276 00277 libmesh_assert (!constraint_row.empty()); 00278 00279 for (DofConstraintRow::const_iterator 00280 it=constraint_row.begin(); it != constraint_row.end(); 00281 ++it) 00282 for (unsigned int j=0; j<elem_dofs.size(); j++) 00283 if (elem_dofs[j] == it->first) 00284 matrix(i,j) = -it->second; 00285 } 00286 } 00287 } // end if is constrained... 00288 00289 STOP_LOG("constrain_elem_matrix()", "DofMap"); 00290 }
| void DofMap::constrain_element_matrix_and_vector | ( | DenseMatrix< Number > & | matrix, | |
| DenseVector< Number > & | rhs, | |||
| std::vector< unsigned int > & | 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 294 of file dof_map_constraints.C.
References _dof_constraints, build_constraint_matrix(), is_constrained_dof(), DenseMatrix< T >::left_multiply_transpose(), DenseMatrixBase< T >::m(), DenseMatrixBase< T >::n(), n_constrained_dofs(), DenseVector< T >::resize(), DenseMatrix< T >::right_multiply(), DenseVector< T >::size(), DenseMatrix< T >::transpose(), and DenseVector< T >::zero().
Referenced by FEMSystem::assembly().
00298 { 00299 libmesh_assert (elem_dofs.size() == matrix.m()); 00300 libmesh_assert (elem_dofs.size() == matrix.n()); 00301 libmesh_assert (elem_dofs.size() == rhs.size()); 00302 00303 // check for easy return 00304 if (this->n_constrained_dofs() == 0) 00305 return; 00306 00307 // The constrained matrix is built up as C^T K C. 00308 // The constrained RHS is built up as C^T F 00309 DenseMatrix<Number> C; 00310 00311 this->build_constraint_matrix (C, elem_dofs); 00312 00313 START_LOG("cnstrn_elem_mat_vec()", "DofMap"); 00314 00315 // It is possible that the matrix is not constrained at all. 00316 if ((C.m() == matrix.m()) && 00317 (C.n() == elem_dofs.size())) // It the matrix is constrained 00318 { 00319 // Compute the matrix-matrix-matrix product C^T K C 00320 matrix.left_multiply_transpose (C); 00321 matrix.right_multiply (C); 00322 00323 00324 libmesh_assert (matrix.m() == matrix.n()); 00325 libmesh_assert (matrix.m() == elem_dofs.size()); 00326 libmesh_assert (matrix.n() == elem_dofs.size()); 00327 00328 00329 for (unsigned int i=0; i<elem_dofs.size(); i++) 00330 if (this->is_constrained_dof(elem_dofs[i])) 00331 { 00332 for (unsigned int j=0; j<matrix.n(); j++) 00333 matrix(i,j) = 0.; 00334 00335 // If the DOF is constrained 00336 matrix(i,i) = 1.; 00337 00338 // This will put a nonsymmetric entry in the constraint 00339 // row to ensure that the linear system produces the 00340 // correct value for the constrained DOF. 00341 if (asymmetric_constraint_rows) 00342 { 00343 DofConstraints::const_iterator 00344 pos = _dof_constraints.find(elem_dofs[i]); 00345 00346 libmesh_assert (pos != _dof_constraints.end()); 00347 00348 const DofConstraintRow& constraint_row = pos->second; 00349 00350 // p refinement creates empty constraint rows 00351 // libmesh_assert (!constraint_row.empty()); 00352 00353 for (DofConstraintRow::const_iterator 00354 it=constraint_row.begin(); it != constraint_row.end(); 00355 ++it) 00356 for (unsigned int j=0; j<elem_dofs.size(); j++) 00357 if (elem_dofs[j] == it->first) 00358 matrix(i,j) = -it->second; 00359 } 00360 } 00361 00362 00363 // Compute the matrix-vector product C^T F 00364 DenseVector<Number> old_rhs(rhs); 00365 00366 // resize the RHS vector & 0 before summation 00367 rhs.resize(elem_dofs.size()); 00368 rhs.zero(); 00369 00370 // compute matrix/vector product 00371 for (unsigned int i=0; i<elem_dofs.size(); i++) 00372 for (unsigned int j=0; j<old_rhs.size(); j++) 00373 rhs(i) += C.transpose(i,j)*old_rhs(j); 00374 00375 00376 libmesh_assert (elem_dofs.size() == rhs.size()); 00377 00378 for (unsigned int i=0; i<elem_dofs.size(); i++) 00379 if (this->is_constrained_dof(elem_dofs[i])) 00380 { 00381 // If the DOF is constrained 00382 rhs(i) = 0.; 00383 } 00384 } // end if is constrained... 00385 00386 STOP_LOG("cnstrn_elem_mat_vec()", "DofMap"); 00387 }
| void DofMap::constrain_element_vector | ( | DenseVector< Number > & | rhs, | |
| std::vector< unsigned int > & | dofs, | |||
| bool | asymmetric_constraint_rows = true | |||
| ) | const [inline] |
Constrains the element vector.
Definition at line 472 of file dof_map_constraints.C.
References build_constraint_matrix(), is_constrained_dof(), DenseMatrixBase< T >::m(), DenseMatrixBase< T >::n(), n_constrained_dofs(), DenseVector< T >::resize(), DenseVector< T >::size(), DenseMatrix< T >::transpose(), and DenseVector< T >::zero().
Referenced by FEMSystem::assemble_qoi_derivative(), and FEMSystem::assembly().
00475 { 00476 libmesh_assert (rhs.size() == row_dofs.size()); 00477 00478 // check for easy return 00479 if (this->n_constrained_dofs() == 0) 00480 return; 00481 00482 // The constrained RHS is built up as R^T F. 00483 DenseMatrix<Number> R; 00484 00485 this->build_constraint_matrix (R, row_dofs); 00486 00487 START_LOG("constrain_elem_vector()", "DofMap"); 00488 00489 // It is possible that the vector is not constrained at all. 00490 if ((R.m() == rhs.size()) && 00491 (R.n() == row_dofs.size())) // if the RHS is constrained 00492 { 00493 // Compute the matrix-vector product 00494 DenseVector<Number> old_rhs(rhs); 00495 00496 // resize RHS & zero before summation 00497 rhs.resize(row_dofs.size()); 00498 rhs.zero(); 00499 00500 // compute matrix/vector product 00501 for (unsigned int i=0; i<row_dofs.size(); i++) 00502 for (unsigned int j=0; j<old_rhs.size(); j++) 00503 rhs(i) += R.transpose(i,j)*old_rhs(j); 00504 00505 libmesh_assert (row_dofs.size() == rhs.size()); 00506 00507 for (unsigned int i=0; i<row_dofs.size(); i++) 00508 if (this->is_constrained_dof(row_dofs[i])) 00509 { 00510 // If the DOF is constrained 00511 rhs(i) = 0.; 00512 } 00513 } // end if the RHS is constrained. 00514 00515 STOP_LOG("constrain_elem_vector()", "DofMap"); 00516 }
| void DofMap::constrain_nothing | ( | std::vector< unsigned int > & | 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 577 of file dof_map_constraints.C.
References build_constraint_matrix(), and n_constrained_dofs().
00578 { 00579 // check for easy return 00580 if (this->n_constrained_dofs() == 0) 00581 return; 00582 00583 // All the work is done by \p build_constraint_matrix. We just need 00584 // a dummy matrix. 00585 DenseMatrix<Number> R; 00586 this->build_constraint_matrix (R, dofs); 00587 }
| void 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 1242 of file dof_map_constraints.C.
References _dof_constraints, Elem::dim(), dim, DofObject::dof_number(), Elem::get_node(), Elem::is_node_on_side(), Elem::is_vertex(), DofObject::n_comp(), FEInterface::n_dofs_at_node(), Elem::n_nodes(), n_nodes, FEType::order, Elem::p_level(), Threads::spin_mtx, sys_number(), Elem::type(), type, and variable_type().
Referenced by FEBase::compute_periodic_constraints(), and FEBase::compute_proj_constraints().
01246 { 01247 // We're constraining dofs on elem which correspond to p refinement 01248 // levels above p - this only makes sense if elem's p refinement 01249 // level is above p. 01250 libmesh_assert(elem->p_level() > p); 01251 libmesh_assert(s < elem->n_sides()); 01252 01253 const unsigned int sys_num = this->sys_number(); 01254 const unsigned int dim = elem->dim(); 01255 ElemType type = elem->type(); 01256 FEType low_p_fe_type = this->variable_type(var); 01257 FEType high_p_fe_type = this->variable_type(var); 01258 low_p_fe_type.order = static_cast<Order>(low_p_fe_type.order + p); 01259 high_p_fe_type.order = static_cast<Order>(high_p_fe_type.order + 01260 elem->p_level()); 01261 01262 const unsigned int n_nodes = elem->n_nodes(); 01263 for (unsigned int n = 0; n != n_nodes; ++n) 01264 if (elem->is_node_on_side(n, s)) 01265 { 01266 const Node * const node = elem->get_node(n); 01267 const unsigned int low_nc = 01268 FEInterface::n_dofs_at_node (dim, low_p_fe_type, type, n); 01269 const unsigned int high_nc = 01270 FEInterface::n_dofs_at_node (dim, high_p_fe_type, type, n); 01271 01272 // since we may be running this method concurretly 01273 // on multiple threads we need to acquire a lock 01274 // before modifying the _dof_constraints object. 01275 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx); 01276 01277 if (elem->is_vertex(n)) 01278 { 01279 // Add "this is zero" constraint rows for high p vertex 01280 // dofs 01281 for (unsigned int i = low_nc; i != high_nc; ++i) 01282 _dof_constraints[node->dof_number(sys_num,var,i)].clear(); 01283 } 01284 else 01285 { 01286 const unsigned int total_dofs = node->n_comp(sys_num, var); 01287 libmesh_assert(total_dofs >= high_nc); 01288 // Add "this is zero" constraint rows for high p 01289 // non-vertex dofs, which are numbered in reverse 01290 for (unsigned int j = low_nc; j != high_nc; ++j) 01291 { 01292 const unsigned int i = total_dofs - j - 1; 01293 _dof_constraints[node->dof_number(sys_num,var,i)].clear(); 01294 } 01295 } 01296 } 01297 }
| void DofMap::create_dof_constraints | ( | const MeshBase & | mesh | ) |
Rebuilds the raw degree of freedom constraints.
Definition at line 112 of file dof_map_constraints.C.
References _dof_constraints, _periodic_boundaries, allgather_recursive_constraints(), dim, MeshBase::elements_begin(), MeshBase::elements_end(), MeshBase::is_prepared(), MeshBase::is_serial(), MeshBase::local_elements_begin(), MeshBase::local_elements_end(), MeshBase::mesh_dimension(), n_variables(), Threads::parallel_for(), and StoredRange< iterator_type, object_type >::reset().
Referenced by EquationSystems::reinit().
00113 { 00114 START_LOG("create_dof_constraints()", "DofMap"); 00115 00116 libmesh_assert (mesh.is_prepared()); 00117 00118 const unsigned int dim = mesh.mesh_dimension(); 00119 00120 // Constraints are not necessary in 1D 00121 if (dim == 1) 00122 { 00123 // make sure we stop logging though 00124 STOP_LOG("create_dof_constraints()", "DofMap"); 00125 return; 00126 } 00127 00128 // Here we build the hanging node constraints. This is done 00129 // by enforcing the condition u_a = u_b along hanging sides. 00130 // u_a = u_b is collocated at the nodes of side a, which gives 00131 // one row of the constraint matrix. 00132 00133 // clear any existing constraints. 00134 _dof_constraints.clear(); 00135 00136 // define the range of elements of interest 00137 ConstElemRange range; 00138 { 00139 // With SerialMesh or a serial ParallelMesh, every processor 00140 // computes every constraint 00141 MeshBase::const_element_iterator 00142 elem_begin = mesh.elements_begin(), 00143 elem_end = mesh.elements_end(); 00144 00145 // With a parallel ParallelMesh, processors compute only 00146 // their local constraints 00147 if (!mesh.is_serial()) 00148 { 00149 elem_begin = mesh.local_elements_begin(); 00150 elem_end = mesh.local_elements_end(); 00151 } 00152 00153 // set the range to contain the specified elements 00154 range.reset (elem_begin, elem_end); 00155 } 00156 00157 // Look at all the variables in the system. Reset the element 00158 // range at each iteration -- there is no need to reconstruct it. 00159 for (unsigned int variable_number=0; variable_number<this->n_variables(); 00160 ++variable_number, range.reset()) 00161 Threads::parallel_for (range, 00162 ComputeConstraints (_dof_constraints, 00163 *this, 00164 #ifdef LIBMESH_ENABLE_PERIODIC 00165 _periodic_boundaries, 00166 #endif 00167 mesh, 00168 variable_number)); 00169 00170 // With a parallelized Mesh, we've computed our local constraints, 00171 // but they may depend on non-local constraints that we'll need to 00172 // take into account. 00173 if (!mesh.is_serial()) 00174 this->allgather_recursive_constraints(); 00175 00176 STOP_LOG("create_dof_constraints()", "DofMap"); 00177 }
| void 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 652 of file dof_map.C.
References _end_df, _first_df, _n_dfs, _n_old_dfs, _send_list, add_neighbors_to_send_list(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), elem_ptr(), MeshBase::elements_begin(), MeshBase::elements_end(), invalidate_dofs(), MeshBase::is_prepared(), libMesh::n_processors(), node_ptr(), MeshBase::nodes_begin(), MeshBase::nodes_end(), libMesh::on_command_line(), libMesh::processor_id(), reinit(), and set_nonlocal_dof_objects().
Referenced by EquationSystems::reinit().
00653 { 00654 // This function must be run on all processors at once 00655 parallel_only(); 00656 00657 // Log how long it takes to distribute the degrees of freedom 00658 START_LOG("distribute_dofs()", "DofMap"); 00659 00660 libmesh_assert (mesh.is_prepared()); 00661 00662 const unsigned int proc_id = libMesh::processor_id(); 00663 const unsigned int n_proc = libMesh::n_processors(); 00664 00665 // libmesh_assert (this->n_variables() > 0); 00666 libmesh_assert (proc_id < n_proc); 00667 00668 // re-init in case the mesh has changed 00669 this->reinit(mesh); 00670 00671 // By default distribute variables in a 00672 // var-major fashion, but allow run-time 00673 // specification 00674 bool node_major_dofs = libMesh::on_command_line ("--node_major_dofs"); 00675 00676 // The DOF counter, will be incremented as we encounter 00677 // new degrees of freedom 00678 unsigned int next_free_dof = 0; 00679 00680 // Clear the send list before we rebuild it 00681 _send_list.clear(); 00682 00683 // Set temporary DOF indices on this processor 00684 if (node_major_dofs) 00685 this->distribute_local_dofs_node_major (next_free_dof, mesh); 00686 else 00687 this->distribute_local_dofs_var_major (next_free_dof, mesh); 00688 00689 // Get DOF counts on all processors 00690 std::vector<unsigned int> dofs_on_proc(n_proc, 0); 00691 Parallel::allgather(next_free_dof, dofs_on_proc); 00692 00693 // Resize the _first_df and _end_df arrays 00694 _first_df.resize(n_proc); 00695 _end_df.resize (n_proc); 00696 00697 // Get DOF offsets 00698 _first_df[0] = 0; 00699 for (unsigned int i=1; i < n_proc; ++i) 00700 _first_df[i] = _end_df[i-1] = _first_df[i-1] + dofs_on_proc[i-1]; 00701 _end_df[n_proc-1] = _first_df[n_proc-1] + dofs_on_proc[n_proc-1]; 00702 00703 // Clear all the current DOF indices 00704 // (distribute_dofs expects them cleared!) 00705 this->invalidate_dofs(mesh); 00706 00707 next_free_dof = _first_df[proc_id]; 00708 00709 // Set permanent DOF indices on this processor 00710 if (node_major_dofs) 00711 this->distribute_local_dofs_node_major (next_free_dof, mesh); 00712 else 00713 this->distribute_local_dofs_var_major (next_free_dof, mesh); 00714 00715 libmesh_assert(next_free_dof == _end_df[proc_id]); 00716 00717 //------------------------------------------------------------ 00718 // At this point, all n_comp and dof_number values on local 00719 // DofObjects should be correct, but a ParallelMesh might have 00720 // incorrect values on non-local DofObjects. Let's request the 00721 // correct values from each other processor. 00722 00723 if (libMesh::n_processors() > 1) 00724 { 00725 this->set_nonlocal_dof_objects(mesh.nodes_begin(), 00726 mesh.nodes_end(), 00727 mesh, &DofMap::node_ptr); 00728 00729 this->set_nonlocal_dof_objects(mesh.elements_begin(), 00730 mesh.elements_end(), 00731 mesh, &DofMap::elem_ptr); 00732 } 00733 00734 // Set the total number of degrees of freedom 00735 #ifdef LIBMESH_ENABLE_AMR 00736 _n_old_dfs = _n_dfs; 00737 #endif 00738 _n_dfs = _end_df[n_proc-1]; 00739 00740 STOP_LOG("distribute_dofs()", "DofMap"); 00741 00742 // Note that in the add_neighbors_to_send_list nodes on processor 00743 // boundaries that are shared by multiple elements are added for 00744 // each element. 00745 this->add_neighbors_to_send_list(mesh); 00746 00747 // Here we used to clean up that data structure; now System and 00748 // EquationSystems call that for us, after we've added constraint 00749 // dependencies to the send_list too. 00750 // this->sort_send_list (); 00751 }
| void DofMap::distribute_local_dofs_node_major | ( | unsigned int & | 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 754 of file dof_map.C.
References _n_SCALAR_dofs, _var_first_local_df, MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), DofObject::dof_number(), first_dof(), Elem::get_node(), DofObject::invalid_id, MeshTools::libmesh_assert_valid_node_procids(), MeshBase::local_nodes_begin(), MeshBase::local_nodes_end(), DofObject::n_comp(), Elem::n_nodes(), n_nodes, libMesh::n_processors(), n_variables(), DofObject::n_vars(), n_vars, FEType::order, libMesh::processor_id(), DofObject::processor_id(), libMeshEnums::SCALAR, DofObject::set_dof_number(), Elem::subdomain_id(), sys_number(), System::Variable::type(), type, and variable().
Referenced by distribute_dofs().
00756 { 00757 const unsigned int sys_num = this->sys_number(); 00758 const unsigned int n_vars = this->n_variables(); 00759 00760 // We now only add remote dofs to the _send_list 00761 // unsigned int send_list_size = 0; 00762 00763 // _var_first_local_df does not work with node_major dofs 00764 _var_first_local_df.resize(n_vars+1); 00765 std::fill (_var_first_local_df.begin(), 00766 _var_first_local_df.end(), 00767 DofObject::invalid_id); 00768 00769 //------------------------------------------------------------------------- 00770 // First count and assign temporary numbers to local dofs 00771 MeshBase::element_iterator elem_it = mesh.active_local_elements_begin(); 00772 const MeshBase::element_iterator elem_end = mesh.active_local_elements_end(); 00773 00774 for ( ; elem_it != elem_end; ++elem_it) 00775 { 00776 // Only number dofs connected to active 00777 // elements on this processor. 00778 Elem* elem = *elem_it; 00779 const unsigned int n_nodes = elem->n_nodes(); 00780 00781 // First number the nodal DOFS 00782 for (unsigned int n=0; n<n_nodes; n++) 00783 { 00784 Node* node = elem->get_node(n); 00785 00786 for (unsigned var=0; var<n_vars; var++) 00787 { 00788 if( (this->variable(var).type().family != SCALAR) && 00789 (this->variable(var).active_on_subdomain(elem->subdomain_id())) ) 00790 { 00791 // assign dof numbers (all at once) if this is 00792 // our node and if they aren't already there 00793 if ((node->n_comp(sys_num,var) > 0) && 00794 (node->processor_id() == libMesh::processor_id()) && 00795 (node->dof_number(sys_num,var,0) == 00796 DofObject::invalid_id)) 00797 { 00798 node->set_dof_number(sys_num, 00799 var, 00800 0, 00801 next_free_dof); 00802 next_free_dof += node->n_comp(sys_num,var); 00803 } 00804 } 00805 } 00806 } 00807 00808 // Now number the element DOFS 00809 for (unsigned var=0; var<n_vars; var++) 00810 if ( (this->variable(var).type().family != SCALAR) && 00811 (this->variable(var).active_on_subdomain(elem->subdomain_id())) ) 00812 if (elem->n_comp(sys_num,var) > 0) 00813 { 00814 libmesh_assert (elem->dof_number(sys_num,var,0) == 00815 DofObject::invalid_id); 00816 00817 elem->set_dof_number(sys_num, 00818 var, 00819 0, 00820 next_free_dof); 00821 00822 next_free_dof += elem->n_comp(sys_num,var); 00823 } 00824 } // done looping over elements 00825 00826 // Finally, count up the SCALAR dofs 00827 this->_n_SCALAR_dofs = 0; 00828 for (unsigned var=0; var<n_vars; var++) 00829 { 00830 if( this->variable(var).type().family == SCALAR ) 00831 { 00832 this->_n_SCALAR_dofs += this->variable(var).type().order; 00833 continue; 00834 } 00835 } 00836 00837 // Only increment next_free_dof if we're on the processor 00838 // that holds this SCALAR variable 00839 if ( libMesh::processor_id() == (libMesh::n_processors()-1) ) 00840 next_free_dof += _n_SCALAR_dofs; 00841 00842 #ifdef DEBUG 00843 // Make sure we didn't miss any nodes 00844 MeshTools::libmesh_assert_valid_node_procids(mesh); 00845 00846 MeshBase::node_iterator node_it = mesh.local_nodes_begin(); 00847 const MeshBase::node_iterator node_end = mesh.local_nodes_end(); 00848 for (; node_it != node_end; ++node_it) 00849 { 00850 Node *obj = *node_it; 00851 libmesh_assert(obj); 00852 unsigned int n_variables = obj->n_vars(this->sys_number()); 00853 for (unsigned int v=0; v != n_variables; ++v) 00854 { 00855 unsigned int n_comp = 00856 obj->n_comp(this->sys_number(), v); 00857 unsigned int first_dof = n_comp ? 00858 obj->dof_number(this->sys_number(), v, 0) : 0; 00859 libmesh_assert(first_dof != DofObject::invalid_id); 00860 } 00861 } 00862 #endif // DEBUG 00863 }
| void DofMap::distribute_local_dofs_var_major | ( | unsigned int & | 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 867 of file dof_map.C.
References _n_SCALAR_dofs, _var_first_local_df, MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), System::Variable::active_on_subdomain(), DofObject::dof_number(), FEType::family, first_dof(), Elem::get_node(), DofObject::invalid_id, MeshTools::libmesh_assert_valid_node_procids(), MeshBase::local_nodes_begin(), MeshBase::local_nodes_end(), DofObject::n_comp(), Elem::n_nodes(), n_nodes, libMesh::n_processors(), n_variables(), DofObject::n_vars(), n_vars, FEType::order, libMesh::processor_id(), DofObject::processor_id(), libMeshEnums::SCALAR, DofObject::set_dof_number(), Elem::subdomain_id(), sys_number(), type, System::Variable::type(), and variable().
Referenced by distribute_dofs().
00869 { 00870 const unsigned int sys_num = this->sys_number(); 00871 const unsigned int n_vars = this->n_variables(); 00872 00873 // We now only add remote dofs to the _send_list 00874 // unsigned int send_list_size = 0; 00875 00876 // We will cache the first local index for each variable 00877 _var_first_local_df.clear(); 00878 00879 //------------------------------------------------------------------------- 00880 // First count and assign temporary numbers to local dofs 00881 for (unsigned var=0; var<n_vars; var++) 00882 { 00883 _var_first_local_df.push_back(next_free_dof); 00884 00885 const System::Variable var_description = this->variable(var); 00886 00887 // Skip the SCALAR dofs 00888 if(var_description.type().family == SCALAR) 00889 continue; 00890 00891 MeshBase::element_iterator elem_it = mesh.active_local_elements_begin(); 00892 const MeshBase::element_iterator elem_end = mesh.active_local_elements_end(); 00893 00894 for ( ; elem_it != elem_end; ++elem_it) 00895 { 00896 // Only number dofs connected to active 00897 // elements on this processor. 00898 Elem* elem = *elem_it; 00899 00900 // ... and only variables which are active on 00901 // on this element's subdomain 00902 if (!var_description.active_on_subdomain(elem->subdomain_id())) 00903 continue; 00904 00905 const unsigned int n_nodes = elem->n_nodes(); 00906 00907 // First number the nodal DOFS 00908 for (unsigned int n=0; n<n_nodes; n++) 00909 { 00910 Node* node = elem->get_node(n); 00911 00912 // assign dof numbers (all at once) if this is 00913 // our node and if they aren't already there 00914 if ((node->n_comp(sys_num,var) > 0) && 00915 (node->processor_id() == libMesh::processor_id()) && 00916 (node->dof_number(sys_num,var,0) == 00917 DofObject::invalid_id)) 00918 { 00919 node->set_dof_number(sys_num, 00920 var, 00921 0, 00922 next_free_dof); 00923 next_free_dof += node->n_comp(sys_num,var); 00924 } 00925 } 00926 00927 // Now number the element DOFS 00928 if (elem->n_comp(sys_num,var) > 0) 00929 { 00930 libmesh_assert (elem->dof_number(sys_num,var,0) == 00931 DofObject::invalid_id); 00932 00933 elem->set_dof_number(sys_num, 00934 var, 00935 0, 00936 next_free_dof); 00937 00938 next_free_dof += elem->n_comp(sys_num,var); 00939 } 00940 } // end loop on elements 00941 } // end loop on variables 00942 00943 // Finally, count up the SCALAR dofs 00944 this->_n_SCALAR_dofs = 0; 00945 for (unsigned var=0; var<n_vars; var++) 00946 { 00947 if( this->variable(var).type().family == SCALAR ) 00948 { 00949 this->_n_SCALAR_dofs += this->variable(var).type().order; 00950 continue; 00951 } 00952 } 00953 00954 // Only increment next_free_dof if we're on the processor 00955 // that holds this SCALAR variable 00956 if ( libMesh::processor_id() == (libMesh::n_processors()-1) ) 00957 next_free_dof += _n_SCALAR_dofs; 00958 00959 // Cache the last local dof number too 00960 _var_first_local_df.push_back(next_free_dof); 00961 00962 #ifdef DEBUG 00963 // Make sure we didn't miss any nodes 00964 MeshTools::libmesh_assert_valid_node_procids(mesh); 00965 00966 MeshBase::node_iterator node_it = mesh.local_nodes_begin(); 00967 const MeshBase::node_iterator node_end = mesh.local_nodes_end(); 00968 for (; node_it != node_end; ++node_it) 00969 { 00970 Node *obj = *node_it; 00971 libmesh_assert(obj); 00972 unsigned int n_variables = obj->n_vars(this->sys_number()); 00973 for (unsigned int v=0; v != n_variables; ++v) 00974 { 00975 unsigned int n_comp = 00976 obj->n_comp(this->sys_number(), v); 00977 unsigned int first_dof = n_comp ? 00978 obj->dof_number(this->sys_number(), v, 0) : 0; 00979 libmesh_assert(first_dof != DofObject::invalid_id); 00980 } 00981 } 00982 #endif // DEBUG 00983 }
| void DofMap::dof_indices | ( | const Elem *const | elem, | |
| std::vector< unsigned int > & | 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 1280 of file dof_map.C.
References Elem::active(), Elem::dim(), dim, DofObject::dof_number(), FEInterface::extra_hanging_dofs(), FEType::family, Elem::get_node(), DofObject::invalid_id, libMesh::invalid_uint, Elem::is_vertex(), libMeshEnums::LAGRANGE, DofObject::n_comp(), n_dofs(), FEInterface::n_dofs_at_node(), FEInterface::n_dofs_per_elem(), Elem::n_nodes(), n_nodes, DofObject::n_systems(), n_variables(), n_vars, FEType::order, Elem::p_level(), libMeshEnums::SCALAR, SCALAR_dof_indices(), Elem::subdomain_id(), sys_number(), Elem::type(), type, variable(), and variable_type().
Referenced by ExactSolution::_compute_error(), add_neighbors_to_send_list(), HPCoarsenTest::add_projection(), EquationSystems::build_discontinuous_solution_vector(), EquationSystems::build_solution_vector(), System::calculate_norm(), FEBase::coarsened_dof_values(), FEBase::compute_periodic_constraints(), FEBase::compute_proj_constraints(), JumpErrorEstimator::estimate_error(), ExactErrorEstimator::estimate_error(), MeshFunction::gradient(), MeshFunction::hessian(), System::local_dof_indices(), max_constraint_error(), FEMSystem::mesh_position_get(), System::ProjectVector::operator()(), PatchRecoveryErrorEstimator::EstimateError::operator()(), MeshFunction::operator()(), SparsityPattern::Build::operator()(), ErrorVector::plot_error(), FEMContext::reinit(), HPCoarsenTest::select_refinement(), EnsightIO::write_scalar_ascii(), and EnsightIO::write_vector_ascii().
01283 { 01284 START_LOG("dof_indices()", "DofMap"); 01285 01286 libmesh_assert (elem != NULL); 01287 01288 const unsigned int n_nodes = elem->n_nodes(); 01289 const ElemType type = elem->type(); 01290 const unsigned int sys_num = this->sys_number(); 01291 const unsigned int n_vars = this->n_variables(); 01292 const unsigned int dim = elem->dim(); 01293 01294 // Clear the DOF indices vector 01295 di.clear(); 01296 01297 #ifdef DEBUG 01298 // Check that sizes match in DEBUG mode 01299 unsigned int tot_size = 0; 01300 #endif 01301 01302 // Create a vector to indicate which 01303 // SCALAR variables have been requested 01304 std::vector<unsigned int> SCALAR_var_numbers; 01305 SCALAR_var_numbers.clear(); 01306 01307 // Get the dof numbers 01308 for (unsigned int v=0; v<n_vars; v++) 01309 if ((v == vn) || (vn == libMesh::invalid_uint)) 01310 { 01311 if(this->variable(v).type().family == SCALAR) 01312 { 01313 // We asked for this variable, so add it to the vector. 01314 SCALAR_var_numbers.push_back(v); 01315 01316 #ifdef DEBUG 01317 FEType fe_type = this->variable_type(v); 01318 tot_size += FEInterface::n_dofs(dim, 01319 fe_type, 01320 type); 01321 #endif 01322 } 01323 else 01324 if (this->variable(v).active_on_subdomain(elem->subdomain_id())) 01325 { // Do this for all the variables if one was not specified 01326 // or just for the specified variable 01327 01328 // Increase the polynomial order on p refined elements 01329 FEType fe_type = this->variable_type(v); 01330 fe_type.order = static_cast<Order>(fe_type.order + 01331 elem->p_level()); 01332 01333 const bool extra_hanging_dofs = 01334 FEInterface::extra_hanging_dofs(fe_type); 01335 01336 #ifdef DEBUG 01337 tot_size += FEInterface::n_dofs(dim, 01338 fe_type, 01339 type); 01340 #endif 01341 01342 // Get the node-based DOF numbers 01343 for (unsigned int n=0; n<n_nodes; n++) 01344 { 01345 const Node* node = elem->get_node(n); 01346 01347 // There is a potential problem with h refinement. Imagine a 01348 // quad9 that has a linear FE on it. Then, on the hanging side, 01349 // it can falsely identify a DOF at the mid-edge node. This is why 01350 // we call FEInterface instead of node->n_comp() directly. 01351 const unsigned int nc = FEInterface::n_dofs_at_node (dim, 01352 fe_type, 01353 type, 01354 n); 01355 01356 // If this is a non-vertex on a hanging node with extra 01357 // degrees of freedom, we use the non-vertex dofs (which 01358 // come in reverse order starting from the end, to 01359 // simplify p refinement) 01360 if (extra_hanging_dofs && !elem->is_vertex(n)) 01361 { 01362 const int dof_offset = node->n_comp(sys_num,v) - nc; 01363 01364 // We should never have fewer dofs than necessary on a 01365 // node unless we're getting indices on a parent element, 01366 // and we should never need the indices on such a node 01367 if (dof_offset < 0) 01368 { 01369 libmesh_assert(!elem->active()); 01370 di.resize(di.size() + nc, DofObject::invalid_id); 01371 } 01372 else 01373 for (int i=node->n_comp(sys_num,v)-1; i>=dof_offset; i--) 01374 { 01375 libmesh_assert (node->dof_number(sys_num,v,i) != 01376 DofObject::invalid_id); 01377 di.push_back(node->dof_number(sys_num,v,i)); 01378 } 01379 } 01380 // If this is a vertex or an element without extra hanging 01381 // dofs, our dofs come in forward order coming from the 01382 // beginning 01383 else 01384 for (unsigned int i=0; i<nc; i++) 01385 { 01386 libmesh_assert (node->dof_number(sys_num,v,i) != 01387 DofObject::invalid_id); 01388 di.push_back(node->dof_number(sys_num,v,i)); 01389 } 01390 } 01391 01392 // If there are any element-based DOF numbers, get them 01393 const unsigned int nc = FEInterface::n_dofs_per_elem(dim, 01394 fe_type, 01395 type); 01396 // We should never have fewer dofs than necessary on an 01397 // element unless we're getting indices on a parent element, 01398 // and we should never need those indices 01399 if (nc != 0) 01400 { 01401 if (elem->n_systems() > sys_num && 01402 nc <= elem->n_comp(sys_num,v)) 01403 { 01404 for (unsigned int i=0; i<nc; i++) 01405 { 01406 libmesh_assert (elem->dof_number(sys_num,v,i) != 01407 DofObject::invalid_id); 01408 01409 di.push_back(elem->dof_number(sys_num,v,i)); 01410 } 01411 } 01412 else 01413 { 01414 libmesh_assert(!elem->active() || fe_type.family == LAGRANGE); 01415 di.resize(di.size() + nc, DofObject::invalid_id); 01416 } 01417 } 01418 } 01419 } // end loop over variables 01420 01421 // Finally append any SCALAR dofs that we asked for. 01422 std::vector<unsigned int> di_new; 01423 std::vector<unsigned int>::iterator it = SCALAR_var_numbers.begin(); 01424 std::vector<unsigned int>::const_iterator it_end = SCALAR_var_numbers.end(); 01425 for( ; it != it_end; ++it) 01426 { 01427 this->SCALAR_dof_indices(di_new,*it); 01428 di.insert( di.end(), di_new.begin(), di_new.end()); 01429 } 01430 01431 #ifdef DEBUG 01432 libmesh_assert (tot_size == di.size()); 01433 #endif 01434 01435 STOP_LOG("dof_indices()", "DofMap"); 01436 }
An adapter function that returns Elem pointers by index
Definition at line 106 of file dof_map.C.
References MeshBase::elem().
Referenced by distribute_dofs().
00107 { 00108 return mesh.elem(i); 00109 }
| unsigned int DofMap::end_dof | ( | const unsigned int | 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 378 of file dof_map.h.
References _end_df.
Referenced by add_constraints_to_send_list(), add_neighbors_to_send_list(), enforce_constraints_exactly(), SparsityPattern::Build::join(), System::local_dof_indices(), SparsityPattern::Build::operator()(), and SparseMatrix< T >::print().
| void DofMap::enforce_constraints_exactly | ( | const System & | system, | |
| NumericVector< Number > * | v = NULL | |||
| ) | 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
Definition at line 591 of file dof_map_constraints.C.
References _dof_constraints, NumericVector< T >::close(), NumericVector< T >::closed(), end_dof(), first_dof(), AutoPtr< Tp >::get(), System::get_dof_map(), libMeshEnums::GHOSTED, NumericVector< T >::localize(), std::max(), n_constrained_dofs(), n_dofs(), n_local_dofs(), libMeshEnums::PARALLEL, libMeshEnums::SERIAL, NumericVector< T >::set(), NumericVector< T >::size(), System::solution, and NumericVector< T >::type().
Referenced by __libmesh_petsc_diff_solver_jacobian(), __libmesh_petsc_diff_solver_residual(), ImplicitSystem::adjoint_solve(), System::project_vector(), ImplicitSystem::sensitivity_solve(), PetscDiffSolver::solve(), NewtonSolver::solve(), ImplicitSystem::weighted_sensitivity_adjoint_solve(), and ImplicitSystem::weighted_sensitivity_solve().
00593 { 00594 parallel_only(); 00595 00596 unsigned int local_constraints = this->n_constrained_dofs(); 00597 Parallel::max(local_constraints); 00598 if (!local_constraints) 00599 return; 00600 00601 START_LOG("enforce_constraints_exactly()","DofMap"); 00602 00603 if (!v) 00604 v = system.solution.get(); 00605 00606 NumericVector<Number> *v_local = NULL; // will be initialized below 00607 NumericVector<Number> *v_global = NULL; // will be initialized below 00608 AutoPtr<NumericVector<Number> > v_built; 00609 if (v->type() == SERIAL) 00610 { 00611 v_built = NumericVector<Number>::build(); 00612 v_built->init(this->n_dofs(), this->n_local_dofs(), true, PARALLEL); 00613 v_built->close(); 00614 00615 for (unsigned int i=v_built->first_local_index(); 00616 i<v_built->last_local_index(); i++) 00617 v_built->set(i, (*v)(i)); 00618 v_built->close(); 00619 v_global = v_built.get(); 00620 00621 v_local = v; 00622 libmesh_assert (v_local->closed()); 00623 } 00624 else if (v->type() == PARALLEL) 00625 { 00626 v_built = NumericVector<Number>::build(); 00627 v_built->init (v->size(), v->size(), true, SERIAL); 00628 v->localize(*v_built); 00629 v_built->close(); 00630 v_local = v_built.get(); 00631 00632 v_global = v; 00633 } 00634 else if (v->type() == GHOSTED) 00635 { 00636 v_local = v; 00637 v_global = v; 00638 } 00639 else // unknown v->type() 00640 { 00641 std::cerr << "ERROR: Unknown v->type() == " << v->type() 00642 << std::endl; 00643 libmesh_error(); 00644 } 00645 00646 // We should never hit these asserts because we should error-out in 00647 // else clause above. Just to be sure we don't try to use v_local 00648 // and v_global uninitialized... 00649 libmesh_assert(v_local); 00650 libmesh_assert(v_global); 00651 libmesh_assert (this == &(system.get_dof_map())); 00652 00653 DofConstraints::const_iterator c_it = _dof_constraints.begin(); 00654 const DofConstraints::const_iterator c_end = _dof_constraints.end(); 00655 00656 for ( ; c_it != c_end; ++c_it) 00657 { 00658 unsigned int constrained_dof = c_it->first; 00659 if (constrained_dof < this->first_dof() || 00660 constrained_dof >= this->end_dof()) 00661 continue; 00662 00663 const DofConstraintRow constraint_row = c_it->second; 00664 00665 Number exact_value = 0; 00666 for (DofConstraintRow::const_iterator 00667 j=constraint_row.begin(); j != constraint_row.end(); 00668 ++j) 00669 exact_value += j->second * (*v_local)(j->first); 00670 00671 v_global->set(constrained_dof, exact_value); 00672 } 00673 00674 // If the old vector was serial, we probably need to send our values 00675 // to other processors 00676 if (v->type() == SERIAL) 00677 { 00678 v_global->localize (*v); 00679 } 00680 v->close(); 00681 00682 STOP_LOG("enforce_constraints_exactly()","DofMap"); 00683 }
| void DofMap::extract_local_vector | ( | const NumericVector< Number > & | Ug, | |
| const std::vector< unsigned int > & | 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_0.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 1210 of file dof_map.C.
References build_constraint_matrix(), DenseVectorBase< T >::el(), NumericVector< T >::first_local_index(), is_constrained_dof(), NumericVector< T >::last_local_index(), DenseMatrixBase< T >::m(), DenseMatrixBase< T >::n(), DenseVectorBase< T >::size(), and DenseVectorBase< T >::zero().
01213 { 01214 #ifdef LIBMESH_ENABLE_AMR 01215 01216 // Trivial mapping 01217 libmesh_assert (dof_indices.size() == Ue.size()); 01218 bool has_constrained_dofs = false; 01219 01220 for (unsigned int il=0; il<dof_indices.size(); il++) 01221 { 01222 const unsigned int ig = dof_indices[il]; 01223 01224 if (this->is_constrained_dof (ig)) has_constrained_dofs = true; 01225 01226 libmesh_assert ((il >= Ug.first_local_index()) && 01227 (il < Ug.last_local_index())); 01228 01229 Ue.el(il) = Ug(ig); 01230 } 01231 01232 // If the element has any constrained DOFs then we need 01233 // to account for them in the mapping. This will handle 01234 // the case that the input vector is not constrained. 01235 if (has_constrained_dofs) 01236 { 01237 // Copy the input DOF indices. 01238 std::vector<unsigned int> constrained_dof_indices(dof_indices); 01239 01240 DenseMatrix<Number> C; 01241 01242 this->build_constraint_matrix (C, constrained_dof_indices); 01243 01244 libmesh_assert (dof_indices.size() == C.m()); 01245 libmesh_assert (constrained_dof_indices.size() == C.n()); 01246 01247 // zero-out Ue 01248 Ue.zero(); 01249 01250 // compute Ue = C Ug, with proper mapping. 01251 for (unsigned int i=0; i<dof_indices.size(); i++) 01252 for (unsigned int j=0; j<constrained_dof_indices.size(); j++) 01253 { 01254 const unsigned int jg = constrained_dof_indices[j]; 01255 01256 libmesh_assert ((jg >= Ug.first_local_index()) && 01257 (jg < Ug.last_local_index())); 01258 01259 Ue.el(i) += C(i,j)*Ug(jg); 01260 } 01261 } 01262 01263 #else 01264 01265 // Trivial mapping 01266 libmesh_assert (dof_indices.size() == Ue.size()); 01267 01268 for (unsigned int il=0; il<dof_indices.size(); il++) 01269 { 01270 const unsigned int ig = dof_indices[il]; 01271 01272 libmesh_assert ((ig >= Ug.first_local_index()) && (ig < Ug.last_local_index())); 01273 01274 Ue.el(il) = Ug(ig); 01275 } 01276 01277 #endif 01278 }
| void DofMap::find_connected_dofs | ( | std::vector< unsigned int > & | 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 1737 of file dof_map.C.
References _dof_constraints, and is_constrained_dof().
Referenced by SparsityPattern::Build::operator()().
01738 { 01739 typedef std::set<unsigned int> RCSet; 01740 01741 // First insert the DOFS we already depend on into the set. 01742 RCSet dof_set (elem_dofs.begin(), elem_dofs.end()); 01743 01744 bool done = true; 01745 01746 // Next insert any dofs those might be constrained in terms 01747 // of. Note that in this case we may not be done: Those may 01748 // in turn depend on others. So, we need to repeat this process 01749 // in that case until the system depends only on unconstrained 01750 // degrees of freedom. 01751 for (unsigned int i=0; i<elem_dofs.size(); i++) 01752 if (this->is_constrained_dof(elem_dofs[i])) 01753 { 01754 // If the DOF is constrained 01755 DofConstraints::const_iterator 01756 pos = _dof_constraints.find(elem_dofs[i]); 01757 01758 libmesh_assert (pos != _dof_constraints.end()); 01759 01760 const DofConstraintRow& constraint_row = pos->second; 01761 01762 // adaptive p refinement currently gives us lots of empty constraint 01763 // rows - we should optimize those DoFs away in the future. [RHS] 01764 // libmesh_assert (!constraint_row.empty()); 01765 01766 DofConstraintRow::const_iterator it = constraint_row.begin(); 01767 DofConstraintRow::const_iterator it_end = constraint_row.end(); 01768 01769 01770 // Add the DOFs this dof is constrained in terms of. 01771 // note that these dofs might also be constrained, so 01772 // we will need to call this function recursively. 01773 for ( ; it != it_end; ++it) 01774 if (!dof_set.count (it->first)) 01775 { 01776 dof_set.insert (it->first); 01777 done = false; 01778 } 01779 } 01780 01781 01782 // If not done then we need to do more work 01783 // (obviously :-) )! 01784 if (!done) 01785 { 01786 // Fill the vector with the contents of the set 01787 elem_dofs.clear(); 01788 elem_dofs.insert (elem_dofs.end(), 01789 dof_set.begin(), dof_set.end()); 01790 01791 01792 // May need to do this recursively. It is possible 01793 // that we just replaced a constrained DOF with another 01794 // constrained DOF. 01795 this->find_connected_dofs (elem_dofs); 01796 01797 } // end if (!done) 01798 }
| unsigned int DofMap::first_dof | ( | const unsigned int | proc = libMesh::processor_id() |
) | const [inline] |
Returns the first dof index that is local to subdomain proc.
Definition at line 363 of file dof_map.h.
References _first_df.
Referenced by add_constraints_to_send_list(), add_neighbors_to_send_list(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), enforce_constraints_exactly(), SparsityPattern::Build::join(), System::local_dof_indices(), SparsityPattern::Build::operator()(), SparseMatrix< T >::print(), and set_nonlocal_dof_objects().
| std::string ReferenceCounter::get_info | ( | ) | [static, inherited] |
Gets a string containing the reference information.
Definition at line 45 of file reference_counter.C.
References ReferenceCounter::_counts, and QuadratureRules::name().
Referenced by ReferenceCounter::print_info().
00046 { 00047 #if defined(LIBMESH_ENABLE_REFERENCE_COUNTING) && defined(DEBUG) 00048 00049 std::ostringstream out; 00050 00051 out << '\n' 00052 << " ---------------------------------------------------------------------------- \n" 00053 << "| Reference count information |\n" 00054 << " ---------------------------------------------------------------------------- \n"; 00055 00056 for (Counts::iterator it = _counts.begin(); 00057 it != _counts.end(); ++it) 00058 { 00059 const std::string name(it->first); 00060 const unsigned int creations = it->second.first; 00061 const unsigned int destructions = it->second.second; 00062 00063 out << "| " << name << " reference count information:\n" 00064 << "| Creations: " << creations << '\n' 00065 << "| Destructions: " << destructions << '\n'; 00066 } 00067 00068 out << " ---------------------------------------------------------------------------- \n"; 00069 00070 return out.str(); 00071 00072 #else 00073 00074 return ""; 00075 00076 #endif 00077 }
| const std::vector<unsigned int>& 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 299 of file dof_map.h.
References _n_nz.
Referenced by PetscMatrix< T >::init(), LaspackMatrix< T >::init(), and EpetraMatrix< T >::update_sparsity_pattern().
00299 { return _n_nz; }
| const std::vector<unsigned int>& 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 PetscMatrix< T >::init(), LaspackMatrix< T >::init(), and EpetraMatrix< T >::update_sparsity_pattern().
00307 { return _n_oz; }
| const std::vector<unsigned int>& 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 291 of file dof_map.h.
References _send_list.
Referenced by UnsteadySolver::solve().
00291 { return _send_list; }
| void 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 149 of file reference_counter.h.
References ReferenceCounter::_counts, and Threads::spin_mtx.
Referenced by ReferenceCountedObject< SparseMatrix< T > >::ReferenceCountedObject().
00150 { 00151 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx); 00152 std::pair<unsigned int, unsigned int>& p = _counts[name]; 00153 00154 p.first++; 00155 }
| void 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 167 of file reference_counter.h.
References ReferenceCounter::_counts, and Threads::spin_mtx.
Referenced by ReferenceCountedObject< SparseMatrix< T > >::~ReferenceCountedObject().
00168 { 00169 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx); 00170 std::pair<unsigned int, unsigned int>& p = _counts[name]; 00171 00172 p.second++; 00173 }
| void DofMap::invalidate_dofs | ( | MeshBase & | mesh | ) | const [private] |
Invalidates all active DofObject dofs for this system
Definition at line 601 of file dof_map.C.
References MeshBase::active_elements_begin(), MeshBase::active_elements_end(), MeshBase::nodes_begin(), MeshBase::nodes_end(), and sys_number().
Referenced by distribute_dofs(), and reinit().
00602 { 00603 const unsigned int sys_num = this->sys_number(); 00604 00605 // All the nodes 00606 MeshBase::node_iterator node_it = mesh.nodes_begin(); 00607 const MeshBase::node_iterator node_end = mesh.nodes_end(); 00608 00609 for ( ; node_it != node_end; ++node_it) 00610 (*node_it)->invalidate_dofs(sys_num); 00611 00612 // All the elements 00613 MeshBase::element_iterator elem_it = mesh.active_elements_begin(); 00614 const MeshBase::element_iterator elem_end = mesh.active_elements_end(); 00615 00616 for ( ; elem_it != elem_end; ++elem_it) 00617 (*elem_it)->invalidate_dofs(sys_num); 00618 }
| bool DofMap::is_constrained_dof | ( | const unsigned int | dof | ) | const [inline] |
- Returns:
- true if the degree of freedom dof is constrained, false otherwise.
Definition at line 895 of file dof_map.h.
References _dof_constraints.
Referenced by add_constraint_row(), allgather_recursive_constraints(), build_constraint_matrix(), FEBase::compute_periodic_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 process_constraints().
00896 { 00897 if (_dof_constraints.count(dof) != 0) 00898 return true; 00899 00900 return false; 00901 }
| bool DofMap::is_periodic_boundary | ( | const unsigned int | boundaryid | ) | const [inline] |
- Returns:
- true if the boundary given by
boundaryidis periodic, false otherwise
Definition at line 909 of file dof_map.h.
References _periodic_boundaries.
00910 { 00911 if (_periodic_boundaries.count(boundaryid) != 0) 00912 return true; 00913 00914 return false; 00915 }
| unsigned int DofMap::last_dof | ( | const unsigned int | proc = libMesh::processor_id() |
) | const [inline] |
| std::pair< Real, Real > 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 688 of file dof_map_constraints.C.
References MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), build_constraint_matrix(), NumericVector< T >::closed(), dof_indices(), NumericVector< T >::first_local_index(), System::get_dof_map(), System::get_mesh(), is_constrained_dof(), NumericVector< T >::last_local_index(), DenseMatrixBase< T >::m(), std::max(), mesh, DenseMatrixBase< T >::n(), and System::solution.
00690 { 00691 if (!v) 00692 v = system.solution.get(); 00693 NumericVector<Number> &vec = *v; 00694 00695 // We'll assume the vector is closed 00696 libmesh_assert (vec.closed()); 00697 00698 Real max_absolute_error = 0., max_relative_error = 0.; 00699 00700 const MeshBase &mesh = system.get_mesh(); 00701 00702 libmesh_assert (this == &(system.get_dof_map())); 00703 00704 // indices on each element 00705 std::vector<unsigned int> local_dof_indices; 00706 00707 MeshBase::const_element_iterator elem_it = 00708 mesh.active_local_elements_begin(); 00709 const MeshBase::const_element_iterator elem_end = 00710 mesh.active_local_elements_end(); 00711 00712 for ( ; elem_it != elem_end; ++elem_it) 00713 { 00714 const Elem* elem = *elem_it; 00715 00716 this->dof_indices(elem, local_dof_indices); 00717 std::vector<unsigned int> raw_dof_indices = local_dof_indices; 00718 00719 // Constraint matrix for each element 00720 DenseMatrix<Number> C; 00721 00722 this->build_constraint_matrix (C, local_dof_indices); 00723 00724 // Continue if the element is unconstrained 00725 if (!C.m()) 00726 continue; 00727 00728 libmesh_assert(C.m() == raw_dof_indices.size()); 00729 libmesh_assert(C.n() == local_dof_indices.size()); 00730 00731 for (unsigned int i=0; i!=C.m(); ++i) 00732 { 00733 // Recalculate any constrained dof owned by this processor 00734 unsigned int global_dof = raw_dof_indices[i]; 00735 if (this->is_constrained_dof(global_dof) && 00736 global_dof >= vec.first_local_index() && 00737 global_dof < vec.last_local_index()) 00738 { 00739 Number exact_value = 0; 00740 for (unsigned int j=0; j!=C.n(); ++j) 00741 { 00742 if (local_dof_indices[j] != global_dof) 00743 exact_value += C(i,j) * 00744 vec(local_dof_indices[j]); 00745 } 00746 00747 max_absolute_error = std::max(max_absolute_error, 00748 std::abs(vec(global_dof) - exact_value)); 00749 max_relative_error = std::max(max_relative_error, 00750 std::abs(vec(global_dof) - exact_value) 00751 / std::abs(exact_value)); 00752 } 00753 } 00754 } 00755 00756 return std::pair<Real, Real>(max_absolute_error, max_relative_error); 00757 }
| unsigned int DofMap::n_constrained_dofs | ( | ) | const [inline] |
- Returns:
- the total number of constrained degrees of freedom in the problem.
Definition at line 452 of file dof_map.h.
References _dof_constraints.
Referenced by constrain_element_dyad_matrix(), constrain_element_matrix(), constrain_element_matrix_and_vector(), constrain_element_vector(), constrain_nothing(), and enforce_constraints_exactly().
00452 { return _dof_constraints.size(); }
| unsigned int DofMap::n_dofs | ( | ) | const [inline] |
- Returns:
- the total number of degrees of freedom in the problem.
Definition at line 342 of file dof_map.h.
References _n_dfs.
Referenced by dof_indices(), enforce_constraints_exactly(), PetscMatrix< T >::init(), LaspackMatrix< T >::init(), SparsityPattern::Build::join(), old_dof_indices(), UnsteadySolver::old_nonlinear_solution(), SCALAR_dof_indices(), and EpetraMatrix< T >::update_sparsity_pattern().
00342 { return _n_dfs; }
| unsigned int DofMap::n_dofs_on_processor | ( | const unsigned int | proc | ) | const [inline] |
Returns the number of degrees of freedom on subdomain proc.
Definition at line 357 of file dof_map.h.
References _end_df, and _first_df.
Referenced by compute_sparsity(), PetscMatrix< T >::init(), LaspackMatrix< T >::init(), SparsityPattern::Build::join(), n_local_dofs(), SparsityPattern::Build::operator()(), and EpetraMatrix< T >::update_sparsity_pattern().
| unsigned int DofMap::n_local_dofs | ( | ) | const [inline] |
- Returns:
- the number of degrees of freedom on this processor.
Definition at line 351 of file dof_map.h.
References n_dofs_on_processor(), and libMesh::processor_id().
Referenced by enforce_constraints_exactly().
00352 { return this->n_dofs_on_processor (libMesh::processor_id()); }
| static unsigned int ReferenceCounter::n_objects | ( | ) | [inline, static, inherited] |
Prints the number of outstanding (created, but not yet destroyed) objects.
Definition at line 76 of file reference_counter.h.
References ReferenceCounter::_n_objects.
00077 { return _n_objects; }
| unsigned int DofMap::n_old_dofs | ( | ) | const [inline] |
- Returns:
- the total number of degrees of freedom on old_dof_objects
Definition at line 640 of file dof_map.h.
References _n_old_dfs.
Referenced by SCALAR_dof_indices().
00640 { return _n_old_dfs; }
| unsigned int DofMap::n_SCALAR_dofs | ( | ) | const [inline] |
- Returns:
- the number of SCALAR dofs.
Definition at line 346 of file dof_map.h.
References _n_SCALAR_dofs.
Referenced by SCALAR_dof_indices().
00346 { return _n_SCALAR_dofs; }
| unsigned int 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 335 of file dof_map.h.
References _variables.
Referenced by compute_sparsity(), create_dof_constraints(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), dof_indices(), old_dof_indices(), SparsityPattern::Build::operator()(), reinit(), SCALAR_dof_indices(), set_nonlocal_dof_objects(), and use_coupled_neighbor_dofs().
00336 { return _variables.size(); }
An adapter function that returns Node pointers by index
Definition at line 99 of file dof_map.C.
References MeshBase::node_ptr().
Referenced by distribute_dofs().
00100 { 00101 return mesh.node_ptr(i); 00102 }
| void DofMap::old_dof_indices | ( | const Elem *const | elem, | |
| std::vector< unsigned int > & | 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 1495 of file dof_map.C.
References Elem::active(), Elem::dim(), dim, DofObject::dof_number(), FEInterface::extra_hanging_dofs(), FEType::family, Elem::get_node(), DofObject::invalid_id, libMesh::invalid_uint, Elem::is_vertex(), Elem::JUST_COARSENED, Elem::JUST_REFINED, libMeshEnums::LAGRANGE, DofObject::n_comp(), n_dofs(), FEInterface::n_dofs_at_node(), FEInterface::n_dofs_per_elem(), Elem::n_nodes(), n_nodes, DofObject::n_systems(), n_variables(), n_vars, DofObject::old_dof_object, FEType::order, Elem::p_level(), Elem::p_refinement_flag(), Elem::refinement_flag(), libMeshEnums::SCALAR, SCALAR_dof_indices(), Elem::subdomain_id(), sys_number(), Elem::type(), type, variable(), and variable_type().
Referenced by FEBase::coarsened_dof_values(), and System::ProjectVector::operator()().
01498 { 01499 START_LOG("old_dof_indices()", "DofMap"); 01500 01501 libmesh_assert (elem != NULL); 01502 libmesh_assert (elem->old_dof_object != NULL); 01503 01504 01505 const unsigned int n_nodes = elem->n_nodes(); 01506 const ElemType type = elem->type(); 01507 const unsigned int sys_num = this->sys_number(); 01508 const unsigned int n_vars = this->n_variables(); 01509 const unsigned int dim = elem->dim(); 01510 01511 // Clear the DOF indices vector. 01512 di.clear(); 01513 01514 #ifdef DEBUG 01515 // Check that sizes match 01516 unsigned int tot_size = 0; 01517 #endif 01518 01519 // Create a vector to indicate which 01520 // SCALAR variables have been requested 01521 std::vector<unsigned int> SCALAR_var_numbers; 01522 SCALAR_var_numbers.clear(); 01523 01524 // Get the dof numbers 01525 for (unsigned int v=0; v<n_vars; v++) 01526 if ((v == vn) || (vn == libMesh::invalid_uint)) 01527 { 01528 if(this->variable(v).type().family == SCALAR) 01529 { 01530 // We asked for this variable, so add it to the vector. 01531 SCALAR_var_numbers.push_back(v); 01532 01533 #ifdef DEBUG 01534 FEType fe_type = this->variable_type(v); 01535 tot_size += FEInterface::n_dofs(dim, 01536 fe_type, 01537 type); 01538 #endif 01539 } 01540 else 01541 if (this->variable(v).active_on_subdomain(elem->subdomain_id())) 01542 { // Do this for all the variables if one was not specified 01543 // or just for the specified variable 01544 01545 // Increase the polynomial order on p refined elements, 01546 // but make sure you get the right polynomial order for 01547 // the OLD degrees of freedom 01548 int p_adjustment = 0; 01549 if (elem->p_refinement_flag() == Elem::JUST_REFINED) 01550 { 01551 libmesh_assert (elem->p_level() > 0); 01552 p_adjustment = -1; 01553 } 01554 else if (elem->p_refinement_flag() == Elem::JUST_COARSENED) 01555 { 01556 p_adjustment = 1; 01557 } 01558 FEType fe_type = this->variable_type(v); 01559 fe_type.order = static_cast<Order>(fe_type.order + 01560 elem->p_level() + 01561 p_adjustment); 01562 01563 const bool extra_hanging_dofs = 01564 FEInterface::extra_hanging_dofs(fe_type); 01565 01566 #ifdef DEBUG 01567 tot_size += FEInterface::n_dofs(dim, 01568 fe_type, 01569 type); 01570 #endif 01571 01572 // Get the node-based DOF numbers 01573 for (unsigned int n=0; n<n_nodes; n++) 01574 { 01575 const Node* node = elem->get_node(n); 01576 01577 // There is a potential problem with h refinement. Imagine a 01578 // quad9 that has a linear FE on it. Then, on the hanging side, 01579 // it can falsely identify a DOF at the mid-edge node. This is why 01580 // we call FEInterface instead of node->n_comp() directly. 01581 const unsigned int nc = FEInterface::n_dofs_at_node (dim, 01582 fe_type, 01583 type, 01584 n); 01585 libmesh_assert (node->old_dof_object != NULL); 01586 01587 // If this is a non-vertex on a hanging node with extra 01588 // degrees of freedom, we use the non-vertex dofs (which 01589 // come in reverse order starting from the end, to 01590 // simplify p refinement) 01591 if (extra_hanging_dofs && !elem->is_vertex(n)) 01592 { 01593 const int dof_offset = 01594 node->old_dof_object->n_comp(sys_num,v) - nc; 01595 01596 // We should never have fewer dofs than necessary on a 01597 // node unless we're getting indices on a parent element 01598 // or a just-coarsened element 01599 if (dof_offset < 0) 01600 { 01601 libmesh_assert(!elem->active() || elem->refinement_flag() == 01602 Elem::JUST_COARSENED); 01603 di.resize(di.size() + nc, DofObject::invalid_id); 01604 } 01605 else 01606 for (int i=node->old_dof_object->n_comp(sys_num,v)-1; 01607 i>=dof_offset; i--) 01608 { 01609 libmesh_assert (node->old_dof_object->dof_number(sys_num,v,i) != 01610 DofObject::invalid_id); 01611 di.push_back(node->old_dof_object->dof_number(sys_num,v,i)); 01612 } 01613 } 01614 // If this is a vertex or an element without extra hanging 01615 // dofs, our dofs come in forward order coming from the 01616 // beginning 01617 else 01618 for (unsigned int i=0; i<nc; i++) 01619 { 01620 libmesh_assert (node->old_dof_object->dof_number(sys_num,v,i) != 01621 DofObject::invalid_id); 01622 di.push_back(node->old_dof_object->dof_number(sys_num,v,i)); 01623 } 01624 } 01625 01626 // If there are any element-based DOF numbers, get them 01627 const unsigned int nc = FEInterface::n_dofs_per_elem(dim, 01628 fe_type, 01629 type); 01630 01631 // We should never have fewer dofs than necessary on an 01632 // element unless we're getting indices on a parent element 01633 // or a just-coarsened element 01634 if (nc != 0) 01635 { 01636 if (elem->old_dof_object->n_systems() > sys_num && 01637 nc <= elem->old_dof_object->n_comp(sys_num,v)) 01638 { 01639 libmesh_assert (elem->old_dof_object != NULL); 01640 01641 for (unsigned int i=0; i<nc; i++) 01642 { 01643 libmesh_assert (elem->old_dof_object->dof_number(sys_num,v,i) != 01644 DofObject::invalid_id); 01645 01646 di.push_back(elem->old_dof_object->dof_number(sys_num,v,i)); 01647 } 01648 } 01649 else 01650 { 01651 libmesh_assert(!elem->active() || fe_type.family == LAGRANGE || 01652 elem->refinement_flag() == Elem::JUST_COARSENED); 01653 di.resize(di.size() + nc, DofObject::invalid_id); 01654 } 01655 } 01656 } 01657 } // end loop over variables 01658 01659 // Finally append any SCALAR dofs that we asked for. 01660 std::vector<unsigned int> di_new; 01661 std::vector<unsigned int>::iterator it = SCALAR_var_numbers.begin(); 01662 std::vector<unsigned int>::const_iterator it_end = SCALAR_var_numbers.end(); 01663 for( ; it != it_end; ++it) 01664 { 01665 this->SCALAR_dof_indices(di_new,*it,true); 01666 di.insert( di.end(), di_new.begin(), di_new.end()); 01667 } 01668 01669 #ifdef DEBUG 01670 libmesh_assert (tot_size == di.size()); 01671 #endif 01672 01673 STOP_LOG("old_dof_indices()", "DofMap"); 01674 }
| void 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.
Definition at line 1089 of file dof_map.C.
References _send_list.
Referenced by EquationSystems::reinit().
01090 { 01091 START_LOG("prepare_send_list()", "DofMap"); 01092 01093 // First sort the send list. After this 01094 // duplicated elements will be adjacent in the 01095 // vector 01096 std::sort(_send_list.begin(), _send_list.end()); 01097 01098 // Now use std::unique to remove duplicate entries 01099 std::vector<unsigned int>::iterator new_end = 01100 std::unique (_send_list.begin(), _send_list.end()); 01101 01102 // Remove the end of the send_list. Use the "swap trick" 01103 // from Effective STL 01104 std::vector<unsigned int> (_send_list.begin(), new_end).swap (_send_list); 01105 01106 STOP_LOG("prepare_send_list()", "DofMap"); 01107 }
| void DofMap::print_dof_constraints | ( | std::ostream & | os = std::cout |
) | const |
Prints the _dof_constraints data structure.
Definition at line 201 of file dof_map_constraints.C.
References _dof_constraints.
00202 { 00203 os << "DOF CONSTRAINTS OUTPUT:" 00204 << std::endl; 00205 00206 for (DofConstraints::const_iterator it=_dof_constraints.begin(); 00207 it != _dof_constraints.end(); ++it) 00208 { 00209 const unsigned int i = it->first; 00210 const DofConstraintRow& row = it->second; 00211 00212 os << "Constraints for DOF " << i 00213 << ": \t"; 00214 00215 for (DofConstraintRow::const_iterator pos=row.begin(); 00216 pos != row.end(); ++pos) 00217 os << " (" << pos->first << "," 00218 << pos->second << ")\t"; 00219 00220 os << std::endl; 00221 } 00222 }
| void ReferenceCounter::print_info | ( | ) | [static, inherited] |
Prints the reference information to std::cout.
Definition at line 83 of file reference_counter.C.
References ReferenceCounter::get_info().
00084 { 00085 #if defined(LIBMESH_ENABLE_REFERENCE_COUNTING) && defined(DEBUG) 00086 00087 std::cout << ReferenceCounter::get_info(); 00088 00089 #endif 00090 }
| void DofMap::process_constraints | ( | ) |
Postprocesses any constrained degrees of freedom in elem_dofs 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 1124 of file dof_map_constraints.C.
References _dof_constraints, add_constraints_to_send_list(), and is_constrained_dof().
Referenced by EquationSystems::reinit().
01125 { 01126 // Create a set containing the DOFs we already depend on 01127 typedef std::set<unsigned int> RCSet; 01128 RCSet unexpanded_set; 01129 01130 for (DofConstraints::iterator i = _dof_constraints.begin(); 01131 i != _dof_constraints.end(); ++i) 01132 unexpanded_set.insert(i->first); 01133 01134 while (!unexpanded_set.empty()) 01135 for (RCSet::iterator i = unexpanded_set.begin(); 01136 i != unexpanded_set.end(); /* nothing */) 01137 { 01138 // If the DOF is constrained 01139 DofConstraints::iterator 01140 pos = _dof_constraints.find(*i); 01141 01142 libmesh_assert (pos != _dof_constraints.end()); 01143 01144 DofConstraintRow& constraint_row = pos->second; 01145 01146 std::vector<unsigned int> constraints_to_expand; 01147 01148 for (DofConstraintRow::const_iterator 01149 it=constraint_row.begin(); it != constraint_row.end(); 01150 ++it) 01151 if (this->is_constrained_dof(it->first)) 01152 { 01153 unexpanded_set.insert(it->first); 01154 constraints_to_expand.push_back(it->first); 01155 } 01156 01157 for (unsigned int j = 0; j != constraints_to_expand.size(); 01158 ++j) 01159 { 01160 unsigned int expandable = constraints_to_expand[j]; 01161 01162 DofConstraints::const_iterator 01163 subpos = _dof_constraints.find(expandable); 01164 01165 libmesh_assert (subpos != _dof_constraints.end()); 01166 01167 const DofConstraintRow& subconstraint_row = subpos->second; 01168 01169 for (DofConstraintRow::const_iterator 01170 it=subconstraint_row.begin(); 01171 it != subconstraint_row.end(); ++it) 01172 { 01173 constraint_row[it->first] += it->second * 01174 constraint_row[expandable]; 01175 } 01176 constraint_row.erase(expandable); 01177 } 01178 01179 if (constraints_to_expand.empty()) 01180 unexpanded_set.erase(i++); 01181 else 01182 i++; 01183 } 01184 01185 // Now that we have our root constraint dependencies sorted out, add 01186 // them to the send_list 01187 this->add_constraints_to_send_list(); 01188 }
| void DofMap::reinit | ( | MeshBase & | mesh | ) |
Reinitialize the underlying data strucures conformal to the current mesh.
Definition at line 263 of file dof_map.C.
References _n_SCALAR_dofs, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), System::Variable::active_on_subdomain(), Elem::dim(), dim, DofObject::dof_number(), MeshBase::elements_begin(), MeshBase::elements_end(), Utility::enum_to_string(), FEInterface::extra_hanging_dofs(), FEType::family, Elem::get_node(), DofObject::has_dofs(), invalidate_dofs(), MeshBase::is_prepared(), Elem::is_vertex(), Elem::JUST_REFINED, std::max(), FEInterface::max_order(), DofObject::n_comp(), FEInterface::n_dofs_at_node(), FEInterface::n_dofs_per_elem(), Elem::n_nodes(), n_variables(), MeshBase::nodes_begin(), MeshBase::nodes_end(), DofObject::old_dof_object, FEType::order, Elem::p_level(), Elem::refinement_flag(), libMeshEnums::SCALAR, DofObject::set_dof_number(), DofObject::set_n_comp(), DofObject::set_old_dof_object(), Elem::set_p_level(), Elem::subdomain_id(), sys_number(), Elem::type(), type, variable(), and variable_type().
Referenced by distribute_dofs().
00264 { 00265 libmesh_assert (mesh.is_prepared()); 00266 00267 START_LOG("reinit()", "DofMap"); 00268 00269 //this->clear(); 00270 00271 const unsigned int n_var = this->n_variables(); 00272 00273 #ifdef LIBMESH_ENABLE_AMR 00274 00275 //------------------------------------------------------------ 00276 // Clear the old_dof_objects for all the nodes 00277 // and elements so that we can overwrite them 00278 { 00279 MeshBase::node_iterator node_it = mesh.nodes_begin(); 00280 const MeshBase::node_iterator node_end = mesh.nodes_end(); 00281 00282 for ( ; node_it != node_end; ++node_it) 00283 { 00284 (*node_it)->clear_old_dof_object(); 00285 libmesh_assert ((*node_it)->old_dof_object == NULL); 00286 } 00287 00288 MeshBase::element_iterator elem_it = mesh.elements_begin(); 00289 const MeshBase::element_iterator elem_end = mesh.elements_end(); 00290 00291 for ( ; elem_it != elem_end; ++elem_it) 00292 { 00293 (*elem_it)->clear_old_dof_object(); 00294 libmesh_assert ((*elem_it)->old_dof_object == NULL); 00295 } 00296 } 00297 00298 00299 //------------------------------------------------------------ 00300 // Set the old_dof_objects for the elements that 00301 // weren't just created, if these old dof objects 00302 // had variables 00303 { 00304 MeshBase::element_iterator elem_it = mesh.elements_begin(); 00305 const MeshBase::element_iterator elem_end = mesh.elements_end(); 00306 00307 for ( ; elem_it != elem_end; ++elem_it) 00308 { 00309 Elem* elem = *elem_it; 00310 00311 // Skip the elements that were just refined 00312 if (elem->refinement_flag() == Elem::JUST_REFINED) continue; 00313 00314 for (unsigned int n=0; n<elem->n_nodes(); n++) 00315 { 00316 Node* node = elem->get_node(n); 00317 00318 if (node->old_dof_object == NULL) 00319 if (node->has_dofs()) 00320 node->set_old_dof_object(); 00321 } 00322 00323 libmesh_assert (elem->old_dof_object == NULL); 00324 00325 if (elem->has_dofs()) 00326 elem->set_old_dof_object(); 00327 } 00328 } 00329 00330 #endif // #ifdef LIBMESH_ENABLE_AMR 00331 00332 00333 //------------------------------------------------------------ 00334 // Then set the number of variables for each \p DofObject 00335 // equal to n_variables() for this system. This will 00336 // handle new \p DofObjects that may have just been created 00337 { 00338 // All the nodes 00339 MeshBase::node_iterator node_it = mesh.nodes_begin(); 00340 const MeshBase::node_iterator node_end = mesh.nodes_end(); 00341 00342 for ( ; node_it != node_end; ++node_it) 00343 (*node_it)->set_n_vars(this->sys_number(),n_var); 00344 00345 // All the elements 00346 MeshBase::element_iterator elem_it = mesh.elements_begin(); 00347 const MeshBase::element_iterator elem_end = mesh.elements_end(); 00348 00349 for ( ; elem_it != elem_end; ++elem_it) 00350 (*elem_it)->set_n_vars(this->sys_number(),n_var); 00351 } 00352 00353 00354 // Zero _n_SCALAR_dofs, it will be updated below. 00355 this->_n_SCALAR_dofs = 0; 00356 00357 //------------------------------------------------------------ 00358 // Next allocate space for the DOF indices 00359 for (unsigned int var=0; var<this->n_variables(); var++) 00360 { 00361 const System::Variable &var_description = this->variable(var); 00362 const FEType& base_fe_type = this->variable_type(var); 00363 00364 // Don't need to loop over elements for a SCALAR variable 00365 // Just increment _n_SCALAR_dofs 00366 if(base_fe_type.family == SCALAR) 00367 { 00368 this->_n_SCALAR_dofs += base_fe_type.order; 00369 continue; 00370 } 00371 00372 // This should be constant even on p-refined elements 00373 const bool extra_hanging_dofs = 00374 FEInterface::extra_hanging_dofs(base_fe_type); 00375 00376 // For all the active elements 00377 MeshBase::element_iterator elem_it = mesh.active_elements_begin(); 00378 const MeshBase::element_iterator elem_end = mesh.active_elements_end(); 00379 00380 // Count vertex degrees of freedom first 00381 for ( ; elem_it != elem_end; ++elem_it) 00382 { 00383 Elem* elem = *elem_it; 00384 libmesh_assert (elem != NULL); 00385 00386 // Skip the numbering if this variable is 00387 // not active on this element's subdoman 00388 if (!var_description.active_on_subdomain(elem->subdomain_id())) 00389 continue; 00390 00391 const ElemType type = elem->type(); 00392 const unsigned int dim = elem->dim(); 00393 00394 FEType fe_type = base_fe_type; 00395 00396 #ifdef LIBMESH_ENABLE_AMR 00397 // Make sure we haven't done more p refinement than we can 00398 // handle 00399 if (elem->p_level() + base_fe_type.order > 00400 FEInterface::max_order(base_fe_type, type)) 00401 { 00402 # ifdef DEBUG 00403 if (FEInterface::max_order(base_fe_type,type) < 00404 static_cast<unsigned int>(base_fe_type.order)) 00405 { 00406 std::cerr << "ERROR: Finite element " 00407 << Utility::enum_to_string(base_fe_type.family) 00408 << " on geometric element " 00409 << Utility::enum_to_string(type) << std::endl 00410 << "only supports FEInterface::max_order = " 00411 << FEInterface::max_order(base_fe_type,type) 00412 << ", not fe_type.order = " << base_fe_type.order 00413 << std::endl; 00414 00415 libmesh_error(); 00416 } 00417 00418 std::cerr << "WARNING: Finite element " 00419 << Utility::enum_to_string(base_fe_type.family) 00420 << " on geometric element " 00421 << Utility::enum_to_string(type) << std::endl 00422 << "could not be p refined past FEInterface::max_order = " 00423 << FEInterface::max_order(base_fe_type,type) 00424 << std::endl; 00425 # endif 00426 elem->set_p_level(FEInterface::max_order(base_fe_type,type) 00427 - base_fe_type.order); 00428 } 00429 #endif 00430 00431 fe_type.order = static_cast<Order>(fe_type.order + 00432 elem->p_level()); 00433 00434 // Allocate the vertex DOFs 00435 for (unsigned int n=0; n<elem->n_nodes(); n++) 00436 { 00437 Node* node = elem->get_node(n); 00438 00439 if (elem->is_vertex(n)) 00440 { 00441 const unsigned int old_node_dofs = 00442 node->n_comp(this->sys_number(), var); 00443 00444 const unsigned int vertex_dofs = 00445 std::max(FEInterface::n_dofs_at_node(dim, fe_type, 00446 type, n), 00447 old_node_dofs); 00448 00449 // Some discontinuous FEs have no vertex dofs 00450 if (vertex_dofs > old_node_dofs) 00451 { 00452 node->set_n_comp(this->sys_number(), var, 00453 vertex_dofs); 00454 // Abusing dof_number to set a "this is a 00455 // vertex" flag 00456 node->set_dof_number(this->sys_number(), 00457 var, 0, vertex_dofs); 00458 } 00459 } 00460 } 00461 } // done counting vertex dofs 00462 00463 // count edge & face dofs next 00464 elem_it = mesh.active_elements_begin(); 00465 00466 for ( ; elem_it != elem_end; ++elem_it) 00467 { 00468 Elem* elem = *elem_it; 00469 libmesh_assert (elem != NULL); 00470 00471 // Skip the numbering if this variable is 00472 // not active on this element's subdoman 00473 if (!var_description.active_on_subdomain(elem->subdomain_id())) 00474 continue; 00475 00476 const ElemType type = elem->type(); 00477 const unsigned int dim = elem->dim(); 00478 00479 FEType fe_type = base_fe_type; 00480 fe_type.order = static_cast<Order>(fe_type.order + 00481 elem->p_level()); 00482 00483 // Allocate the edge and face DOFs 00484 for (unsigned int n=0; n<elem->n_nodes(); n++) 00485 { 00486 Node* node = elem->get_node(n); 00487 00488 const unsigned int old_node_dofs = 00489 node->n_comp(this->sys_number(), var); 00490 00491 const unsigned int vertex_dofs = old_node_dofs? 00492 node->dof_number (this->sys_number(),var,0):0; 00493 00494 const unsigned int new_node_dofs = 00495 FEInterface::n_dofs_at_node(dim, fe_type, type, n); 00496 00497 // We've already allocated vertex DOFs 00498 if (elem->is_vertex(n)) 00499 { 00500 libmesh_assert(old_node_dofs >= vertex_dofs); 00501 libmesh_assert(vertex_dofs >= new_node_dofs); 00502 } 00503 // We need to allocate the rest 00504 else 00505 { 00506 // If this has no dofs yet, it needs no vertex 00507 // dofs, so we just give it edge or face dofs 00508 if (!old_node_dofs) 00509 { 00510 node->set_n_comp(this->sys_number(), var, 00511 new_node_dofs); 00512 // Abusing dof_number to set a "this has no 00513 // vertex dofs" flag 00514 if (new_node_dofs) 00515 node->set_dof_number(this->sys_number(), 00516 var, 0, 0); 00517 } 00518 00519 // If this has dofs, but has no vertex dofs, 00520 // it may still need more edge or face dofs if 00521 // we're p-refined. 00522 else if (vertex_dofs == 0) 00523 { 00524 if (new_node_dofs > old_node_dofs) 00525 { 00526 node->set_n_comp(this->sys_number(), var, 00527 new_node_dofs); 00528 node->set_dof_number(this->sys_number(), 00529 var, 0, vertex_dofs); 00530 } 00531 } 00532 // If this is another element's vertex, 00533 // add more (non-overlapping) edge/face dofs if 00534 // necessary 00535 else if (extra_hanging_dofs) 00536 { 00537 if (new_node_dofs > old_node_dofs - vertex_dofs) 00538 { 00539 node->set_n_comp(this->sys_number(), var, 00540 vertex_dofs + new_node_dofs); 00541 node->set_dof_number(this->sys_number(), 00542 var, 0, vertex_dofs); 00543 } 00544 } 00545 // If this is another element's vertex, add any 00546 // (overlapping) edge/face dofs if necessary 00547 else 00548 { 00549 libmesh_assert(old_node_dofs >= vertex_dofs); 00550 if (new_node_dofs > old_node_dofs) 00551 { 00552 node->set_n_comp(this->sys_number(), var, 00553 new_node_dofs); 00554 node->set_dof_number(this->sys_number(), 00555 var, 0, vertex_dofs); 00556 } 00557 } 00558 } 00559 } 00560 // Allocate the element DOFs 00561 const unsigned int dofs_per_elem = 00562 FEInterface::n_dofs_per_elem(dim, fe_type, 00563 type); 00564 00565 elem->set_n_comp(this->sys_number(), var, dofs_per_elem); 00566 00567 } 00568 } 00569 00570 // Calling DofMap::reinit() by itself makes little sense, 00571 // so we won't bother with nonlocal DofObjects. 00572 // Those will be fixed by distribute_dofs 00573 /* 00574 //------------------------------------------------------------ 00575 // At this point, all n_comp and dof_number values on local 00576 // DofObjects should be correct, but a ParallelMesh might have 00577 // incorrect values on non-local DofObjects. Let's request the 00578 // correct values from each other processor. 00579 00580 this->set_nonlocal_n_comps(mesh.nodes_begin(), 00581 mesh.nodes_end(), 00582 mesh, 00583 &DofMap::node_ptr); 00584 00585 this->set_nonlocal_n_comps(mesh.elements_begin(), 00586 mesh.elements_end(), 00587 mesh, 00588 &DofMap::elem_ptr); 00589 */ 00590 00591 //------------------------------------------------------------ 00592 // Finally, clear all the current DOF indices 00593 // (distribute_dofs expects them cleared!) 00594 this->invalidate_dofs(mesh); 00595 00596 STOP_LOG("reinit()", "DofMap"); 00597 }
| void DofMap::SCALAR_dof_indices | ( | std::vector< unsigned int > & | 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.
Definition at line 1438 of file dof_map.C.
References FEType::family, n_dofs(), n_old_dofs(), n_SCALAR_dofs(), n_variables(), FEType::order, libMeshEnums::SCALAR, System::Variable::type(), type, and variable().
Referenced by dof_indices(), old_dof_indices(), and System::project_vector().
01441 { 01442 START_LOG("SCALAR_dof_indices()", "DofMap"); 01443 01444 if(this->variable(vn).type().family != SCALAR) 01445 { 01446 std::cerr << "ERROR: SCALAR_dof_indices called for a non-SCALAR variable." 01447 << std::endl; 01448 } 01449 01450 // Clear the DOF indices vector 01451 di.clear(); 01452 01453 // First we need to find out the first dof 01454 // index for each SCALAR. 01455 unsigned int first_SCALAR_dof_index = (old_dofs ? n_old_dofs() : n_dofs()) - n_SCALAR_dofs(); 01456 std::map<unsigned int, unsigned int> SCALAR_first_dof_index; 01457 SCALAR_first_dof_index.clear(); 01458 01459 // Iterate over _all_ of the SCALARs and store each one's first dof index 01460 // We need to do this since the SCALAR dofs are packed contiguously 01461 for (unsigned int v=0; v<this->n_variables(); v++) 01462 if(this->variable(v).type().family == SCALAR) 01463 { 01464 unsigned int current_n_SCALAR_dofs = this->variable(v).type().order; 01465 SCALAR_first_dof_index.insert( 01466 std::pair<unsigned int, unsigned int>(v,first_SCALAR_dof_index) ); 01467 first_SCALAR_dof_index += current_n_SCALAR_dofs; 01468 } 01469 01470 // Now use vn to index into SCALAR_first_dof_index 01471 std::map<unsigned int, unsigned int>::const_iterator iter = 01472 SCALAR_first_dof_index.find(vn); 01473 01474 #ifdef DEBUG 01475 libmesh_assert(iter != SCALAR_first_dof_index.end()); 01476 #endif 01477 01478 unsigned int current_first_SCALAR_dof_index = iter->second; 01479 01480 // Also, get the number of SCALAR dofs from the variable order 01481 unsigned int current_n_SCALAR_dofs = this->variable(vn).type().order; 01482 01483 for(unsigned int j=0; j<current_n_SCALAR_dofs; j++) 01484 { 01485 unsigned int index = current_first_SCALAR_dof_index+j; 01486 di.push_back(index); 01487 } 01488 01489 STOP_LOG("SCALAR_dof_indices()", "DofMap"); 01490 }
| void 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 114 of file dof_map.C.
References _send_list, DofObject::dof_number(), first_dof(), DofObject::id(), DofObject::invalid_id, DofObject::invalid_processor_id, DofObject::n_comp(), libMesh::n_processors(), n_variables(), DofObject::n_vars(), libMesh::processor_id(), DofObject::processor_id(), DofObject::set_dof_number(), DofObject::set_n_comp(), and sys_number().
Referenced by distribute_dofs().
00118 { 00119 // This function must be run on all processors at once 00120 parallel_only(); 00121 00122 // First, iterate over local objects to find out how many 00123 // are on each processor 00124 std::vector<unsigned int> 00125 ghost_objects_from_proc(libMesh::n_processors(), 0); 00126 00127 iterator_type it = objects_begin; 00128 00129 for (; it != objects_end; ++it) 00130 { 00131 DofObject *obj = *it; 00132 00133 if (obj) 00134 { 00135 unsigned int obj_procid = obj->processor_id(); 00136 // We'd better be completely partitioned by now 00137 libmesh_assert(obj_procid != DofObject::invalid_processor_id); 00138 ghost_objects_from_proc[obj_procid]++; 00139 } 00140 } 00141 00142 std::vector<unsigned int> objects_on_proc(libMesh::n_processors(), 0); 00143 Parallel::allgather(ghost_objects_from_proc[libMesh::processor_id()], 00144 objects_on_proc); 00145 00146 #ifdef DEBUG 00147 for (unsigned int p=0; p != libMesh::n_processors(); ++p) 00148 libmesh_assert(ghost_objects_from_proc[p] <= objects_on_proc[p]); 00149 #endif 00150 00151 // Request sets to send to each processor 00152 std::vector<std::vector<unsigned int> > 00153 requested_ids(libMesh::n_processors()); 00154 00155 // We know how many of our objects live on each processor, so 00156 // reserve() space for requests from each. 00157 for (unsigned int p=0; p != libMesh::n_processors(); ++p) 00158 if (p != libMesh::processor_id()) 00159 requested_ids[p].reserve(ghost_objects_from_proc[p]); 00160 00161 for (it = objects_begin; it != objects_end; ++it) 00162 { 00163 DofObject *obj = *it; 00164 if (obj->processor_id() != DofObject::invalid_processor_id) 00165 requested_ids[obj->processor_id()].push_back(obj->id()); 00166 } 00167 #ifdef DEBUG 00168 for (unsigned int p=0; p != libMesh::n_processors(); ++p) 00169 libmesh_assert(requested_ids[p].size() == ghost_objects_from_proc[p]); 00170 #endif 00171 00172 // Next set ghost object n_comps from other processors 00173 for (unsigned int p=1; p != libMesh::n_processors(); ++p) 00174 { 00175 // Trade my requests with processor procup and procdown 00176 unsigned int procup = (libMesh::processor_id() + p) % 00177 libMesh::n_processors(); 00178 unsigned int procdown = (libMesh::n_processors() + 00179 libMesh::processor_id() - p) % 00180 libMesh::n_processors(); 00181 std::vector<unsigned int> request_to_fill; 00182 Parallel::send_receive(procup, requested_ids[procup], 00183 procdown, request_to_fill); 00184 00185 // Fill those requests 00186 const unsigned int n_variables = this->n_variables(); 00187 00188 std::vector<unsigned int> ghost_data 00189 (request_to_fill.size() * 2 * n_variables); 00190 00191 for (unsigned int i=0; i != request_to_fill.size(); ++i) 00192 { 00193 DofObject *requested = (this->*objects)(mesh, request_to_fill[i]); 00194 libmesh_assert(requested); 00195 libmesh_assert(requested->processor_id() == libMesh::processor_id()); 00196 libmesh_assert(requested->n_vars(this->sys_number()) == n_variables); 00197 for (unsigned int v=0; v != n_variables; ++v) 00198 { 00199 unsigned int n_comp = 00200 requested->n_comp(this->sys_number(), v); 00201 ghost_data[i*2*n_variables+v] = n_comp; 00202 unsigned int first_dof = n_comp ? 00203 requested->dof_number(this->sys_number(), v, 0) : 0; 00204 libmesh_assert(first_dof != DofObject::invalid_id); 00205 ghost_data[i*2*n_variables+n_variables+v] = first_dof; 00206 } 00207 } 00208 00209 // Trade back the results 00210 std::vector<unsigned int> filled_request; 00211 Parallel::send_receive(procdown, ghost_data, 00212 procup, filled_request); 00213 00214 // And copy the id changes we've now been informed of 00215 libmesh_assert(filled_request.size() == 00216 requested_ids[procup].size() * 2 * n_variables); 00217 for (unsigned int i=0; i != requested_ids[procup].size(); ++i) 00218 { 00219 DofObject *requested = (this->*objects)(mesh, requested_ids[procup][i]); 00220 libmesh_assert(requested); 00221 libmesh_assert (requested->processor_id() == procup); 00222 for (unsigned int v=0; v != n_variables; ++v) 00223 { 00224 unsigned int n_comp = filled_request[i*2*n_variables+v]; 00225 requested->set_n_comp(this->sys_number(), v, n_comp); 00226 if (n_comp) 00227 { 00228 unsigned int first_dof = 00229 filled_request[i*2*n_variables+n_variables+v]; 00230 libmesh_assert(first_dof != DofObject::invalid_id); 00231 requested->set_dof_number 00232 (this->sys_number(), v, 0, first_dof); 00233 00234 // don't forget to add these remote dofs to the _send_list 00235 for (unsigned int comp=0; comp!=n_comp; ++comp) 00236 _send_list.push_back(first_dof+comp); 00237 } 00238 } 00239 } 00240 } 00241 00242 #ifdef DEBUG 00243 // Double check for invalid dofs 00244 for (it = objects_begin; it != objects_end; ++it) 00245 { 00246 DofObject *obj = *it; 00247 libmesh_assert (obj); 00248 unsigned int n_variables = obj->n_vars(this->sys_number()); 00249 for (unsigned int v=0; v != n_variables; ++v) 00250 { 00251 unsigned int n_comp = 00252 obj->n_comp(this->sys_number(), v); 00253 unsigned int first_dof = n_comp ? 00254 obj->dof_number(this->sys_number(), v, 0) : 0; 00255 libmesh_assert(first_dof != DofObject::invalid_id); 00256 } 00257 } 00258 #endif 00259 }
| unsigned int DofMap::sys_number | ( | ) | const [inline, private] |
- Returns:
- the number of the system we are responsible for.
Definition at line 921 of file dof_map.h.
References _sys_number.
Referenced by 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().
00922 { 00923 return _sys_number; 00924 }
| bool 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 1111 of file dof_map.C.
References FEBase::build(), libMeshEnums::DISCONTINUOUS, MeshBase::mesh_dimension(), n_variables(), libMesh::on_command_line(), and variable_type().
Referenced by compute_sparsity().
01112 { 01113 // If we were asked on the command line, then we need to 01114 // include sensitivities between neighbor degrees of freedom 01115 bool implicit_neighbor_dofs = 01116 libMesh::on_command_line ("--implicit_neighbor_dofs"); 01117 01118 // look at all the variables in this system. If every one is 01119 // discontinuous then the user must be doing DG/FVM, so be nice 01120 // and force implicit_neighbor_dofs=true 01121 { 01122 bool all_discontinuous_dofs = true; 01123 01124 for (unsigned int var=0; var<this->n_variables(); var++) 01125 if (FEBase::build (mesh.mesh_dimension(), 01126 this->variable_type(var))->get_continuity() != DISCONTINUOUS) 01127 all_discontinuous_dofs = false; 01128 01129 if (all_discontinuous_dofs) 01130 implicit_neighbor_dofs = true; 01131 } 01132 01133 return implicit_neighbor_dofs; 01134 }
| const System::Variable & DofMap::variable | ( | const unsigned int | c | ) | const |
- Returns:
- the variable description object for variable
c.
Definition at line 63 of file dof_map.C.
References _variables.
Referenced by distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), dof_indices(), old_dof_indices(), System::ProjectVector::operator()(), reinit(), and SCALAR_dof_indices().
00064 { 00065 libmesh_assert (c < _variables.size()); 00066 00067 return _variables[c]; 00068 }
| unsigned int DofMap::variable_first_local_dof | ( | const unsigned int | var | ) | const [inline] |
Returns the first local degree of freedom index for variable var.
Definition at line 384 of file dof_map.h.
References _var_first_local_df, and DofObject::invalid_id.
00385 { 00386 libmesh_assert ((var+1) < _var_first_local_df.size()); 00387 libmesh_assert (_var_first_local_df[var] != DofObject::invalid_id); 00388 return _var_first_local_df[var]; 00389 }
| unsigned int DofMap::variable_last_local_dof | ( | const unsigned int | var | ) | const [inline] |
Returns (one past) the last local degree of freedom index for variable var. Analogous to the end() member function of STL containers.
Definition at line 395 of file dof_map.h.
References _var_first_local_df, and DofObject::invalid_id.
00396 { 00397 libmesh_assert ((var+1) < _var_first_local_df.size()); 00398 libmesh_assert (_var_first_local_df[var+1] != DofObject::invalid_id); 00399 return _var_first_local_df[var+1]; 00400 }
| Order DofMap::variable_order | ( | const unsigned int | c | ) | const |
- Returns:
- the approximation order for variable
c.
Definition at line 72 of file dof_map.C.
References _variables.
00073 { 00074 libmesh_assert (c < _variables.size()); 00075 00076 return _variables[c].type().order; 00077 }
| const FEType & DofMap::variable_type | ( | const unsigned int | c | ) | const |
- Returns:
- the finite element type for variable
c.
Definition at line 81 of file dof_map.C.
References _variables.
Referenced by ExactSolution::_compute_error(), HPCoarsenTest::add_projection(), System::calculate_norm(), FEBase::coarsened_dof_values(), FEInterface::compute_constraints(), FEBase::compute_periodic_constraints(), FEBase::compute_proj_constraints(), constrain_p_dofs(), dof_indices(), JumpErrorEstimator::estimate_error(), ExactErrorEstimator::estimate_error(), System::get_info(), MeshFunction::gradient(), MeshFunction::hessian(), old_dof_indices(), System::ProjectVector::operator()(), PatchRecoveryErrorEstimator::EstimateError::operator()(), MeshFunction::operator()(), reinit(), HPCoarsenTest::select_refinement(), and use_coupled_neighbor_dofs().
00082 { 00083 libmesh_assert (c < _variables.size()); 00084 00085 return _variables[c].type(); 00086 }
Friends And Related Function Documentation
friend class SparsityPattern::Build [friend] |
Member Data Documentation
ReferenceCounter::Counts ReferenceCounter::_counts [static, protected, inherited] |
Actually holds the data.
Definition at line 110 of file reference_counter.h.
Referenced by ReferenceCounter::get_info(), ReferenceCounter::increment_constructor_count(), and ReferenceCounter::increment_destructor_count().
DofConstraints DofMap::_dof_constraints [private] |
Data structure containing DOF constraints. The ith entry is the constraint matrix row for DOF i.
Definition at line 857 of file dof_map.h.
Referenced by add_constraint_row(), add_constraints_to_send_list(), allgather_recursive_constraints(), build_constraint_matrix(), clear(), constrain_element_matrix(), constrain_element_matrix_and_vector(), constrain_p_dofs(), create_dof_constraints(), enforce_constraints_exactly(), find_connected_dofs(), is_constrained_dof(), n_constrained_dofs(), print_dof_constraints(), and process_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.
Definition at line 677 of file dof_map.h.
Referenced by compute_sparsity().
std::vector<unsigned int> DofMap::_end_df [private] |
Last DOF index (plus 1) on processor p.
Definition at line 806 of file dof_map.h.
Referenced by allgather_recursive_constraints(), clear(), distribute_dofs(), end_dof(), last_dof(), and n_dofs_on_processor().
std::vector<unsigned int> DofMap::_first_df [private] |
First DOF index on processor p.
Definition at line 801 of file dof_map.h.
Referenced by clear(), distribute_dofs(), first_dof(), and n_dofs_on_processor().
std::vector<SparseMatrix<Number>* > 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 796 of file dof_map.h.
Referenced by attach_matrix(), clear(), compute_sparsity(), and DofMap().
Threads::spin_mutex ReferenceCounter::_mutex [static, protected, inherited] |
Mutual exclusion object to enable thread-safe reference counting.
Definition at line 123 of file reference_counter.h.
unsigned int DofMap::_n_dfs [private] |
Total number of degrees of freedom.
Definition at line 834 of file dof_map.h.
Referenced by clear(), distribute_dofs(), and n_dofs().
std::vector<unsigned int> DofMap::_n_nz [private] |
The number of on-processor nonzeros in my portion of the global matrix.
Definition at line 823 of file dof_map.h.
Referenced by clear(), compute_sparsity(), and get_n_nz().
Threads::atomic< unsigned int > ReferenceCounter::_n_objects [static, protected, inherited] |
The number of objects. Print the reference count information when the number returns to 0.
Definition at line 118 of file reference_counter.h.
Referenced by ReferenceCounter::n_objects(), ReferenceCounter::ReferenceCounter(), and ReferenceCounter::~ReferenceCounter().
unsigned int DofMap::_n_old_dfs [private] |
Total number of degrees of freedom on old dof objects
Definition at line 847 of file dof_map.h.
Referenced by clear(), distribute_dofs(), and n_old_dofs().
std::vector<unsigned int> DofMap::_n_oz [private] |
The number of off-processor nonzeros in my portion of the global matrix.
Definition at line 829 of file dof_map.h.
Referenced by clear(), compute_sparsity(), and get_n_oz().
unsigned int DofMap::_n_SCALAR_dofs [private] |
The total number of SCALAR dofs associated to all SCALAR variables.
Definition at line 840 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 periodic boundaries. The ith entry is the constraint matrix row for boundaryid i.
Definition at line 867 of file dof_map.h.
Referenced by add_periodic_boundary(), create_dof_constraints(), and is_periodic_boundary().
std::vector<unsigned int> DofMap::_send_list [private] |
A list containing all the global DOF indicies that affect the solution on my subdomain.
Definition at line 817 of file dof_map.h.
Referenced by add_constraints_to_send_list(), add_neighbors_to_send_list(), clear(), distribute_dofs(), get_send_list(), prepare_send_list(), and set_nonlocal_dof_objects().
const unsigned int DofMap::_sys_number [private] |
The number of the system we manage DOFs for.
Definition at line 789 of file dof_map.h.
Referenced by sys_number().
std::vector<unsigned int> DofMap::_var_first_local_df [private] |
The first local DOF index for each variable in the System.
Definition at line 811 of file dof_map.h.
Referenced by clear(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), variable_first_local_dof(), and variable_last_local_dof().
std::vector<System::Variable> DofMap::_variables [private] |
The finite element type for each variable.
Definition at line 784 of file dof_map.h.
Referenced by add_variable(), clear(), n_variables(), variable(), variable_order(), and variable_type().
The documentation for this class was generated from the following files: