DofMap Class Reference

#include <dof_map.h>

Inheritance diagram for DofMap:

List of all members.

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::Variablevariable (const unsigned int c) const
Order variable_order (const unsigned int c) const
const FETypevariable_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, Realmax_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
DofObjectnode_ptr (MeshBase &mesh, unsigned int i) const
DofObjectelem_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.

Author:
Benjamin S. Kirk, 2002-2007

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

Destructor.

Definition at line 49 of file dof_map.C.

References clear().

00050 {
00051   this->clear();
00052 }


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 }

DofObject * DofMap::elem_ptr ( MeshBase mesh,
unsigned int  i 
) const [private]

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

00379   { libmesh_assert(proc < _end_df.size()); return _end_df[proc]; }

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]] $

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]

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 boundaryid is 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]

Returns the last dof index that is local to subdomain proc. This function is now deprecated, because it returns nonsense in the rare case where proc has no local dof indices. Use end_dof() instead.

Definition at line 371 of file dof_map.h.

References _end_df.

00372   { libmesh_deprecated(); libmesh_assert(proc < _end_df.size()); return (_end_df[proc] - 1); }  

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]

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

00358   { libmesh_assert(proc < _first_df.size()); return (_end_df[proc] - _first_df[proc]); }

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(); }

DofObject * DofMap::node_ptr ( MeshBase mesh,
unsigned int  i 
) const [private]

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 }

template<typename iterator_type >
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 }


Friends And Related Function Documentation

friend class SparsityPattern::Build [friend]

Definition at line 870 of file dof_map.h.


Member Data Documentation

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:

Site Created By: libMesh Developers
Last modified: November 25 2009 03:44:05.

Hosted By:
SourceForge.net Logo