libMesh::DofMap Class Reference

#include <dof_map.h>

Inheritance diagram for libMesh::DofMap:

List of all members.

Classes

class  AugmentSendList
class  AugmentSparsityPattern

Public Member Functions

 DofMap (const unsigned int sys_number)
 ~DofMap ()
void attach_matrix (SparseMatrix< Number > &matrix)
bool is_attached (SparseMatrix< Number > &matrix)
void distribute_dofs (MeshBase &)
void compute_sparsity (const MeshBase &)
void clear_sparsity ()
void attach_extra_sparsity_object (DofMap::AugmentSparsityPattern &asp)
void attach_extra_sparsity_function (void(*func)(SparsityPattern::Graph &sparsity, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *), void *context=NULL)
void attach_extra_send_list_object (DofMap::AugmentSendList &asl)
void attach_extra_send_list_function (void(*func)(std::vector< dof_id_type > &, void *), void *context=NULL)
void prepare_send_list ()
const std::vector< dof_id_type > & get_send_list () const
const std::vector< dof_id_type > & get_n_nz () const
const std::vector< dof_id_type > & get_n_oz () const
void add_variable_group (const VariableGroup &var_group)
const VariableGroupvariable_group (const unsigned int c) const
const Variablevariable (const unsigned int c) const
Order variable_order (const unsigned int c) const
Order variable_group_order (const unsigned int vg) const
const FETypevariable_type (const unsigned int c) const
const FETypevariable_group_type (const unsigned int vg) const
unsigned int n_variable_groups () const
unsigned int n_variables () const
dof_id_type n_dofs () const
dof_id_type n_SCALAR_dofs () const
dof_id_type n_local_dofs () const
dof_id_type n_dofs_on_processor (const processor_id_type proc) const
dof_id_type first_dof (const processor_id_type proc=libMesh::processor_id()) const
dof_id_type first_old_dof (const processor_id_type proc=libMesh::processor_id()) const
dof_id_type last_dof (const processor_id_type proc=libMesh::processor_id()) const
dof_id_type end_dof (const processor_id_type proc=libMesh::processor_id()) const
dof_id_type end_old_dof (const processor_id_type proc=libMesh::processor_id()) const
void dof_indices (const Elem *const elem, std::vector< dof_id_type > &di, const unsigned int vn=libMesh::invalid_uint) const
void SCALAR_dof_indices (std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
bool all_semilocal_indices (const std::vector< dof_id_type > &dof_indices) const
bool use_coupled_neighbor_dofs (const MeshBase &mesh) const
void extract_local_vector (const NumericVector< Number > &Ug, const std::vector< dof_id_type > &dof_indices, DenseVectorBase< Number > &Ue) const
dof_id_type n_constrained_dofs () const
dof_id_type n_local_constrained_dofs () const
dof_id_type n_constrained_nodes () const
void create_dof_constraints (const MeshBase &, Real time=0)
void allgather_recursive_constraints (MeshBase &)
void scatter_constraints (MeshBase &)
void process_constraints (MeshBase &)
void add_constraint_row (const dof_id_type dof_number, const DofConstraintRow &constraint_row, const Number constraint_rhs, const bool forbid_constraint_overwrite)
void add_constraint_row (const dof_id_type dof_number, const DofConstraintRow &constraint_row, const bool forbid_constraint_overwrite=true)
DofConstraints::const_iterator constraint_rows_begin () const
DofConstraints::const_iterator constraint_rows_end () const
NodeConstraints::const_iterator node_constraint_rows_begin () const
NodeConstraints::const_iterator node_constraint_rows_end () const
bool is_constrained_dof (const dof_id_type dof) const
bool is_constrained_node (const Node *node) const
void print_dof_constraints (std::ostream &os=libMesh::out, bool print_nonlocal=false) const
std::string get_local_constraints (bool print_nonlocal=false) const
std::pair< Real, Realmax_constraint_error (const System &system, NumericVector< Number > *v=NULL) const
void constrain_element_matrix (DenseMatrix< Number > &matrix, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
void constrain_element_matrix (DenseMatrix< Number > &matrix, std::vector< dof_id_type > &row_dofs, std::vector< dof_id_type > &col_dofs, bool asymmetric_constraint_rows=true) const
void constrain_element_vector (DenseVector< Number > &rhs, std::vector< dof_id_type > &dofs, bool asymmetric_constraint_rows=true) const
void constrain_element_matrix_and_vector (DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
void heterogenously_constrain_element_matrix_and_vector (DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
void constrain_element_dyad_matrix (DenseVector< Number > &v, DenseVector< Number > &w, std::vector< dof_id_type > &row_dofs, bool asymmetric_constraint_rows=true) const
void constrain_nothing (std::vector< dof_id_type > &dofs) const
void enforce_constraints_exactly (const System &system, NumericVector< Number > *v=NULL, bool homogeneous=false) const
void add_periodic_boundary (const PeriodicBoundaryBase &periodic_boundary)
void add_periodic_boundary (const PeriodicBoundaryBase &boundary, const PeriodicBoundaryBase &inverse_boundary)
bool is_periodic_boundary (const boundary_id_type boundaryid) const
PeriodicBoundariesget_periodic_boundaries ()
void add_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary)
void remove_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary)
DirichletBoundariesget_dirichlet_boundaries ()
void old_dof_indices (const Elem *const elem, std::vector< dof_id_type > &di, const unsigned int vn=libMesh::invalid_uint) const
dof_id_type n_old_dofs () const
void constrain_p_dofs (unsigned int var, const Elem *elem, unsigned int s, unsigned int p)
void reinit (MeshBase &mesh)
void clear ()
void print_info (std::ostream &os=libMesh::out) const
std::string get_info () const
unsigned int sys_number () const

Static Public Member Functions

static std::string get_info ()
static void print_info (std::ostream &out=libMesh::out)
static unsigned int n_objects ()
static void enable_print_counter_info ()
static void disable_print_counter_info ()

Public Attributes

CouplingMatrix_dof_coupling

Protected Types

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

Protected Member Functions

void increment_constructor_count (const std::string &name)
void increment_destructor_count (const std::string &name)

Static Protected Attributes

static Counts _counts
static Threads::atomic
< unsigned int > 
_n_objects
static Threads::spin_mutex _mutex
static bool _enable_print_counter = true

Private Types

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

Private Member Functions

AutoPtr< SparsityPattern::Buildbuild_sparsity (const MeshBase &mesh) const
void invalidate_dofs (MeshBase &mesh) const
DofObjectnode_ptr (MeshBase &mesh, dof_id_type i) const
DofObjectelem_ptr (MeshBase &mesh, dof_id_type i) const
template<typename iterator_type >
void set_nonlocal_dof_objects (iterator_type objects_begin, iterator_type objects_end, MeshBase &mesh, dofobject_accessor objects)
void distribute_local_dofs_var_major (dof_id_type &next_free_dof, MeshBase &mesh)
void distribute_local_dofs_node_major (dof_id_type &next_free_dof, MeshBase &mesh)
void add_neighbors_to_send_list (MeshBase &mesh)
void build_constraint_matrix (DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
void build_constraint_matrix_and_vector (DenseMatrix< Number > &C, DenseVector< Number > &H, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
void find_connected_dofs (std::vector< dof_id_type > &elem_dofs) const
void find_connected_dof_objects (std::vector< const DofObject * > &objs) const
void add_constraints_to_send_list ()

Private Attributes

std::vector< Variable_variables
std::vector< VariableGroup_variable_groups
const unsigned int _sys_number
std::vector< SparseMatrix
< Number > * > 
_matrices
std::vector< dof_id_type_first_df
std::vector< dof_id_type_end_df
std::vector< dof_id_type_send_list
AugmentSparsityPattern_augment_sparsity_pattern
void(* _extra_sparsity_function )(SparsityPattern::Graph &, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *)
void * _extra_sparsity_context
AugmentSendList_augment_send_list
void(* _extra_send_list_function )(std::vector< dof_id_type > &, void *)
void * _extra_send_list_context
bool need_full_sparsity_pattern
AutoPtr< SparsityPattern::Build_sp
std::vector< dof_id_type > * _n_nz
std::vector< dof_id_type > * _n_oz
dof_id_type _n_dfs
dof_id_type _n_SCALAR_dofs
dof_id_type _n_old_dfs
std::vector< dof_id_type_first_old_df
std::vector< dof_id_type_end_old_df
DofConstraints _dof_constraints
NodeConstraints _node_constraints
PeriodicBoundaries_periodic_boundaries
DirichletBoundaries_dirichlet_boundaries

Friends

class SparsityPattern::Build

Detailed Description

This class handles the numbering of degrees of freedom on a mesh. For systems of equations the class supports a fixed number of variables. The degrees of freedom are numbered such that sequential, contiguous blocks correspond to distinct subdomains. This is so that the resulting data structures will work well with parallel linear algebra packages.

Author:
Benjamin S. Kirk, 2002-2007

Definition at line 142 of file dof_map.h.


Member Typedef Documentation

typedef std::map<std::string, std::pair<unsigned int, unsigned int> > libMesh::ReferenceCounter::Counts [protected, inherited]

Data structure to log the information. The log is identified by the class name.

Definition at line 113 of file reference_counter.h.

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

A member function type like node_ptr or elem_ptr

Definition at line 902 of file dof_map.h.


Constructor & Destructor Documentation

libMesh::DofMap::DofMap ( const unsigned int  sys_number  )  [explicit]

Constructor. Requires the number of the system for which we will be numbering degrees of freedom.

Definition at line 128 of file dof_map.C.

References _matrices.

00128                                         :
00129   _dof_coupling(NULL),
00130   _variables(),
00131   _variable_groups(),
00132   _sys_number(number),
00133   _matrices(),
00134   _first_df(),
00135   _end_df(),
00136   _send_list(),
00137   _augment_sparsity_pattern(NULL),
00138   _extra_sparsity_function(NULL),
00139   _extra_sparsity_context(NULL),
00140   _augment_send_list(NULL),
00141   _extra_send_list_function(NULL),
00142   _extra_send_list_context(NULL),
00143   need_full_sparsity_pattern(false),
00144   _n_nz(NULL),
00145   _n_oz(NULL),
00146   _n_dfs(0),
00147   _n_SCALAR_dofs(0)
00148 #ifdef LIBMESH_ENABLE_AMR
00149   , _n_old_dfs(0),
00150   _first_old_df(),
00151   _end_old_df()
00152 #endif
00153 #ifdef LIBMESH_ENABLE_CONSTRAINTS
00154   , _dof_constraints()
00155 #endif
00156 #ifdef LIBMESH_ENABLE_PERIODIC
00157   , _periodic_boundaries(new PeriodicBoundaries)
00158 #endif
00159 #ifdef LIBMESH_ENABLE_DIRICHLET
00160   , _dirichlet_boundaries(new DirichletBoundaries)
00161 #endif
00162 {
00163   _matrices.clear();
00164 }

libMesh::DofMap::~DofMap (  ) 

Destructor.

Definition at line 169 of file dof_map.C.

References _dirichlet_boundaries, _periodic_boundaries, and clear().

00170 {
00171   this->clear();
00172 #ifdef LIBMESH_ENABLE_PERIODIC
00173   delete _periodic_boundaries;
00174 #endif
00175 #ifdef LIBMESH_ENABLE_DIRICHLET
00176   delete _dirichlet_boundaries;
00177 #endif
00178 }


Member Function Documentation

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

Adds a copy of the user-defined row to the constraint matrix, using a homogeneous right-hand-side for the constraint equation. By default, produces an error if the DOF was already constrained.

Definition at line 550 of file dof_map.h.

References add_constraint_row().

Referenced by add_constraint_row().

00553     { add_constraint_row(dof_number, constraint_row, 0., forbid_constraint_overwrite); }

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

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

Definition at line 980 of file dof_map_constraints.C.

References _dof_constraints, libMesh::err, and is_constrained_dof().

00984 {
00985   // Optionally allow the user to overwrite constraints.  Defaults to false.
00986   if (forbid_constraint_overwrite)
00987     if (this->is_constrained_dof(dof_number))
00988       {
00989         libMesh::err << "ERROR: DOF " << dof_number << " was already constrained!"
00990                       << std::endl;
00991         libmesh_error();
00992       }
00993 
00994   std::pair<dof_id_type, std::pair<DofConstraintRow,Number> > kv(dof_number, std::make_pair(constraint_row, constraint_rhs));
00995 
00996   _dof_constraints.insert(kv);
00997 }

void libMesh::DofMap::add_constraints_to_send_list (  )  [private]

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

Definition at line 2961 of file dof_map_constraints.C.

References _dof_constraints, _send_list, libMesh::CommWorld, end_dof(), first_dof(), libMesh::Parallel::Communicator::max(), and libMesh::n_processors().

Referenced by process_constraints().

02962 {
02963   // This function must be run on all processors at once
02964   parallel_only();
02965 
02966   // Return immediately if there's nothing to gather
02967   if (libMesh::n_processors() == 1)
02968     return;
02969 
02970   // We might get to return immediately if none of the processors
02971   // found any constraints
02972   unsigned int has_constraints = !_dof_constraints.empty();
02973   CommWorld.max(has_constraints);
02974   if (!has_constraints)
02975     return;
02976 
02977   for (DofConstraints::iterator i = _dof_constraints.begin();
02978          i != _dof_constraints.end(); ++i)
02979     {
02980       dof_id_type constrained_dof = i->first;
02981 
02982       // We only need the dependencies of our own constrained dofs
02983       if (constrained_dof < this->first_dof() ||
02984           constrained_dof >= this->end_dof())
02985         continue;
02986 
02987       DofConstraintRow& constraint_row = i->second.first;
02988       for (DofConstraintRow::const_iterator
02989            j=constraint_row.begin(); j != constraint_row.end();
02990            ++j)
02991         {
02992           dof_id_type constraint_dependency = j->first;
02993 
02994           // No point in adding one of our own dofs to the send_list
02995           if (constraint_dependency >= this->first_dof() &&
02996               constraint_dependency < this->end_dof())
02997             continue;
02998 
02999           _send_list.push_back(constraint_dependency);
03000         }
03001     }
03002 }

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

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

Definition at line 3076 of file dof_map_constraints.C.

References _dirichlet_boundaries.

03077 {
03078   _dirichlet_boundaries->push_back(new DirichletBoundary(dirichlet_boundary));
03079 }

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

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

Definition at line 1242 of file dof_map.C.

References _send_list, libMesh::Elem::active(), libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::Elem::active_family_tree_by_neighbor(), libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), dof_indices(), libMesh::DofObject::dof_number(), end_dof(), first_dof(), libMesh::Elem::get_node(), libMesh::MeshBase::max_node_id(), libMesh::DofObject::n_comp(), libMesh::Elem::n_neighbors(), libMesh::Elem::n_nodes(), libMesh::DofObject::n_vars(), n_vars, libMesh::Elem::neighbor(), libMesh::Elem::node(), libMesh::DofObject::processor_id(), libMesh::processor_id(), and sys_number().

Referenced by distribute_dofs().

01243 {
01244   START_LOG("add_neighbors_to_send_list()", "DofMap");
01245 
01246   const unsigned int sys_num = this->sys_number();
01247 
01248   //-------------------------------------------------------------------------
01249   // We need to add the DOFs from elements that live on neighboring processors
01250   // that are neighbors of the elements on the local processor
01251   //-------------------------------------------------------------------------
01252 
01253   MeshBase::const_element_iterator       local_elem_it
01254     = mesh.active_local_elements_begin();
01255   const MeshBase::const_element_iterator local_elem_end
01256     = mesh.active_local_elements_end();
01257 
01258   std::vector<bool> node_on_processor(mesh.max_node_id(), false);
01259   std::vector<dof_id_type> di;
01260   std::vector<const Elem *> family;
01261 
01262   // Loop over the active local elements, adding all active elements
01263   // that neighbor an active local element to the send list.
01264   for ( ; local_elem_it != local_elem_end; ++local_elem_it)
01265     {
01266       const Elem* elem = *local_elem_it;
01267 
01268       for (unsigned int n=0; n!=elem->n_nodes(); n++)
01269         {
01270           // Flag all the nodes of active local elements as seen, so
01271           // we can add nodal neighbor dofs to the send_list later.
01272           node_on_processor[elem->node(n)] = true;
01273 
01274           // Add all remote dofs on these nodes to the send_list.
01275           // This is necessary in case those dofs are *not* also dofs
01276           // on neighbors; e.g. in the case of a HIERARCHIC's local
01277           // side which is only a vertex on the neighbor that owns it.
01278           const Node* node = elem->get_node(n);
01279           const unsigned n_vars = node->n_vars(sys_num);
01280           for (unsigned int v=0; v != n_vars; ++v)
01281             {
01282               const unsigned int n_comp = node->n_comp(sys_num, v);
01283               for (unsigned int c=0; c != n_comp; ++c)
01284                 {
01285                   const dof_id_type dof_index = node->dof_number(sys_num, v, c);
01286                   if (dof_index < this->first_dof() || dof_index >= this->end_dof())
01287                     {
01288                       _send_list.push_back(dof_index);
01289                       // libmesh_here();
01290                       // std::cout << "sys_num,v,c,dof_index="
01291                       //                << sys_num << ", "
01292                       //                << v << ", "
01293                       //                << c << ", "
01294                       //                << dof_index << '\n';
01295                       // node->debug_buffer();
01296                     }
01297                 }
01298             }
01299         }
01300 
01301       // Loop over the neighbors of those elements
01302       for (unsigned int s=0; s<elem->n_neighbors(); s++)
01303         if (elem->neighbor(s) != NULL)
01304           {
01305             family.clear();
01306 
01307             // Find all the active elements that neighbor elem
01308 #ifdef LIBMESH_ENABLE_AMR
01309             if (!elem->neighbor(s)->active())
01310               elem->neighbor(s)->active_family_tree_by_neighbor(family, elem);
01311             else
01312 #endif
01313               family.push_back(elem->neighbor(s));
01314 
01315             for (dof_id_type i=0; i!=family.size(); ++i)
01316               // If the neighbor lives on a different processor
01317               if (family[i]->processor_id() != libMesh::processor_id())
01318                 {
01319                   // Get the DOF indices for this neighboring element
01320                   this->dof_indices (family[i], di);
01321 
01322                   // Insert the remote DOF indices into the send list
01323                   for (std::size_t j=0; j != di.size(); ++j)
01324                     if (di[j] < this->first_dof() ||
01325                         di[j] >= this->end_dof())
01326                       _send_list.push_back(di[j]);
01327                 }
01328           }
01329     }
01330 
01331   // Now loop over all non_local active elements and add any missing
01332   // nodal-only neighbors.  This will also get any dofs from nonlocal
01333   // nodes on local elements, because every nonlocal node exists on a
01334   // nonlocal nodal neighbor element.
01335   MeshBase::const_element_iterator       elem_it
01336     = mesh.active_elements_begin();
01337   const MeshBase::const_element_iterator elem_end
01338     = mesh.active_elements_end();
01339 
01340   for ( ; elem_it != elem_end; ++elem_it)
01341     {
01342       const Elem* elem = *elem_it;
01343 
01344       // If this is one of our elements, we've already added it
01345       if (elem->processor_id() == libMesh::processor_id())
01346         continue;
01347 
01348       // Do we need to add the element DOFs?
01349       bool add_elem_dofs = false;
01350 
01351       // Check all the nodes of the element to see if it
01352       // shares a node with us
01353       for (unsigned int n=0; n!=elem->n_nodes(); n++)
01354         if (node_on_processor[elem->node(n)])
01355           add_elem_dofs = true;
01356 
01357       // Add the element degrees of freedom if it shares at
01358       // least one node.
01359       if (add_elem_dofs)
01360         {
01361           // Get the DOF indices for this neighboring element
01362           this->dof_indices (elem, di);
01363 
01364           // Insert the remote DOF indices into the send list
01365             for (std::size_t j=0; j != di.size(); ++j)
01366               if (di[j] < this->first_dof() ||
01367                   di[j] >= this->end_dof())
01368                 _send_list.push_back(di[j]);
01369         }
01370     }
01371 
01372   STOP_LOG("add_neighbors_to_send_list()", "DofMap");
01373 }

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

Add a periodic boundary pair

Parameters:
boundary - primary boundary
inverse_boundary - inverse boundary

Definition at line 3144 of file dof_map_constraints.C.

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

03145 {
03146   libmesh_assert_equal_to (boundary.myboundary, inverse_boundary.pairedboundary);
03147   libmesh_assert_equal_to (boundary.pairedboundary, inverse_boundary.myboundary);
03148 
03149   // Allocate copies on the heap.  The _periodic_boundaries object will manage this memory.
03150   // Note: this also means that the copy constructor for the PeriodicBoundary (or user class
03151   // derived therefrom) must be implemented!
03152   // PeriodicBoundary* p_boundary = new PeriodicBoundary(boundary);
03153   // PeriodicBoundary* p_inverse_boundary = new PeriodicBoundary(inverse_boundary);
03154 
03155   // We can't use normal copy construction since this leads to slicing with derived classes.
03156   // Use clone() "virtual constructor" instead.  But, this *requires* user to override the clone()
03157   // method.  Note also that clone() allocates memory.  In this case, the _periodic_boundaries object
03158   // takes responsibility for cleanup.
03159   PeriodicBoundaryBase* p_boundary = boundary.clone().release();
03160   PeriodicBoundaryBase* p_inverse_boundary = inverse_boundary.clone().release();
03161 
03162   // Add the periodic boundary and its inverse to the PeriodicBoundaries data structure.  The 
03163   // PeriodicBoundaries data structure takes ownership of the pointers.
03164   _periodic_boundaries->insert(std::make_pair(p_boundary->myboundary, p_boundary));
03165   _periodic_boundaries->insert(std::make_pair(p_inverse_boundary->myboundary, p_inverse_boundary));
03166 }

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

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

Definition at line 3114 of file dof_map_constraints.C.

References _periodic_boundaries, libMesh::PeriodicBoundaries::boundary(), libMesh::PeriodicBoundaryBase::clone(), libMesh::PeriodicBoundaryBase::INVERSE, libMesh::PeriodicBoundaryBase::merge(), libMesh::PeriodicBoundaryBase::myboundary, and libMesh::PeriodicBoundaryBase::pairedboundary.

03115 {
03116   // See if we already have a periodic boundary associated myboundary...
03117   PeriodicBoundaryBase* existing_boundary = _periodic_boundaries->boundary(periodic_boundary.myboundary);
03118 
03119   if ( existing_boundary == NULL )
03120   {
03121     // ...if not, clone the input (and its inverse) and add them to the PeriodicBoundaries object
03122     PeriodicBoundaryBase* boundary = periodic_boundary.clone().release();
03123     PeriodicBoundaryBase* inverse_boundary = periodic_boundary.clone(PeriodicBoundaryBase::INVERSE).release();
03124 
03125     // _periodic_boundaries takes ownership of the pointers
03126     _periodic_boundaries->insert(std::make_pair(boundary->myboundary, boundary));
03127     _periodic_boundaries->insert(std::make_pair(inverse_boundary->myboundary, inverse_boundary));
03128   }
03129   else
03130   {
03131     // ...otherwise, merge this object's variable IDs with the existing boundary object's.
03132     existing_boundary->merge(periodic_boundary);
03133     
03134     // Do the same merging process for the inverse boundary.  Note: the inverse better already exist!
03135     PeriodicBoundaryBase* inverse_boundary = _periodic_boundaries->boundary(periodic_boundary.pairedboundary);
03136     libmesh_assert(inverse_boundary);
03137     inverse_boundary->merge(periodic_boundary);
03138   }
03139 }

void libMesh::DofMap::add_variable_group ( const VariableGroup var_group  ) 

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

Definition at line 203 of file dof_map.C.

References _variable_groups, _variables, and libMesh::VariableGroup::n_variables().

00204 {
00205   _variable_groups.push_back(var_group);
00206 
00207   VariableGroup &new_var_group = _variable_groups.back();
00208   
00209   for (unsigned int var=0; var<new_var_group.n_variables(); var++)    
00210     _variables.push_back (new_var_group(var));
00211 }

bool libMesh::DofMap::all_semilocal_indices ( const std::vector< dof_id_type > &  dof_indices  )  const

Returns true iff all degree of freedom indices in dof_indices are either local indices or in the send_list. Note that this is an O(logN) operation, not O(1); we don't cache enough information for O(1) right now.

Definition at line 1812 of file dof_map.C.

References _send_list, end_dof(), and first_dof().

01813 {
01814   // We're all semilocal unless we find a counterexample
01815   for (std::size_t i=0; i != dof_indices_in.size(); ++i)
01816     {
01817       const dof_id_type di = dof_indices_in[i];
01818       // If it's not in the local indices
01819       if (di < this->first_dof() ||
01820           di >= this->end_dof())
01821         {
01822           // and if it's not in the ghost indices, then we're not
01823           // semilocal
01824           if (!std::binary_search(_send_list.begin(), _send_list.end(), di))
01825             return false;
01826         }
01827     }
01828 
01829   return true;
01830 }

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

Gathers constraint equation dependencies from other processors

Definition at line 1971 of file dof_map_constraints.C.

References _dof_constraints, _end_df, _node_constraints, libMesh::MeshBase::active_not_local_elements_begin(), libMesh::MeshBase::active_not_local_elements_end(), libMesh::CommWorld, dof_indices(), end, end_dof(), first_dof(), libMesh::Elem::get_node(), libMesh::DofObject::id(), is_constrained_dof(), is_constrained_node(), libMesh::Parallel::Communicator::max(), libMesh::Elem::n_nodes(), libMesh::n_processors(), libMesh::Elem::node(), libMesh::MeshBase::node_ptr(), libMesh::processor_id(), libMesh::DofObject::processor_id(), libMesh::Parallel::Communicator::send_receive(), and libMesh::Parallel::Communicator::send_receive_packed_range().

Referenced by process_constraints().

01972 {
01973   // This function must be run on all processors at once
01974   parallel_only();
01975 
01976   // Return immediately if there's nothing to gather
01977   if (libMesh::n_processors() == 1)
01978     return;
01979 
01980   // We might get to return immediately if none of the processors
01981   // found any constraints
01982   unsigned int has_constraints = !_dof_constraints.empty()
01983 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
01984                                  || !_node_constraints.empty()
01985 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
01986                                  ;
01987   CommWorld.max(has_constraints);
01988   if (!has_constraints)
01989     return;
01990 
01991   // We might have calculated constraints for constrained dofs
01992   // which have support on other processors.
01993   // Push these out first.
01994   {
01995   std::vector<std::set<dof_id_type> > pushed_ids(libMesh::n_processors());
01996 
01997 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
01998   std::vector<std::set<dof_id_type> > pushed_node_ids(libMesh::n_processors());
01999 #endif
02000 
02001   MeshBase::element_iterator
02002     foreign_elem_it  = mesh.active_not_local_elements_begin(),
02003     foreign_elem_end = mesh.active_not_local_elements_end();
02004 
02005   // Collect the constraints to push to each processor
02006   for (; foreign_elem_it != foreign_elem_end; ++foreign_elem_it)
02007     {
02008       Elem *elem = *foreign_elem_it;
02009 
02010       std::vector<dof_id_type> my_dof_indices;
02011       this->dof_indices (elem, my_dof_indices);
02012 
02013       for (unsigned int i=0; i != my_dof_indices.size(); ++i)
02014         if (this->is_constrained_dof(my_dof_indices[i]))
02015           pushed_ids[elem->processor_id()].insert(my_dof_indices[i]);
02016 
02017 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02018       for (unsigned int n=0; n != elem->n_nodes(); ++n)
02019         if (this->is_constrained_node(elem->get_node(n)))
02020           pushed_node_ids[elem->processor_id()].insert(elem->node(n));
02021 #endif
02022     }
02023 
02024   // Now trade constraint rows
02025   for (processor_id_type p = 0; p != libMesh::n_processors(); ++p)
02026     {
02027       // Push to processor procup while receiving from procdown
02028       processor_id_type procup = (libMesh::processor_id() + p) %
02029                                   libMesh::n_processors();
02030       processor_id_type procdown = (libMesh::n_processors() +
02031                                     libMesh::processor_id() - p) %
02032                                     libMesh::n_processors();
02033 
02034       // Pack the dof constraint rows and rhs's to push to procup
02035       const std::size_t pushed_ids_size = pushed_ids[procup].size();
02036       std::vector<std::vector<dof_id_type> > pushed_keys(pushed_ids_size);
02037       std::vector<std::vector<Real> > pushed_vals(pushed_ids_size);
02038       std::vector<Number> pushed_rhss(pushed_ids_size);
02039       std::set<dof_id_type>::const_iterator it = pushed_ids[procup].begin();
02040       for (std::size_t i = 0; it != pushed_ids[procup].end();
02041            ++i, ++it)
02042         {
02043           const dof_id_type pushed_id = *it;
02044           DofConstraintRow &row = _dof_constraints[pushed_id].first;
02045           std::size_t row_size = row.size();
02046           pushed_keys[i].reserve(row_size);
02047           pushed_vals[i].reserve(row_size);
02048           for (DofConstraintRow::iterator j = row.begin();
02049                j != row.end(); ++j)
02050             {
02051               pushed_keys[i].push_back(j->first);
02052               pushed_vals[i].push_back(j->second);
02053             }
02054           pushed_rhss[i] = _dof_constraints[pushed_id].second;
02055         }
02056 
02057 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02058       // Pack the node constraint rows to push to procup
02059       const std::size_t pushed_nodes_size = pushed_node_ids[procup].size();
02060       std::vector<std::vector<dof_id_type> > pushed_node_keys(pushed_nodes_size);
02061       std::vector<std::vector<Real> > pushed_node_vals(pushed_nodes_size);
02062       std::vector<Point> pushed_node_offsets(pushed_nodes_size);
02063       std::set<dof_id_type>::const_iterator node_it = pushed_node_ids[procup].begin();
02064       for (std::size_t i = 0; node_it != pushed_node_ids[procup].end();
02065            ++i, ++node_it)
02066         {
02067           const Node *node = mesh.node_ptr(*node_it);
02068           NodeConstraintRow &row = _node_constraints[node].first;
02069           std::size_t row_size = row.size();
02070           pushed_node_keys[i].reserve(row_size);
02071           pushed_node_vals[i].reserve(row_size);
02072           for (NodeConstraintRow::iterator j = row.begin();
02073                j != row.end(); ++j)
02074             {
02075               pushed_node_keys[i].push_back(j->first->id());
02076               pushed_node_vals[i].push_back(j->second);
02077             }
02078           pushed_node_offsets[i] = _node_constraints[node].second;
02079         }
02080 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02081 
02082       // Trade pushed dof constraint rows
02083       std::vector<dof_id_type> pushed_ids_from_me
02084         (pushed_ids[procup].begin(), pushed_ids[procup].end());
02085       std::vector<dof_id_type> pushed_ids_to_me;
02086       std::vector<std::vector<dof_id_type> > pushed_keys_to_me;
02087       std::vector<std::vector<Real> > pushed_vals_to_me;
02088       std::vector<Number> pushed_rhss_to_me;
02089       CommWorld.send_receive(procup, pushed_ids_from_me,
02090                              procdown, pushed_ids_to_me);
02091       CommWorld.send_receive(procup, pushed_keys,
02092                              procdown, pushed_keys_to_me);
02093       CommWorld.send_receive(procup, pushed_vals,
02094                              procdown, pushed_vals_to_me);
02095       CommWorld.send_receive(procup, pushed_rhss,
02096                              procdown, pushed_rhss_to_me);
02097       libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_keys_to_me.size());
02098       libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_vals_to_me.size());
02099       libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_rhss_to_me.size());
02100 
02101 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02102       // Trade pushed node constraint rows
02103       std::vector<dof_id_type> pushed_node_ids_from_me
02104         (pushed_node_ids[procup].begin(), pushed_node_ids[procup].end());
02105       std::vector<dof_id_type> pushed_node_ids_to_me;
02106       std::vector<std::vector<dof_id_type> > pushed_node_keys_to_me;
02107       std::vector<std::vector<Real> > pushed_node_vals_to_me;
02108       std::vector<Point> pushed_node_offsets_to_me;
02109       CommWorld.send_receive(procup, pushed_node_ids_from_me,
02110                              procdown, pushed_node_ids_to_me);
02111       CommWorld.send_receive(procup, pushed_node_keys,
02112                              procdown, pushed_node_keys_to_me);
02113       CommWorld.send_receive(procup, pushed_node_vals,
02114                              procdown, pushed_node_vals_to_me);
02115       CommWorld.send_receive(procup, pushed_node_offsets,
02116                              procdown, pushed_node_offsets_to_me);
02117 
02118       // Note that we aren't doing a send_receive on the Nodes
02119       // themselves.  At this point we should only be pushing out
02120       // "raw" constraints, and there should be no
02121       // constrained-by-constrained-by-etc. situations that could
02122       // involve non-semilocal nodes.
02123 
02124       libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_keys_to_me.size());
02125       libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_vals_to_me.size());
02126       libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_offsets_to_me.size());
02127 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02128 
02129       // Add the dof constraints that I've been sent
02130       for (std::size_t i = 0; i != pushed_ids_to_me.size(); ++i)
02131         {
02132           libmesh_assert_equal_to (pushed_keys_to_me[i].size(), pushed_vals_to_me[i].size());
02133 
02134           dof_id_type constrained = pushed_ids_to_me[i];
02135 
02136           // If we don't already have a constraint for this dof,
02137           // add the one we were sent
02138           if (!this->is_constrained_dof(constrained))
02139             {
02140               DofConstraintRow &row = _dof_constraints[constrained].first;
02141               for (std::size_t j = 0; j != pushed_keys_to_me[i].size(); ++j)
02142                 {
02143                   row[pushed_keys_to_me[i][j]] = pushed_vals_to_me[i][j];
02144                 }
02145               _dof_constraints[constrained].second = pushed_rhss_to_me[i];
02146             }
02147         }
02148 
02149 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02150       // Add the node constraints that I've been sent
02151       for (std::size_t i = 0; i != pushed_node_ids_to_me.size(); ++i)
02152         {
02153           libmesh_assert_equal_to (pushed_node_keys_to_me[i].size(), pushed_node_vals_to_me[i].size());
02154 
02155           dof_id_type constrained_id = pushed_node_ids_to_me[i];
02156 
02157           // If we don't already have a constraint for this node,
02158           // add the one we were sent
02159           const Node *constrained = mesh.node_ptr(constrained_id);
02160           if (!this->is_constrained_node(constrained))
02161             {
02162               NodeConstraintRow &row = _node_constraints[constrained].first;
02163               for (std::size_t j = 0; j != pushed_node_keys_to_me[i].size(); ++j)
02164                 {
02165                   const Node *key_node = mesh.node_ptr(pushed_node_keys_to_me[i][j]);
02166                   libmesh_assert(key_node);
02167                   row[key_node] = pushed_node_vals_to_me[i][j];
02168                 }
02169               _node_constraints[constrained].second = pushed_node_offsets_to_me[i];
02170             }
02171         }
02172 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02173     }
02174   }
02175 
02176   // Now start checking for any other constraints we need
02177   // to know about, requesting them recursively.
02178 
02179   // Create sets containing the DOFs and nodes we already depend on
02180   typedef std::set<dof_id_type> DoF_RCSet;
02181   DoF_RCSet unexpanded_dofs;
02182 
02183   for (DofConstraints::iterator i = _dof_constraints.begin();
02184          i != _dof_constraints.end(); ++i)
02185     {
02186       unexpanded_dofs.insert(i->first);
02187     }
02188 
02189   typedef std::set<const Node *> Node_RCSet;
02190   Node_RCSet unexpanded_nodes;
02191 
02192 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02193   for (NodeConstraints::iterator i = _node_constraints.begin();
02194          i != _node_constraints.end(); ++i)
02195     {
02196       unexpanded_nodes.insert(i->first);
02197     }
02198 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02199 
02200   // We have to keep recursing while the unexpanded set is
02201   // nonempty on *any* processor
02202   bool unexpanded_set_nonempty = !unexpanded_dofs.empty() ||
02203                                  !unexpanded_nodes.empty();
02204   CommWorld.max(unexpanded_set_nonempty);
02205 
02206   while (unexpanded_set_nonempty)
02207     {
02208       // Let's make sure we don't lose sync in this loop.
02209       parallel_only();
02210 
02211       // Request sets
02212       DoF_RCSet   dof_request_set;
02213       Node_RCSet node_request_set;
02214 
02215       // Request sets to send to each processor
02216       std::vector<std::vector<dof_id_type> >
02217         requested_dof_ids(libMesh::n_processors()),
02218         requested_node_ids(libMesh::n_processors());
02219 
02220       // And the sizes of each
02221       std::vector<dof_id_type>
02222         dof_ids_on_proc(libMesh::n_processors(), 0),
02223         node_ids_on_proc(libMesh::n_processors(), 0);
02224 
02225       // Fill (and thereby sort and uniq!) the main request sets
02226       for (DoF_RCSet::iterator i = unexpanded_dofs.begin();
02227            i != unexpanded_dofs.end(); ++i)
02228         {
02229           DofConstraintRow &row = _dof_constraints[*i].first;
02230           for (DofConstraintRow::iterator j = row.begin();
02231                j != row.end(); ++j)
02232             {
02233               const dof_id_type constraining_dof = j->first;
02234 
02235               // If it's non-local and we haven't already got a
02236               // constraint for it, we might need to ask for one
02237               if (((constraining_dof < this->first_dof()) ||
02238                    (constraining_dof >= this->end_dof())) &&
02239                   !_dof_constraints.count(constraining_dof))
02240                 dof_request_set.insert(constraining_dof);
02241             }
02242         }
02243 
02244 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02245       for (Node_RCSet::iterator i = unexpanded_nodes.begin();
02246            i != unexpanded_nodes.end(); ++i)
02247         {
02248           NodeConstraintRow &row = _node_constraints[*i].first;
02249           for (NodeConstraintRow::iterator j = row.begin();
02250                j != row.end(); ++j)
02251             {
02252               const Node* const node = j->first;
02253               libmesh_assert(node);
02254 
02255               // If it's non-local and we haven't already got a
02256               // constraint for it, we might need to ask for one
02257               if ((node->processor_id() != libMesh::processor_id()) &&
02258                   !_node_constraints.count(node))
02259                 node_request_set.insert(node);
02260             }
02261         }
02262 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02263 
02264       // Clear the unexpanded constraint sets; we're about to expand
02265       // them
02266       unexpanded_dofs.clear();
02267       unexpanded_nodes.clear();
02268 
02269       // Count requests by processor
02270       processor_id_type proc_id = 0;
02271       for (DoF_RCSet::iterator i = dof_request_set.begin();
02272            i != dof_request_set.end(); ++i)
02273         {
02274           while (*i >= _end_df[proc_id])
02275             proc_id++;
02276           dof_ids_on_proc[proc_id]++;
02277         }
02278 
02279       for (Node_RCSet::iterator i = node_request_set.begin();
02280            i != node_request_set.end(); ++i)
02281         {
02282           libmesh_assert(*i);
02283           libmesh_assert_less ((*i)->processor_id(), libMesh::n_processors());
02284           node_ids_on_proc[(*i)->processor_id()]++;
02285         }
02286 
02287       for (processor_id_type p = 0; p != libMesh::n_processors(); ++p)
02288         {
02289           requested_dof_ids[p].reserve(dof_ids_on_proc[p]);
02290           requested_node_ids[p].reserve(node_ids_on_proc[p]);
02291         }
02292 
02293       // Prepare each processor's request set
02294       proc_id = 0;
02295       for (DoF_RCSet::iterator i = dof_request_set.begin();
02296            i != dof_request_set.end(); ++i)
02297         {
02298           while (*i >= _end_df[proc_id])
02299             proc_id++;
02300           requested_dof_ids[proc_id].push_back(*i);
02301         }
02302 
02303       for (Node_RCSet::iterator i = node_request_set.begin();
02304            i != node_request_set.end(); ++i)
02305         {
02306           requested_node_ids[(*i)->processor_id()].push_back((*i)->id());
02307         }
02308 
02309       // Now request constraint rows from other processors
02310       for (processor_id_type p=1; p != libMesh::n_processors(); ++p)
02311         {
02312           // Trade my requests with processor procup and procdown
02313           processor_id_type procup = (libMesh::processor_id() + p) %
02314                                       libMesh::n_processors();
02315           processor_id_type procdown = (libMesh::n_processors() +
02316                                         libMesh::processor_id() - p) %
02317                                         libMesh::n_processors();
02318           std::vector<dof_id_type> dof_request_to_fill,
02319                                    node_request_to_fill;
02320           CommWorld.send_receive(procup, requested_dof_ids[procup],
02321                                  procdown, dof_request_to_fill);
02322           CommWorld.send_receive(procup, requested_node_ids[procup],
02323                                  procdown, node_request_to_fill);
02324 
02325           // Fill those requests
02326           std::vector<std::vector<dof_id_type> > dof_row_keys(dof_request_to_fill.size()),
02327                                                  node_row_keys(node_request_to_fill.size());
02328 
02329           // FIXME - this could be an unordered set, given a
02330           // hash<pointers> specialization
02331           std::set<const Node*> nodes_requested;
02332 
02333           std::vector<std::vector<Real> > dof_row_vals(dof_request_to_fill.size()),
02334                                           node_row_vals(node_request_to_fill.size());
02335           std::vector<Number> dof_row_rhss(dof_request_to_fill.size());
02336           std::vector<Point>  node_row_rhss(node_request_to_fill.size());
02337           for (std::size_t i=0; i != dof_request_to_fill.size(); ++i)
02338             {
02339               dof_id_type constrained = dof_request_to_fill[i];
02340               if (_dof_constraints.count(constrained))
02341                 {
02342                   DofConstraintRow &row = _dof_constraints[constrained].first;
02343                   std::size_t row_size = row.size();
02344                   dof_row_keys[i].reserve(row_size);
02345                   dof_row_vals[i].reserve(row_size);
02346                   for (DofConstraintRow::iterator j = row.begin();
02347                        j != row.end(); ++j)
02348                     {
02349                       dof_row_keys[i].push_back(j->first);
02350                       dof_row_vals[i].push_back(j->second);
02351 
02352                       // We should never have a 0 constraint
02353                       // coefficient; that's implicit via sparse
02354                       // constraint storage
02355                       libmesh_assert(j->second);
02356                     }
02357                   dof_row_rhss[i] = _dof_constraints[constrained].second;
02358                 }
02359             }
02360 
02361 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02362           for (std::size_t i=0; i != node_request_to_fill.size(); ++i)
02363             {
02364               dof_id_type constrained_id = node_request_to_fill[i];
02365               const Node *constrained_node = mesh.node_ptr(constrained_id);
02366               if (_node_constraints.count(constrained_node))
02367                 {
02368                   const NodeConstraintRow &row = _node_constraints[constrained_node].first;
02369                   std::size_t row_size = row.size();
02370                   node_row_keys[i].reserve(row_size);
02371                   node_row_vals[i].reserve(row_size);
02372                   for (NodeConstraintRow::const_iterator j = row.begin();
02373                        j != row.end(); ++j)
02374                     {
02375                       const Node* node = j->first;
02376                       node_row_keys[i].push_back(node->id());
02377                       node_row_vals[i].push_back(j->second);
02378 
02379                       // If we're not sure whether our send
02380                       // destination already has this node, let's give
02381                       // it a copy.
02382                       if (node->processor_id() != procdown)
02383                         nodes_requested.insert(node);
02384 
02385                       // We can have 0 nodal constraint
02386                       // coefficients, where no Lagrange constrant
02387                       // exists but non-Lagrange basis constraints
02388                       // might.
02389                       // libmesh_assert(j->second);
02390                     }
02391                   node_row_rhss[i] = _node_constraints[constrained_node].second;
02392                 }
02393             }
02394 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02395 
02396           // Trade back the results
02397           std::vector<std::vector<dof_id_type> > dof_filled_keys,
02398                                                  node_filled_keys;
02399           std::vector<std::vector<Real> > dof_filled_vals,
02400                                           node_filled_vals;
02401           std::vector<Number> dof_filled_rhss;
02402           std::vector<Point> node_filled_rhss;
02403           CommWorld.send_receive(procdown, dof_row_keys,
02404                                  procup, dof_filled_keys);
02405           CommWorld.send_receive(procdown, dof_row_vals,
02406                                  procup, dof_filled_vals);
02407           CommWorld.send_receive(procdown, dof_row_rhss,
02408                                  procup, dof_filled_rhss);
02409 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02410           CommWorld.send_receive(procdown, node_row_keys,
02411                                  procup, node_filled_keys);
02412           CommWorld.send_receive(procdown, node_row_vals,
02413                                  procup, node_filled_vals);
02414           CommWorld.send_receive(procdown, node_row_rhss,
02415                                  procup, node_filled_rhss);
02416 
02417           // Constraining nodes might not even exist on our subset of
02418           // a distributed mesh, so let's make them exist.
02419           CommWorld.send_receive_packed_range
02420             (procdown, &mesh, nodes_requested.begin(), nodes_requested.end(),
02421              procup,   &mesh, mesh_inserter_iterator<Node>(mesh));
02422 
02423 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02424           libmesh_assert_equal_to (dof_filled_keys.size(), requested_dof_ids[procup].size());
02425           libmesh_assert_equal_to (dof_filled_vals.size(), requested_dof_ids[procup].size());
02426           libmesh_assert_equal_to (dof_filled_rhss.size(), requested_dof_ids[procup].size());
02427           libmesh_assert_equal_to (node_filled_keys.size(), requested_node_ids[procup].size());
02428           libmesh_assert_equal_to (node_filled_vals.size(), requested_node_ids[procup].size());
02429           libmesh_assert_equal_to (node_filled_rhss.size(), requested_node_ids[procup].size());
02430 
02431           // Add any new constraint rows we've found
02432           for (std::size_t i=0; i != requested_dof_ids[procup].size(); ++i)
02433             {
02434               libmesh_assert_equal_to (dof_filled_keys[i].size(), dof_filled_vals[i].size());
02435               // FIXME - what about empty p constraints!?
02436               if (!dof_filled_keys[i].empty())
02437                 {
02438                   dof_id_type constrained = requested_dof_ids[procup][i];
02439                   DofConstraintRow &row = _dof_constraints[constrained].first;
02440                   for (std::size_t j = 0; j != dof_filled_keys[i].size(); ++j)
02441                     row[dof_filled_keys[i][j]] = dof_filled_vals[i][j];
02442                   _dof_constraints[constrained].second = dof_filled_rhss[i];
02443 
02444                   // And prepare to check for more recursive constraints
02445                   unexpanded_dofs.insert(constrained);
02446                 }
02447             }
02448 
02449 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02450           for (std::size_t i=0; i != requested_node_ids[procup].size(); ++i)
02451             {
02452               libmesh_assert_equal_to (node_filled_keys[i].size(), node_filled_vals[i].size());
02453               if (!node_filled_keys[i].empty())
02454                 {
02455                   dof_id_type constrained_id = requested_node_ids[procup][i];
02456                   const Node* constrained_node = mesh.node_ptr(constrained_id);
02457                   NodeConstraintRow &row = _node_constraints[constrained_node].first;
02458                   for (std::size_t j = 0; j != node_filled_keys[i].size(); ++j)
02459                     {
02460                       const Node* key_node =
02461                         mesh.node_ptr(node_filled_keys[i][j]);
02462                       libmesh_assert(key_node);
02463                       row[key_node] = node_filled_vals[i][j];
02464                     }
02465                   _node_constraints[constrained_node].second = node_filled_rhss[i];
02466 
02467                   // And prepare to check for more recursive constraints
02468                   unexpanded_nodes.insert(constrained_node);
02469                 }
02470             }
02471 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02472         }
02473 
02474       // We have to keep recursing while the unexpanded set is
02475       // nonempty on *any* processor
02476       unexpanded_set_nonempty = !unexpanded_dofs.empty() ||
02477                                 !unexpanded_nodes.empty();
02478       CommWorld.max(unexpanded_set_nonempty);
02479     }
02480 }

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

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

Definition at line 270 of file dof_map.h.

References _extra_send_list_context, and _extra_send_list_function.

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

Attach an object to populate the send_list with extra entries. This should only add to the send list, but no checking is done to enforce this behavior.

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

Definition at line 261 of file dof_map.h.

References _augment_send_list.

00262   {
00263     _augment_send_list = &asl;
00264   }

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

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

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

Further, you _must_ modify n_nz and n_oz properly!

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

Definition at line 247 of file dof_map.h.

References _extra_sparsity_context, and _extra_sparsity_function.

void libMesh::DofMap::attach_extra_sparsity_object ( DofMap::AugmentSparsityPattern asp  )  [inline]

Attach an object to use to populate the sparsity pattern with extra entries.

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

Further, you _must_ modify n_nz and n_oz properly!

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

Definition at line 232 of file dof_map.h.

References _augment_sparsity_pattern.

00233   {
00234     _augment_sparsity_pattern = &asp;
00235   }

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

Additional matrices may be handled with this DofMap. They are initialized to the same sparsity structure as the major matrix.

Definition at line 215 of file dof_map.C.

References _matrices, _n_nz, _n_oz, _sp, libMesh::SparseMatrix< T >::attach_dof_map(), libMesh::CommWorld, libMesh::AutoPtr< Tp >::get(), libMesh::Parallel::Communicator::max(), need_full_sparsity_pattern, libMesh::SparseMatrix< T >::need_full_sparsity_pattern(), and libMesh::SparseMatrix< T >::update_sparsity_pattern().

Referenced by libMesh::ImplicitSystem::init_matrices(), and libMesh::EigenSystem::init_matrices().

00216 {
00217   parallel_only();
00218 
00219   // We shouldn't be trying to re-attach the same matrices repeatedly
00220   libmesh_assert (std::find(_matrices.begin(), _matrices.end(),
00221                             &matrix) == _matrices.end());
00222 
00223   _matrices.push_back(&matrix);
00224 
00225   matrix.attach_dof_map (*this);
00226 
00227   // If we've already computed sparsity, then it's too late
00228   // to wait for "compute_sparsity" to help with sparse matrix
00229   // initialization, and we need to handle this matrix individually
00230   bool computed_sparsity_already =
00231     ((_n_nz && !_n_nz->empty()) ||
00232      (_n_oz && !_n_oz->empty()));
00233   CommWorld.max(computed_sparsity_already);
00234   if (computed_sparsity_already &&
00235       matrix.need_full_sparsity_pattern())
00236     {
00237       // We'd better have already computed the full sparsity pattern
00238       // if we need it here
00239       libmesh_assert(need_full_sparsity_pattern);
00240       libmesh_assert(_sp.get());
00241 
00242       matrix.update_sparsity_pattern (_sp->sparsity_pattern);
00243     }
00244       
00245   if (matrix.need_full_sparsity_pattern())
00246     need_full_sparsity_pattern = true;
00247 }

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

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

Definition at line 1721 of file dof_map_constraints.C.

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

Referenced by constrain_element_dyad_matrix(), constrain_element_matrix(), constrain_element_matrix_and_vector(), constrain_element_vector(), constrain_nothing(), and max_constraint_error().

01724 {
01725   if (!called_recursively) START_LOG("build_constraint_matrix()", "DofMap");
01726 
01727   // Create a set containing the DOFs we already depend on
01728   typedef std::set<dof_id_type> RCSet;
01729   RCSet dof_set;
01730 
01731   bool we_have_constraints = false;
01732 
01733   // Next insert any other dofs the current dofs might be constrained
01734   // in terms of.  Note that in this case we may not be done: Those
01735   // may in turn depend on others.  So, we need to repeat this process
01736   // in that case until the system depends only on unconstrained
01737   // degrees of freedom.
01738   for (unsigned int i=0; i<elem_dofs.size(); i++)
01739     if (this->is_constrained_dof(elem_dofs[i]))
01740       {
01741         we_have_constraints = true;
01742 
01743         // If the DOF is constrained
01744         DofConstraints::const_iterator
01745           pos = _dof_constraints.find(elem_dofs[i]);
01746 
01747         libmesh_assert (pos != _dof_constraints.end());
01748 
01749         const DofConstraintRow& constraint_row = pos->second.first;
01750 
01751 // Constraint rows in p refinement may be empty
01752 //      libmesh_assert (!constraint_row.empty());
01753 
01754         for (DofConstraintRow::const_iterator
01755                it=constraint_row.begin(); it != constraint_row.end();
01756              ++it)
01757           dof_set.insert (it->first);
01758       }
01759 
01760   // May be safe to return at this point
01761   // (but remember to stop the perflog)
01762   if (!we_have_constraints)
01763     {
01764       STOP_LOG("build_constraint_matrix()", "DofMap");
01765       return;
01766     }
01767 
01768   for (unsigned int i=0; i != elem_dofs.size(); ++i)
01769     dof_set.erase (elem_dofs[i]);
01770 
01771   // If we added any DOFS then we need to do this recursively.
01772   // It is possible that we just added a DOF that is also
01773   // constrained!
01774   //
01775   // Also, we need to handle the special case of an element having DOFs
01776   // constrained in terms of other, local DOFs
01777   if (!dof_set.empty() ||  // case 1: constrained in terms of other DOFs
01778       !called_recursively) // case 2: constrained in terms of our own DOFs
01779     {
01780       const unsigned int old_size =
01781         libmesh_cast_int<unsigned int>(elem_dofs.size());
01782 
01783       // Add new dependency dofs to the end of the current dof set
01784       elem_dofs.insert(elem_dofs.end(),
01785                        dof_set.begin(), dof_set.end());
01786 
01787       // Now we can build the constraint matrix.
01788       // Note that resize also zeros for a DenseMatrix<Number>.
01789       C.resize (old_size,
01790                 libmesh_cast_int<unsigned int>(elem_dofs.size()));
01791 
01792       // Create the C constraint matrix.
01793       for (unsigned int i=0; i != old_size; i++)
01794         if (this->is_constrained_dof(elem_dofs[i]))
01795           {
01796             // If the DOF is constrained
01797             DofConstraints::const_iterator
01798               pos = _dof_constraints.find(elem_dofs[i]);
01799 
01800             libmesh_assert (pos != _dof_constraints.end());
01801 
01802             const DofConstraintRow& constraint_row = pos->second.first;
01803 
01804 // p refinement creates empty constraint rows
01805 //          libmesh_assert (!constraint_row.empty());
01806 
01807             for (DofConstraintRow::const_iterator
01808                    it=constraint_row.begin(); it != constraint_row.end();
01809                  ++it)
01810               for (unsigned int j=0; j != elem_dofs.size(); j++)
01811                 if (elem_dofs[j] == it->first)
01812                   C(i,j) = it->second;
01813           }
01814         else
01815           {
01816             C(i,i) = 1.;
01817           }
01818 
01819       // May need to do this recursively.  It is possible
01820       // that we just replaced a constrained DOF with another
01821       // constrained DOF.
01822       DenseMatrix<Number> Cnew;
01823 
01824       this->build_constraint_matrix (Cnew, elem_dofs, true);
01825 
01826       if ((C.n() == Cnew.m()) &&
01827           (Cnew.n() == elem_dofs.size())) // If the constraint matrix
01828         C.right_multiply(Cnew);           // is constrained...
01829 
01830       libmesh_assert_equal_to (C.n(), elem_dofs.size());
01831     }
01832 
01833   if (!called_recursively) STOP_LOG("build_constraint_matrix()", "DofMap");
01834 }

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

Build the constraint matrix C and the forcing vector H associated with the element degree of freedom indices elem_dofs. The optional parameter called_recursively should be left at the default value false. This is used to handle the special case of an element's degrees of freedom being constrained in terms of other, local degrees of freedom. The usual case is for an elements DOFs to be constrained by some other, external DOFs and/or Dirichlet conditions.

Definition at line 1839 of file dof_map_constraints.C.

References libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::resize(), libMesh::DenseMatrix< T >::resize(), libMesh::DenseMatrix< T >::right_multiply(), and libMesh::DenseMatrix< T >::vector_mult_add().

Referenced by extract_local_vector().

01843 {
01844   if (!called_recursively)
01845     START_LOG("build_constraint_matrix_and_vector()", "DofMap");
01846 
01847   // Create a set containing the DOFs we already depend on
01848   typedef std::set<dof_id_type> RCSet;
01849   RCSet dof_set;
01850 
01851   bool we_have_constraints = false;
01852 
01853   // Next insert any other dofs the current dofs might be constrained
01854   // in terms of.  Note that in this case we may not be done: Those
01855   // may in turn depend on others.  So, we need to repeat this process
01856   // in that case until the system depends only on unconstrained
01857   // degrees of freedom.
01858   for (unsigned int i=0; i<elem_dofs.size(); i++)
01859     if (this->is_constrained_dof(elem_dofs[i]))
01860       {
01861         we_have_constraints = true;
01862 
01863         // If the DOF is constrained
01864         DofConstraints::const_iterator
01865           pos = _dof_constraints.find(elem_dofs[i]);
01866 
01867         libmesh_assert (pos != _dof_constraints.end());
01868 
01869         const DofConstraintRow& constraint_row = pos->second.first;
01870 
01871 // Constraint rows in p refinement may be empty
01872 //      libmesh_assert (!constraint_row.empty());
01873 
01874         for (DofConstraintRow::const_iterator
01875                it=constraint_row.begin(); it != constraint_row.end();
01876              ++it)
01877           dof_set.insert (it->first);
01878       }
01879 
01880   // May be safe to return at this point
01881   // (but remember to stop the perflog)
01882   if (!we_have_constraints)
01883     {
01884       STOP_LOG("build_constraint_matrix_and_vector()", "DofMap");
01885       return;
01886     }
01887 
01888   for (unsigned int i=0; i != elem_dofs.size(); ++i)
01889     dof_set.erase (elem_dofs[i]);
01890 
01891   // If we added any DOFS then we need to do this recursively.
01892   // It is possible that we just added a DOF that is also
01893   // constrained!
01894   //
01895   // Also, we need to handle the special case of an element having DOFs
01896   // constrained in terms of other, local DOFs
01897   if (!dof_set.empty() ||  // case 1: constrained in terms of other DOFs
01898       !called_recursively) // case 2: constrained in terms of our own DOFs
01899     {
01900       const unsigned int old_size =
01901         libmesh_cast_int<unsigned int>(elem_dofs.size());
01902 
01903       // Add new dependency dofs to the end of the current dof set
01904       elem_dofs.insert(elem_dofs.end(),
01905                        dof_set.begin(), dof_set.end());
01906 
01907       elem_dofs.insert(elem_dofs.end(),
01908                        dof_set.begin(), dof_set.end());
01909 
01910       // Now we can build the constraint matrix and vector.
01911       // Note that resize also zeros for a DenseMatrix and DenseVector
01912       C.resize (old_size,
01913                 libmesh_cast_int<unsigned int>(elem_dofs.size()));
01914       H.resize (old_size);
01915 
01916       // Create the C constraint matrix.
01917       for (unsigned int i=0; i != old_size; i++)
01918         if (this->is_constrained_dof(elem_dofs[i]))
01919           {
01920             // If the DOF is constrained
01921             DofConstraints::const_iterator
01922               pos = _dof_constraints.find(elem_dofs[i]);
01923 
01924             libmesh_assert (pos != _dof_constraints.end());
01925 
01926             const DofConstraintRow& constraint_row = pos->second.first;
01927 
01928 // p refinement creates empty constraint rows
01929 //          libmesh_assert (!constraint_row.empty());
01930 
01931             for (DofConstraintRow::const_iterator
01932                    it=constraint_row.begin(); it != constraint_row.end();
01933                  ++it)
01934               for (unsigned int j=0; j != elem_dofs.size(); j++)
01935                 if (elem_dofs[j] == it->first)
01936                   C(i,j) = it->second;
01937 
01938             H(i) = pos->second.second;
01939           }
01940         else
01941           {
01942             C(i,i) = 1.;
01943           }
01944 
01945       // May need to do this recursively.  It is possible
01946       // that we just replaced a constrained DOF with another
01947       // constrained DOF.
01948       DenseMatrix<Number> Cnew;
01949       DenseVector<Number> Hnew;
01950 
01951       this->build_constraint_matrix_and_vector (Cnew, Hnew, elem_dofs, true);
01952 
01953       if ((C.n() == Cnew.m()) &&          // If the constraint matrix
01954           (Cnew.n() == elem_dofs.size())) // is constrained...
01955         {
01956           C.right_multiply(Cnew);
01957 
01958           // If x = Cy + h and y = Dz + g
01959           // Then x = (CD)z + (Cg + h)
01960           C.vector_mult_add(H, 1, Hnew);
01961         }
01962 
01963       libmesh_assert_equal_to (C.n(), elem_dofs.size());
01964     }
01965 
01966   if (!called_recursively)
01967     STOP_LOG("build_constraint_matrix_and_vector()", "DofMap");
01968 }

AutoPtr< SparsityPattern::Build > libMesh::DofMap::build_sparsity ( const MeshBase mesh  )  const [private]

Builds a sparsity pattern

Definition at line 54 of file dof_map.C.

References libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::MeshBase::is_prepared(), libMesh::out, libMesh::Threads::parallel_reduce(), and libMesh::MeshBase::processor_id().

Referenced by compute_sparsity().

00055 {
00056   libmesh_assert (mesh.is_prepared());
00057   libmesh_assert (this->n_variables());
00058 
00059   START_LOG("build_sparsity()", "DofMap");
00060 
00061   // Compute the sparsity structure of the global matrix.  This can be
00062   // fed into a PetscMatrix to allocate exacly the number of nonzeros
00063   // necessary to store the matrix.  This algorithm should be linear
00064   // in the (# of elements)*(# nodes per element)
00065 
00066   // We can be more efficient in the threaded sparsity pattern assembly
00067   // if we don't need the exact pattern.  For some sparse matrix formats
00068   // a good upper bound will suffice.
00069 
00070   // See if we need to include sparsity pattern entries for coupling
00071   // between neighbor dofs
00072   bool implicit_neighbor_dofs = this->use_coupled_neighbor_dofs(mesh);
00073 
00074   // We can compute the sparsity pattern in parallel on multiple
00075   // threads.  The goal is for each thread to compute the full sparsity
00076   // pattern for a subset of elements.  These sparsity patterns can
00077   // be efficiently merged in the SparsityPattern::Build::join()
00078   // method, especially if there is not too much overlap between them.
00079   // Even better, if the full sparsity pattern is not needed then
00080   // the number of nonzeros per row can be estimated from the
00081   // sparsity patterns created on each thread.
00082   AutoPtr<SparsityPattern::Build> sp
00083     (new SparsityPattern::Build (mesh,
00084                                  *this,
00085                                  this->_dof_coupling,
00086                                  implicit_neighbor_dofs,
00087                                  need_full_sparsity_pattern));
00088 
00089   Threads::parallel_reduce (ConstElemRange (mesh.active_local_elements_begin(),
00090                                             mesh.active_local_elements_end()), *sp);
00091 
00092   sp->parallel_sync();
00093 
00094 #ifndef NDEBUG
00095   // Avoid declaring these variables unless asserts are enabled.
00096   const processor_id_type proc_id        = mesh.processor_id();
00097   const dof_id_type n_dofs_on_proc = this->n_dofs_on_processor(proc_id);
00098 #endif
00099   libmesh_assert_equal_to (sp->sparsity_pattern.size(), n_dofs_on_proc);
00100 
00101   STOP_LOG("build_sparsity()", "DofMap");
00102 
00103   // Check to see if we have any extra stuff to add to the sparsity_pattern
00104   if (_extra_sparsity_function)
00105     {
00106       if (_augment_sparsity_pattern)
00107         {
00108           libmesh_here();
00109           libMesh::out << "WARNING:  You have specified both an extra sparsity function and object.\n"
00110                        << "          Are you sure this is what you meant to do??"
00111                        << std::endl;
00112         }
00113 
00114       _extra_sparsity_function
00115         (sp->sparsity_pattern, sp->n_nz,
00116          sp->n_oz, _extra_sparsity_context);
00117     }
00118 
00119   if (_augment_sparsity_pattern)
00120     _augment_sparsity_pattern->augment_sparsity_pattern
00121       (sp->sparsity_pattern, sp->n_nz, sp->n_oz);
00122 
00123   return sp;
00124 }

void libMesh::DofMap::clear (  ) 

Free all memory associated with the object, but keep the mesh pointer.

Definition at line 798 of file dof_map.C.

References _dof_constraints, _end_df, _end_old_df, _first_df, _first_old_df, _matrices, _n_dfs, _n_old_dfs, _send_list, _variable_groups, _variables, clear_sparsity(), and need_full_sparsity_pattern.

Referenced by ~DofMap().

00799 {
00800   // we don't want to clear
00801   // the coupling matrix!
00802   // It should not change...
00803   //_dof_coupling->clear();
00804 
00805   _variables.clear();
00806   _variable_groups.clear();
00807   _first_df.clear();
00808   _end_df.clear();
00809   _send_list.clear();
00810   this->clear_sparsity();
00811   need_full_sparsity_pattern = false;
00812 
00813 #ifdef LIBMESH_ENABLE_AMR
00814 
00815   _dof_constraints.clear();
00816   _n_old_dfs = 0;
00817   _first_old_df.clear();
00818   _end_old_df.clear();
00819 
00820 #endif
00821 
00822   _matrices.clear();
00823 
00824   _n_dfs = 0;
00825 }

void libMesh::DofMap::clear_sparsity (  ) 

Clears the sparsity pattern

Definition at line 1480 of file dof_map.C.

References _n_nz, _n_oz, _sp, libMesh::AutoPtr< Tp >::get(), need_full_sparsity_pattern, and libMesh::AutoPtr< Tp >::reset().

Referenced by clear(), libMesh::ImplicitSystem::reinit(), and libMesh::EigenSystem::reinit().

01481 {
01482   if (need_full_sparsity_pattern)
01483     {
01484       libmesh_assert(_sp.get());
01485       libmesh_assert(!_n_nz || _n_nz == &_sp->n_nz);
01486       libmesh_assert(!_n_oz || _n_oz == &_sp->n_oz);
01487       _sp.reset();
01488     }
01489   else
01490     {
01491       libmesh_assert(!_sp.get());
01492       delete _n_nz;
01493       delete _n_oz;
01494     }
01495   _n_nz = NULL;
01496   _n_oz = NULL;
01497 }

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

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

Definition at line 1443 of file dof_map.C.

References _matrices, _n_nz, _n_oz, _sp, build_sparsity(), end, need_full_sparsity_pattern, and libMesh::AutoPtr< Tp >::reset().

Referenced by libMesh::ImplicitSystem::init_matrices(), libMesh::EigenSystem::init_matrices(), libMesh::ImplicitSystem::reinit(), and libMesh::EigenSystem::reinit().

01444 {
01445   _sp = this->build_sparsity(mesh);
01446 
01447   // It is possible that some \p SparseMatrix implementations want to
01448   // see it.  Let them see it before we throw it away.
01449   std::vector<SparseMatrix<Number>* >::const_iterator
01450     pos = _matrices.begin(),
01451     end = _matrices.end();
01452 
01453   // If we need the full sparsity pattern, then we share a view of its
01454   // arrays, and we pass it in to the matrices.
01455   if (need_full_sparsity_pattern)
01456     {
01457       _n_nz = &_sp->n_nz;
01458       _n_oz = &_sp->n_oz;
01459 
01460       for (; pos != end; ++pos)
01461         (*pos)->update_sparsity_pattern (_sp->sparsity_pattern);
01462     }
01463   // If we don't need the full sparsity pattern anymore, steal the
01464   // arrays we do need and free the rest of the memory
01465   else
01466     {
01467       if (!_n_nz)
01468         _n_nz = new std::vector<dof_id_type>();
01469       _n_nz->swap(_sp->n_nz);
01470       if (!_n_oz)
01471         _n_oz = new std::vector<dof_id_type>();
01472       _n_oz->swap(_sp->n_oz);
01473 
01474       _sp.reset();
01475     }
01476 }

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

Constrains a dyadic element matrix B = v w'. This method requires the element matrix to be square, in which case the elem_dofs correspond to the global DOF indices of both the rows and columns of the element matrix. For this case the rows and columns of the matrix necessarily correspond to variables of the same approximation order.

Definition at line 1475 of file dof_map_constraints.C.

References _dof_constraints, build_constraint_matrix(), is_constrained_dof(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::size(), and libMesh::DenseMatrix< T >::vector_mult_transpose().

01479 {
01480   libmesh_assert_equal_to (v.size(), row_dofs.size());
01481   libmesh_assert_equal_to (w.size(), row_dofs.size());
01482 
01483   // check for easy return
01484   if (this->_dof_constraints.empty())
01485     return;
01486 
01487   // The constrained RHS is built up as R^T F.
01488   DenseMatrix<Number> R;
01489 
01490   this->build_constraint_matrix (R, row_dofs);
01491 
01492   START_LOG("cnstrn_elem_dyad_mat()", "DofMap");
01493 
01494   // It is possible that the vector is not constrained at all.
01495   if ((R.m() == v.size()) &&
01496       (R.n() == row_dofs.size())) // if the RHS is constrained
01497     {
01498       // Compute the matrix-vector products
01499       DenseVector<Number> old_v(v);
01500       DenseVector<Number> old_w(w);
01501 
01502       // compute matrix/vector product
01503       R.vector_mult_transpose(v, old_v);
01504       R.vector_mult_transpose(w, old_w);
01505 
01506       libmesh_assert_equal_to (row_dofs.size(), v.size());
01507       libmesh_assert_equal_to (row_dofs.size(), w.size());
01508 
01509       /* Constrain only v, not w.  */
01510 
01511       for (unsigned int i=0; i<row_dofs.size(); i++)
01512         if (this->is_constrained_dof(row_dofs[i]))
01513           {
01514             // If the DOF is constrained
01515             DofConstraints::const_iterator
01516                   pos = _dof_constraints.find(row_dofs[i]);
01517           
01518             libmesh_assert (pos != _dof_constraints.end());
01519 
01520             v(i) = 0;
01521           }
01522     } // end if the RHS is constrained.
01523 
01524   STOP_LOG("cnstrn_elem_dyad_mat()", "DofMap");
01525 }

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

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

Definition at line 1347 of file dof_map_constraints.C.

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

01351 {
01352   libmesh_assert_equal_to (row_dofs.size(), matrix.m());
01353   libmesh_assert_equal_to (col_dofs.size(), matrix.n());
01354 
01355   // check for easy return
01356   if (this->_dof_constraints.empty())
01357     return;
01358 
01359   // The constrained matrix is built up as R^T K C.
01360   DenseMatrix<Number> R;
01361   DenseMatrix<Number> C;
01362 
01363   // Safeguard against the user passing us the same
01364   // object for row_dofs and col_dofs.  If that is done
01365   // the calls to build_matrix would fail
01366   std::vector<dof_id_type> orig_row_dofs(row_dofs);
01367   std::vector<dof_id_type> orig_col_dofs(col_dofs);
01368 
01369   this->build_constraint_matrix (R, orig_row_dofs);
01370   this->build_constraint_matrix (C, orig_col_dofs);
01371 
01372   START_LOG("constrain_elem_matrix()", "DofMap");
01373 
01374   row_dofs = orig_row_dofs;
01375   col_dofs = orig_col_dofs;
01376 
01377 
01378   // It is possible that the matrix is not constrained at all.
01379   if ((R.m() == matrix.m()) &&
01380       (R.n() == row_dofs.size()) &&
01381       (C.m() == matrix.n()) &&
01382       (C.n() == col_dofs.size())) // If the matrix is constrained
01383     {
01384       // K_constrained = R^T K C
01385       matrix.left_multiply_transpose  (R);
01386       matrix.right_multiply (C);
01387 
01388 
01389       libmesh_assert_equal_to (matrix.m(), row_dofs.size());
01390       libmesh_assert_equal_to (matrix.n(), col_dofs.size());
01391 
01392 
01393       for (unsigned int i=0; i<row_dofs.size(); i++)
01394         if (this->is_constrained_dof(row_dofs[i]))
01395           {
01396             for (unsigned int j=0; j<matrix.n(); j++)
01397             {
01398               if(row_dofs[i] != col_dofs[j])
01399                 matrix(i,j) = 0.;
01400               else // If the DOF is constrained
01401                 matrix(i,j) = 1.;
01402             }
01403 
01404             if (asymmetric_constraint_rows)
01405               {
01406                 DofConstraints::const_iterator
01407                   pos = _dof_constraints.find(row_dofs[i]);
01408 
01409                 libmesh_assert (pos != _dof_constraints.end());
01410 
01411                 const DofConstraintRow& constraint_row = pos->second.first;
01412 
01413                 libmesh_assert (!constraint_row.empty());
01414 
01415                 for (DofConstraintRow::const_iterator
01416                        it=constraint_row.begin(); it != constraint_row.end();
01417                      ++it)
01418                   for (unsigned int j=0; j<col_dofs.size(); j++)
01419                     if (col_dofs[j] == it->first)
01420                       matrix(i,j) = -it->second;
01421               }
01422           }
01423     } // end if is constrained...
01424 
01425   STOP_LOG("constrain_elem_matrix()", "DofMap");
01426 }

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

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

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

Definition at line 1106 of file dof_map_constraints.C.

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

01109 {
01110   libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
01111   libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
01112 
01113   // check for easy return
01114   if (this->_dof_constraints.empty())
01115     return;
01116 
01117   // The constrained matrix is built up as C^T K C.
01118   DenseMatrix<Number> C;
01119 
01120 
01121   this->build_constraint_matrix (C, elem_dofs);
01122 
01123   START_LOG("constrain_elem_matrix()", "DofMap");
01124 
01125   // It is possible that the matrix is not constrained at all.
01126   if ((C.m() == matrix.m()) &&
01127       (C.n() == elem_dofs.size())) // It the matrix is constrained
01128     {
01129       // Compute the matrix-matrix-matrix product C^T K C
01130       matrix.left_multiply_transpose  (C);
01131       matrix.right_multiply (C);
01132 
01133 
01134       libmesh_assert_equal_to (matrix.m(), matrix.n());
01135       libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
01136       libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
01137 
01138 
01139       for (unsigned int i=0; i<elem_dofs.size(); i++)
01140         // If the DOF is constrained
01141         if (this->is_constrained_dof(elem_dofs[i]))
01142           {
01143             for (unsigned int j=0; j<matrix.n(); j++)
01144               matrix(i,j) = 0.;
01145 
01146             matrix(i,i) = 1.;
01147 
01148             if (asymmetric_constraint_rows)
01149               {
01150                 DofConstraints::const_iterator
01151                   pos = _dof_constraints.find(elem_dofs[i]);
01152 
01153                 libmesh_assert (pos != _dof_constraints.end());
01154 
01155                 const DofConstraintRow& constraint_row = pos->second.first;
01156 
01157                 // This is an overzealous assertion in the presence of
01158                 // heterogenous constraints: we now can constrain "u_i = c"
01159                 // with no other u_j terms involved.
01160                 //
01161                 // libmesh_assert (!constraint_row.empty());
01162 
01163                 for (DofConstraintRow::const_iterator
01164                        it=constraint_row.begin(); it != constraint_row.end();
01165                      ++it)
01166                   for (unsigned int j=0; j<elem_dofs.size(); j++)
01167                     if (elem_dofs[j] == it->first)
01168                       matrix(i,j) = -it->second;
01169               }
01170           }
01171     } // end if is constrained...
01172 
01173   STOP_LOG("constrain_elem_matrix()", "DofMap");
01174 }

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

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

Definition at line 1178 of file dof_map_constraints.C.

References _dof_constraints, build_constraint_matrix(), is_constrained_dof(), libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::right_multiply(), libMesh::DenseVector< T >::size(), and libMesh::DenseMatrix< T >::vector_mult_transpose().

01182 {
01183   libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
01184   libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
01185   libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
01186 
01187   // check for easy return
01188   if (this->_dof_constraints.empty())
01189     return;
01190 
01191   // The constrained matrix is built up as C^T K C.
01192   // The constrained RHS is built up as C^T F
01193   DenseMatrix<Number> C;
01194 
01195   this->build_constraint_matrix (C, elem_dofs);
01196 
01197   START_LOG("cnstrn_elem_mat_vec()", "DofMap");
01198 
01199   // It is possible that the matrix is not constrained at all.
01200   if ((C.m() == matrix.m()) &&
01201       (C.n() == elem_dofs.size())) // It the matrix is constrained
01202     {
01203       // Compute the matrix-matrix-matrix product C^T K C
01204       matrix.left_multiply_transpose  (C);
01205       matrix.right_multiply (C);
01206 
01207 
01208       libmesh_assert_equal_to (matrix.m(), matrix.n());
01209       libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
01210       libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
01211 
01212 
01213       for (unsigned int i=0; i<elem_dofs.size(); i++)
01214         if (this->is_constrained_dof(elem_dofs[i]))
01215           {
01216             for (unsigned int j=0; j<matrix.n(); j++)
01217               matrix(i,j) = 0.;
01218 
01219             // If the DOF is constrained
01220             matrix(i,i) = 1.;
01221 
01222             // This will put a nonsymmetric entry in the constraint
01223             // row to ensure that the linear system produces the
01224             // correct value for the constrained DOF.
01225             if (asymmetric_constraint_rows)
01226               {
01227                 DofConstraints::const_iterator
01228                   pos = _dof_constraints.find(elem_dofs[i]);
01229 
01230                 libmesh_assert (pos != _dof_constraints.end());
01231 
01232                 const DofConstraintRow& constraint_row = pos->second.first;
01233 
01234 // p refinement creates empty constraint rows
01235 //          libmesh_assert (!constraint_row.empty());
01236 
01237                 for (DofConstraintRow::const_iterator
01238                        it=constraint_row.begin(); it != constraint_row.end();
01239                      ++it)
01240                   for (unsigned int j=0; j<elem_dofs.size(); j++)
01241                     if (elem_dofs[j] == it->first)
01242                       matrix(i,j) = -it->second;
01243               }
01244           }
01245 
01246 
01247       // Compute the matrix-vector product C^T F
01248       DenseVector<Number> old_rhs(rhs);
01249 
01250       // compute matrix/vector product
01251       C.vector_mult_transpose(rhs, old_rhs);
01252     } // end if is constrained...
01253 
01254   STOP_LOG("cnstrn_elem_mat_vec()", "DofMap");
01255 }

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

Constrains the element vector.

Definition at line 1430 of file dof_map_constraints.C.

References _dof_constraints, build_constraint_matrix(), is_constrained_dof(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::size(), and libMesh::DenseMatrix< T >::vector_mult_transpose().

01433 {
01434   libmesh_assert_equal_to (rhs.size(), row_dofs.size());
01435 
01436   // check for easy return
01437   if (this->_dof_constraints.empty())
01438     return;
01439 
01440   // The constrained RHS is built up as R^T F.
01441   DenseMatrix<Number> R;
01442 
01443   this->build_constraint_matrix (R, row_dofs);
01444 
01445   START_LOG("constrain_elem_vector()", "DofMap");
01446 
01447   // It is possible that the vector is not constrained at all.
01448   if ((R.m() == rhs.size()) &&
01449       (R.n() == row_dofs.size())) // if the RHS is constrained
01450     {
01451       // Compute the matrix-vector product
01452       DenseVector<Number> old_rhs(rhs);
01453       R.vector_mult_transpose(rhs, old_rhs);
01454 
01455       libmesh_assert_equal_to (row_dofs.size(), rhs.size());
01456 
01457       for (unsigned int i=0; i<row_dofs.size(); i++)
01458         if (this->is_constrained_dof(row_dofs[i]))
01459           {
01460             // If the DOF is constrained
01461             DofConstraints::const_iterator
01462                   pos = _dof_constraints.find(row_dofs[i]);
01463           
01464             libmesh_assert (pos != _dof_constraints.end());
01465 
01466             rhs(i) = 0;
01467           }
01468     } // end if the RHS is constrained.
01469 
01470   STOP_LOG("constrain_elem_vector()", "DofMap");
01471 }

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

Does not actually constrain anything, but modifies dofs in the same way as any of the constrain functions would do, i.e. adds those dofs in terms of which any of the existing dofs is constrained.

Definition at line 1529 of file dof_map_constraints.C.

References _dof_constraints, and build_constraint_matrix().

01530 {
01531   // check for easy return
01532   if (this->_dof_constraints.empty())
01533     return;
01534 
01535   // All the work is done by \p build_constraint_matrix.  We just need
01536   // a dummy matrix.
01537   DenseMatrix<Number> R;
01538   this->build_constraint_matrix (R, dofs);
01539 }

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

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

Definition at line 3011 of file dof_map_constraints.C.

References _dof_constraints, libMesh::Elem::dim(), libMesh::DofObject::dof_number(), libMesh::Elem::get_node(), libMesh::Elem::is_node_on_side(), libMesh::Elem::is_vertex(), libMesh::DofObject::n_comp(), libMesh::FEInterface::n_dofs_at_node(), libMesh::Elem::n_nodes(), libMesh::Elem::n_sides(), libMesh::FEType::order, libMesh::Elem::p_level(), libMesh::Threads::spin_mtx, sys_number(), libMesh::Elem::type(), and variable_type().

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

03015 {
03016   // We're constraining dofs on elem which correspond to p refinement
03017   // levels above p - this only makes sense if elem's p refinement
03018   // level is above p.
03019   libmesh_assert_greater (elem->p_level(), p);
03020   libmesh_assert_less (s, elem->n_sides());
03021 
03022   const unsigned int sys_num = this->sys_number();
03023   const unsigned int dim = elem->dim();
03024   ElemType type = elem->type();
03025   FEType low_p_fe_type = this->variable_type(var);
03026   FEType high_p_fe_type = this->variable_type(var);
03027   low_p_fe_type.order = static_cast<Order>(low_p_fe_type.order + p);
03028   high_p_fe_type.order = static_cast<Order>(high_p_fe_type.order +
03029                                             elem->p_level());
03030 
03031   const unsigned int n_nodes = elem->n_nodes();
03032   for (unsigned int n = 0; n != n_nodes; ++n)
03033     if (elem->is_node_on_side(n, s))
03034       {
03035         const Node * const node = elem->get_node(n);
03036         const unsigned int low_nc =
03037           FEInterface::n_dofs_at_node (dim, low_p_fe_type, type, n);
03038         const unsigned int high_nc =
03039           FEInterface::n_dofs_at_node (dim, high_p_fe_type, type, n);
03040 
03041         // since we may be running this method concurretly
03042         // on multiple threads we need to acquire a lock
03043         // before modifying the _dof_constraints object.
03044         Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
03045 
03046         if (elem->is_vertex(n))
03047           {
03048             // Add "this is zero" constraint rows for high p vertex
03049             // dofs
03050             for (unsigned int i = low_nc; i != high_nc; ++i)
03051               {
03052                 _dof_constraints[node->dof_number(sys_num,var,i)].first.clear();
03053                 _dof_constraints[node->dof_number(sys_num,var,i)].second = 0.;
03054               }
03055           }
03056         else
03057           {
03058             const unsigned int total_dofs = node->n_comp(sys_num, var);
03059             libmesh_assert_greater_equal (total_dofs, high_nc);
03060             // Add "this is zero" constraint rows for high p
03061             // non-vertex dofs, which are numbered in reverse
03062             for (unsigned int j = low_nc; j != high_nc; ++j)
03063               {
03064                 const unsigned int i = total_dofs - j - 1;
03065                 _dof_constraints[node->dof_number(sys_num,var,i)].first.clear();
03066                 _dof_constraints[node->dof_number(sys_num,var,i)].second = 0.;
03067               }
03068           }
03069       }
03070 }

DofConstraints::const_iterator libMesh::DofMap::constraint_rows_begin (  )  const [inline]

Returns an iterator pointing to the first DoF constraint row

Definition at line 558 of file dof_map.h.

References _dof_constraints.

00559     { return _dof_constraints.begin(); }

DofConstraints::const_iterator libMesh::DofMap::constraint_rows_end (  )  const [inline]

Returns an iterator pointing just past the last DoF constraint row

Definition at line 564 of file dof_map.h.

References _dof_constraints.

00565     { return _dof_constraints.end(); }

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

Rebuilds the raw degree of freedom and DofObject constraints. A time is specified for use in building time-dependent Dirichlet constraints.

Definition at line 856 of file dof_map_constraints.C.

References _dirichlet_boundaries, _dof_constraints, _node_constraints, _periodic_boundaries, libMesh::CommWorld, libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), libMesh::StoredRange< iterator_type, object_type >::empty(), libMesh::MeshBase::is_prepared(), libMesh::MeshBase::is_serial(), libMesh::MeshBase::local_elements_begin(), libMesh::MeshBase::local_elements_end(), libMesh::Parallel::Communicator::max(), libMesh::MeshBase::mesh_dimension(), n_variables(), libMesh::Threads::parallel_for(), libMesh::StoredRange< iterator_type, object_type >::reset(), libMesh::MeshBase::sub_point_locator(), and libMesh::Parallel::Communicator::verify().

Referenced by libMesh::EquationSystems::allgather(), and libMesh::EquationSystems::reinit().

00857 {
00858   parallel_only();
00859 
00860   START_LOG("create_dof_constraints()", "DofMap");
00861 
00862   libmesh_assert (mesh.is_prepared());
00863 
00864   const unsigned int dim = mesh.mesh_dimension();
00865 
00866   // We might get constraint equations from AMR hanging nodes in 2D/3D
00867   // or from boundary conditions in any dimension
00868   const bool possible_local_constraints = false
00869 #ifdef LIBMESH_ENABLE_AMR
00870     || dim > 1 
00871 #endif
00872 #ifdef LIBMESH_ENABLE_PERIODIC
00873     || !_periodic_boundaries->empty()
00874 #endif
00875 #ifdef LIBMESH_ENABLE_DIRICHLET
00876     || !_dirichlet_boundaries->empty()
00877 #endif
00878   ;
00879 
00880   // Even if we don't have constraints, another processor might.
00881   bool possible_global_constraints = possible_local_constraints;
00882 #if defined(LIBMESH_ENABLE_PERIODIC) || defined(LIBMESH_ENABLE_DIRICHLET) || defined(LIBMESH_ENABLE_AMR)
00883   libmesh_assert(CommWorld.verify(mesh.is_serial()));
00884 
00885   if (!mesh.is_serial())
00886     CommWorld.max(possible_global_constraints);
00887 #endif
00888 
00889   if (!possible_global_constraints)
00890     {
00891       // make sure we stop logging though
00892       STOP_LOG("create_dof_constraints()", "DofMap");
00893       return;
00894     }
00895 
00896   // Here we build the hanging node constraints.  This is done
00897   // by enforcing the condition u_a = u_b along hanging sides.
00898   // u_a = u_b is collocated at the nodes of side a, which gives
00899   // one row of the constraint matrix.
00900 
00901   // define the range of elements of interest
00902   ConstElemRange range;
00903   if (possible_local_constraints)
00904     {
00905       // With SerialMesh or a serial ParallelMesh, every processor
00906       // computes every constraint
00907       MeshBase::const_element_iterator
00908         elem_begin = mesh.elements_begin(),
00909         elem_end   = mesh.elements_end();
00910 
00911       // With a parallel ParallelMesh, processors compute only
00912       // their local constraints
00913       if (!mesh.is_serial())
00914         {
00915           elem_begin = mesh.local_elements_begin();
00916           elem_end   = mesh.local_elements_end();
00917         }
00918 
00919       // set the range to contain the specified elements
00920       range.reset (elem_begin, elem_end);
00921     }
00922   else
00923     range.reset (mesh.elements_end(), mesh.elements_end());
00924 
00925   // compute_periodic_constraints requires a point_locator() from our
00926   // Mesh, that point_locator() construction is threaded.  Rather than
00927   // nest threads within threads we'll make sure it's preconstructed.
00928 #ifdef LIBMESH_ENABLE_PERIODIC
00929   if (!_periodic_boundaries->empty() && !range.empty())
00930     mesh.sub_point_locator();
00931 #endif
00932 
00933 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
00934   // recalculate node constraints from scratch
00935   _node_constraints.clear();
00936 
00937   Threads::parallel_for (range,
00938                          ComputeNodeConstraints (_node_constraints,
00939                                                  *this,
00940 #ifdef LIBMESH_ENABLE_PERIODIC
00941                                                  *_periodic_boundaries,
00942 #endif
00943                                                  mesh));
00944 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
00945 
00946 
00947   // recalculate dof constraints from scratch
00948   _dof_constraints.clear();
00949 
00950   // Look at all the variables in the system.  Reset the element
00951   // range at each iteration -- there is no need to reconstruct it.
00952   for (unsigned int variable_number=0; variable_number<this->n_variables();
00953        ++variable_number, range.reset())
00954     Threads::parallel_for (range,
00955                            ComputeConstraints (_dof_constraints,
00956                                                *this,
00957 #ifdef LIBMESH_ENABLE_PERIODIC
00958                                                *_periodic_boundaries,
00959 #endif
00960                                                mesh,
00961                                                variable_number));
00962 
00963 #ifdef LIBMESH_ENABLE_DIRICHLET
00964   for (DirichletBoundaries::iterator 
00965          i = _dirichlet_boundaries->begin();
00966        i != _dirichlet_boundaries->end(); ++i, range.reset())
00967     {
00968       Threads::parallel_for
00969         (range,
00970          ConstrainDirichlet(*this, mesh, time, **i)
00971          );
00972     }
00973 #endif // LIBMESH_ENABLE_DIRICHLET
00974 
00975   STOP_LOG("create_dof_constraints()", "DofMap");
00976 }

void libMesh::ReferenceCounter::disable_print_counter_info (  )  [static, inherited]

Definition at line 106 of file reference_counter.C.

References libMesh::ReferenceCounter::_enable_print_counter.

00107 {
00108   _enable_print_counter = false;
00109   return;
00110 }

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

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

Definition at line 829 of file dof_map.C.

References _end_df, _end_old_df, _first_df, _first_old_df, _n_dfs, _n_old_dfs, _send_list, add_neighbors_to_send_list(), libMesh::Parallel::Communicator::allgather(), libMesh::CommWorld, distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), elem_ptr(), libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), invalidate_dofs(), libMesh::MeshBase::is_prepared(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), libMesh::n_processors(), node_ptr(), libMesh::MeshBase::nodes_begin(), libMesh::MeshBase::nodes_end(), libMesh::on_command_line(), libMesh::processor_id(), reinit(), and set_nonlocal_dof_objects().

Referenced by libMesh::EquationSystems::allgather(), and libMesh::EquationSystems::reinit().

00830 {
00831   // This function must be run on all processors at once
00832   parallel_only();
00833 
00834   // Log how long it takes to distribute the degrees of freedom
00835   START_LOG("distribute_dofs()", "DofMap");
00836 
00837   libmesh_assert (mesh.is_prepared());
00838 
00839   const processor_id_type proc_id = libMesh::processor_id();
00840   const processor_id_type n_proc  = libMesh::n_processors();
00841 
00842 //  libmesh_assert_greater (this->n_variables(), 0);
00843   libmesh_assert_less (proc_id, n_proc);
00844 
00845   // re-init in case the mesh has changed
00846   this->reinit(mesh);
00847 
00848   // By default distribute variables in a
00849   // var-major fashion, but allow run-time
00850   // specification
00851   bool node_major_dofs = libMesh::on_command_line ("--node_major_dofs");
00852 
00853   // The DOF counter, will be incremented as we encounter
00854   // new degrees of freedom
00855   dof_id_type next_free_dof = 0;
00856 
00857   // Clear the send list before we rebuild it
00858   _send_list.clear();
00859 
00860   // Set temporary DOF indices on this processor
00861   if (node_major_dofs)
00862     this->distribute_local_dofs_node_major (next_free_dof, mesh);
00863   else
00864     this->distribute_local_dofs_var_major (next_free_dof, mesh);
00865 
00866   // Get DOF counts on all processors
00867   std::vector<dof_id_type> dofs_on_proc(n_proc, 0);
00868   CommWorld.allgather(next_free_dof, dofs_on_proc);
00869 
00870   // Resize and fill the _first_df and _end_df arrays
00871 #ifdef LIBMESH_ENABLE_AMR
00872   _first_old_df = _first_df;
00873   _end_old_df = _end_df;
00874 #endif
00875 
00876   _first_df.resize(n_proc);
00877   _end_df.resize (n_proc);
00878 
00879   // Get DOF offsets
00880   _first_df[0] = 0;
00881   for (processor_id_type i=1; i < n_proc; ++i)
00882     _first_df[i] = _end_df[i-1] = _first_df[i-1] + dofs_on_proc[i-1];
00883   _end_df[n_proc-1] = _first_df[n_proc-1] + dofs_on_proc[n_proc-1];
00884 
00885   // Clear all the current DOF indices
00886   // (distribute_dofs expects them cleared!)
00887   this->invalidate_dofs(mesh);
00888 
00889   next_free_dof = _first_df[proc_id];
00890 
00891   // Set permanent DOF indices on this processor
00892   if (node_major_dofs)
00893     this->distribute_local_dofs_node_major (next_free_dof, mesh);
00894   else
00895     this->distribute_local_dofs_var_major (next_free_dof, mesh);
00896 
00897   libmesh_assert_equal_to (next_free_dof, _end_df[proc_id]);
00898 
00899   //------------------------------------------------------------
00900   // At this point, all n_comp and dof_number values on local
00901   // DofObjects should be correct, but a ParallelMesh might have
00902   // incorrect values on non-local DofObjects.  Let's request the
00903   // correct values from each other processor.
00904 
00905   if (libMesh::n_processors() > 1)
00906     {
00907       this->set_nonlocal_dof_objects(mesh.nodes_begin(),
00908                                      mesh.nodes_end(),
00909                                      mesh, &DofMap::node_ptr);
00910 
00911       this->set_nonlocal_dof_objects(mesh.elements_begin(),
00912                                      mesh.elements_end(),
00913                                      mesh, &DofMap::elem_ptr);
00914 
00915 #ifdef DEBUG
00916       MeshTools::libmesh_assert_valid_dof_ids(mesh);
00917 #endif
00918     }
00919 
00920   // Set the total number of degrees of freedom
00921 #ifdef LIBMESH_ENABLE_AMR
00922   _n_old_dfs = _n_dfs;
00923 #endif
00924   _n_dfs = _end_df[n_proc-1];
00925 
00926   STOP_LOG("distribute_dofs()", "DofMap");
00927 
00928   // Note that in the add_neighbors_to_send_list nodes on processor
00929   // boundaries that are shared by multiple elements are added for
00930   // each element.
00931   this->add_neighbors_to_send_list(mesh);
00932 
00933   // Here we used to clean up that data structure; now System and
00934   // EquationSystems call that for us, after we've added constraint
00935   // dependencies to the send_list too.
00936   // this->sort_send_list ();
00937 }

void libMesh::DofMap::distribute_local_dofs_node_major ( dof_id_type next_free_dof,
MeshBase mesh 
) [private]

Distributes the global degrees of freedom, for dofs on this processor. In this format all the degrees of freedom at a node/element are in contiguous blocks. Note in particular that the degrees of freedom for a given variable are not in contiguous blocks, as in the case of distribute_local_dofs_var_major. Starts at index next_free_dof, and increments it to the post-final index. If build_send_list is true, builds the send list. If false, clears and reserves the send list

Definition at line 940 of file dof_map.C.

References _n_SCALAR_dofs, libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::Elem::get_node(), libMesh::DofObject::invalid_id, libMesh::MeshTools::libmesh_assert_valid_procids< Node >(), libMesh::MeshBase::local_nodes_begin(), libMesh::MeshBase::local_nodes_end(), libMesh::DofObject::n_comp(), libMesh::DofObject::n_comp_group(), libMesh::Elem::n_nodes(), n_nodes, libMesh::n_processors(), libMesh::DofObject::n_var_groups(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::FEType::order, libMesh::processor_id(), libMesh::DofObject::processor_id(), libMeshEnums::SCALAR, libMesh::DofObject::set_vg_dof_base(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::Variable::type(), variable_group(), and libMesh::DofObject::vg_dof_base().

Referenced by distribute_dofs().

00942 {
00943   const unsigned int sys_num       = this->sys_number();
00944   const unsigned int n_var_groups  = this->n_variable_groups();
00945 
00946   //-------------------------------------------------------------------------
00947   // First count and assign temporary numbers to local dofs
00948   MeshBase::element_iterator       elem_it  = mesh.active_local_elements_begin();
00949   const MeshBase::element_iterator elem_end = mesh.active_local_elements_end();
00950 
00951   for ( ; elem_it != elem_end; ++elem_it)
00952     {
00953       // Only number dofs connected to active
00954       // elements on this processor.
00955       Elem* elem                 = *elem_it;
00956       const unsigned int n_nodes = elem->n_nodes();
00957 
00958       // First number the nodal DOFS
00959       for (unsigned int n=0; n<n_nodes; n++)
00960         {
00961           Node* node = elem->get_node(n);
00962           
00963           for (unsigned vg=0; vg<n_var_groups; vg++)
00964             {
00965               const VariableGroup &vg_description(this->variable_group(vg));
00966               
00967               if( (vg_description.type().family != SCALAR) &&
00968                   (vg_description.active_on_subdomain(elem->subdomain_id())) )
00969                 {
00970                   // assign dof numbers (all at once) if this is
00971                   // our node and if they aren't already there
00972                   if ((node->n_comp_group(sys_num,vg) > 0) &&
00973                       (node->processor_id() == libMesh::processor_id()) &&
00974                       (node->vg_dof_base(sys_num,vg) ==
00975                        DofObject::invalid_id))
00976                     {
00977                       node->set_vg_dof_base(sys_num,
00978                                             vg,
00979                                             next_free_dof);
00980                       next_free_dof += (vg_description.n_variables()*
00981                                         node->n_comp_group(sys_num,vg));
00982                       //node->debug_buffer();
00983                     }
00984                 }
00985             }
00986         }
00987 
00988       // Now number the element DOFS
00989       for (unsigned vg=0; vg<n_var_groups; vg++)
00990         {
00991           const VariableGroup &vg_description(this->variable_group(vg));
00992 
00993           if ( (vg_description.type().family != SCALAR) &&
00994                (vg_description.active_on_subdomain(elem->subdomain_id())) )
00995             if (elem->n_comp_group(sys_num,vg) > 0)
00996               {
00997                 libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg),
00998                                          DofObject::invalid_id);
00999 
01000                 elem->set_vg_dof_base(sys_num,
01001                                       vg,
01002                                       next_free_dof);
01003 
01004                 next_free_dof += (vg_description.n_variables()*
01005                                   elem->n_comp(sys_num,vg));            
01006               }
01007         }
01008     } // done looping over elements
01009 
01010 
01011   // we may have missed assigning DOFs to nodes that we own
01012   // but to which we have no connected elements matching our
01013   // variable restriction criterion.  this will happen, for example,
01014   // if variable V is restricted to subdomain S.  We may not own
01015   // any elements which live in S, but we may own nodes which are
01016   // *connected* to elements which do.  in this scenario these nodes
01017   // will presently have unnumbered DOFs. we need to take care of
01018   // them here since we own them and no other processor will touch them.
01019   {
01020     MeshBase::node_iterator       node_it  = mesh.local_nodes_begin();
01021     const MeshBase::node_iterator node_end = mesh.local_nodes_end();
01022 
01023     for (; node_it != node_end; ++node_it)
01024       {
01025         Node *node = *node_it;
01026         libmesh_assert(node);
01027 
01028         for (unsigned vg=0; vg<n_var_groups; vg++)
01029           {
01030             const VariableGroup &vg_description(this->variable_group(vg));
01031             
01032             if (node->n_comp_group(sys_num,vg))
01033               if (node->vg_dof_base(sys_num,vg) == DofObject::invalid_id)
01034                 {
01035                   node->set_vg_dof_base (sys_num,
01036                                          vg,
01037                                          next_free_dof);
01038 
01039                   next_free_dof += (vg_description.n_variables()*
01040                                     node->n_comp(sys_num,vg));
01041                 }
01042           }
01043       }
01044   }
01045 
01046   // Finally, count up the SCALAR dofs
01047   this->_n_SCALAR_dofs = 0;
01048   for (unsigned vg=0; vg<n_var_groups; vg++)
01049     {
01050       const VariableGroup &vg_description(this->variable_group(vg));
01051       
01052       if( vg_description.type().family == SCALAR )
01053         {
01054           this->_n_SCALAR_dofs += (vg_description.n_variables()*
01055                                    vg_description.type().order);
01056           continue;
01057         }
01058     }
01059 
01060   // Only increment next_free_dof if we're on the processor
01061   // that holds this SCALAR variable
01062   if ( libMesh::processor_id() == (libMesh::n_processors()-1) )
01063     next_free_dof += _n_SCALAR_dofs;
01064 
01065 #ifdef DEBUG
01066   {
01067     // std::cout << "next_free_dof=" << next_free_dof << std::endl
01068     //        << "_n_SCALAR_dofs=" << _n_SCALAR_dofs << std::endl;
01069 
01070     // Make sure we didn't miss any nodes
01071     MeshTools::libmesh_assert_valid_procids<Node>(mesh);
01072 
01073     MeshBase::node_iterator       node_it  = mesh.local_nodes_begin();
01074     const MeshBase::node_iterator node_end = mesh.local_nodes_end();
01075     for (; node_it != node_end; ++node_it)
01076       {
01077         Node *obj = *node_it;
01078         libmesh_assert(obj);
01079         unsigned int n_var_g = obj->n_var_groups(this->sys_number());
01080         for (unsigned int vg=0; vg != n_var_g; ++vg)
01081           {
01082             unsigned int n_comp_g =
01083               obj->n_comp_group(this->sys_number(), vg);
01084             dof_id_type my_first_dof = n_comp_g ?
01085               obj->vg_dof_base(this->sys_number(), vg) : 0;
01086             libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
01087           }
01088       }
01089   }
01090 #endif // DEBUG
01091 }

void libMesh::DofMap::distribute_local_dofs_var_major ( dof_id_type next_free_dof,
MeshBase mesh 
) [private]

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

Definition at line 1095 of file dof_map.C.

References _n_SCALAR_dofs, libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::Elem::get_node(), libMesh::DofObject::invalid_id, libMesh::MeshTools::libmesh_assert_valid_procids< Node >(), libMesh::MeshBase::local_nodes_begin(), libMesh::MeshBase::local_nodes_end(), libMesh::DofObject::n_comp_group(), libMesh::Elem::n_nodes(), n_nodes, libMesh::n_processors(), libMesh::DofObject::n_var_groups(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::FEType::order, libMesh::processor_id(), libMesh::DofObject::processor_id(), libMeshEnums::SCALAR, libMesh::DofObject::set_vg_dof_base(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::Variable::type(), variable_group(), and libMesh::DofObject::vg_dof_base().

Referenced by distribute_dofs().

01097 {
01098   const unsigned int sys_num      = this->sys_number();
01099   const unsigned int n_var_groups = this->n_variable_groups();
01100   
01101   //-------------------------------------------------------------------------
01102   // First count and assign temporary numbers to local dofs
01103   for (unsigned vg=0; vg<n_var_groups; vg++)
01104     {
01105       const VariableGroup &vg_description(this->variable_group(vg));
01106 
01107       const unsigned int n_vars_in_group = vg_description.n_variables();
01108       
01109       // Skip the SCALAR dofs
01110       if (vg_description.type().family == SCALAR)
01111         continue;
01112 
01113       MeshBase::element_iterator       elem_it  = mesh.active_local_elements_begin();
01114       const MeshBase::element_iterator elem_end = mesh.active_local_elements_end();
01115 
01116       for ( ; elem_it != elem_end; ++elem_it)
01117         {
01118           // Only number dofs connected to active
01119           // elements on this processor.
01120           Elem* elem  = *elem_it;
01121 
01122           // ... and only variables which are active on
01123           // on this element's subdomain
01124           if (!vg_description.active_on_subdomain(elem->subdomain_id()))
01125             continue;
01126 
01127           const unsigned int n_nodes = elem->n_nodes();
01128 
01129           // First number the nodal DOFS
01130           for (unsigned int n=0; n<n_nodes; n++)
01131             {
01132               Node* node = elem->get_node(n);
01133 
01134               // assign dof numbers (all at once) if this is
01135               // our node and if they aren't already there
01136               if ((node->n_comp_group(sys_num,vg) > 0) &&
01137                   (node->processor_id() == libMesh::processor_id()) &&
01138                   (node->vg_dof_base(sys_num,vg) ==
01139                    DofObject::invalid_id))
01140                 {
01141                   node->set_vg_dof_base(sys_num,
01142                                         vg,
01143                                         next_free_dof);
01144                   
01145                   next_free_dof += (n_vars_in_group*
01146                                     node->n_comp_group(sys_num,vg));
01147                 }
01148             }
01149 
01150           // Now number the element DOFS
01151           if (elem->n_comp_group(sys_num,vg) > 0)
01152             {
01153               libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg),
01154                                        DofObject::invalid_id);
01155 
01156               elem->set_vg_dof_base(sys_num,
01157                                     vg,
01158                                     next_free_dof);
01159 
01160               next_free_dof += (n_vars_in_group*
01161                                 elem->n_comp_group(sys_num,vg));
01162             }
01163         } // end loop on elements
01164 
01165       // we may have missed assigning DOFs to nodes that we own
01166       // but to which we have no connected elements matching our
01167       // variable restriction criterion.  this will happen, for example,
01168       // if variable V is restricted to subdomain S.  We may not own
01169       // any elements which live in S, but we may own nodes which are
01170       // *connected* to elements which do.  in this scenario these nodes
01171       // will presently have unnumbered DOFs. we need to take care of
01172       // them here since we own them and no other processor will touch them.
01173       {
01174         MeshBase::node_iterator       node_it  = mesh.local_nodes_begin();
01175         const MeshBase::node_iterator node_end = mesh.local_nodes_end();
01176 
01177         for (; node_it != node_end; ++node_it)
01178           {
01179             Node *node = *node_it;
01180             libmesh_assert(node);
01181 
01182             if (node->n_comp_group(sys_num,vg))
01183               if (node->vg_dof_base(sys_num,vg) == DofObject::invalid_id)
01184                 {
01185                   node->set_vg_dof_base (sys_num,
01186                                          vg,
01187                                          next_free_dof);
01188 
01189                   next_free_dof += (n_vars_in_group*
01190                                     node->n_comp_group(sys_num,vg));
01191                 }
01192           }
01193       }
01194     } // end loop on variable groups
01195 
01196   // Finally, count up the SCALAR dofs
01197   this->_n_SCALAR_dofs = 0;
01198   for (unsigned vg=0; vg<n_var_groups; vg++)
01199     {
01200       const VariableGroup &vg_description(this->variable_group(vg));
01201       
01202       if( vg_description.type().family == SCALAR )
01203         {
01204           this->_n_SCALAR_dofs += (vg_description.n_variables()*
01205                                    vg_description.type().order);
01206           continue;
01207         }
01208     }
01209 
01210   // Only increment next_free_dof if we're on the processor
01211   // that holds this SCALAR variable
01212   if ( libMesh::processor_id() == (libMesh::n_processors()-1) )
01213     next_free_dof += _n_SCALAR_dofs;
01214 
01215 #ifdef DEBUG
01216   {
01217     // Make sure we didn't miss any nodes
01218     MeshTools::libmesh_assert_valid_procids<Node>(mesh);
01219     
01220     MeshBase::node_iterator       node_it  = mesh.local_nodes_begin();
01221     const MeshBase::node_iterator node_end = mesh.local_nodes_end();
01222     for (; node_it != node_end; ++node_it)
01223       {
01224         Node *obj = *node_it;
01225         libmesh_assert(obj);
01226         unsigned int n_var_g = obj->n_var_groups(this->sys_number());
01227         for (unsigned int vg=0; vg != n_var_g; ++vg)
01228           {
01229             unsigned int n_comp_g =
01230               obj->n_comp_group(this->sys_number(), vg);
01231             dof_id_type my_first_dof = n_comp_g ?
01232               obj->vg_dof_base(this->sys_number(), vg) : 0;
01233             libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
01234           }
01235       }
01236   }
01237 #endif // DEBUG
01238 }

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

Fills the vector di with the global degree of freedom indices for the element. If no variable number is specified then all variables are returned.

Definition at line 1587 of file dof_map.C.

References libMesh::Elem::active(), libMesh::Elem::dim(), libMesh::DofObject::dof_number(), libMesh::FEInterface::extra_hanging_dofs(), libMesh::FEType::family, libMesh::Elem::get_node(), libMesh::DofObject::invalid_id, libMesh::invalid_uint, libMesh::Elem::is_vertex(), libMeshEnums::LAGRANGE, libMesh::DofObject::n_comp(), n_dofs(), libMesh::FEInterface::n_dofs_at_node(), libMesh::FEInterface::n_dofs_per_elem(), libMesh::Elem::n_nodes(), n_nodes, libMesh::DofObject::n_systems(), n_variables(), n_vars, libMesh::FEType::order, libMesh::Elem::p_level(), libMeshEnums::SCALAR, SCALAR_dof_indices(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::Elem::type(), variable(), and variable_type().

Referenced by libMesh::ExactSolution::_compute_error(), add_neighbors_to_send_list(), libMesh::HPCoarsenTest::add_projection(), allgather_recursive_constraints(), libMesh::EquationSystems::build_discontinuous_solution_vector(), libMesh::EquationSystems::build_solution_vector(), libMesh::System::calculate_norm(), libMesh::FEGenericBase< OutputType >::coarsened_dof_values(), libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), libMesh::FEGenericBase< OutputType >::compute_proj_constraints(), DMCreateDomainDecomposition_libMesh(), DMCreateFieldDecomposition_libMesh(), libMesh::JumpErrorEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::EquationSystems::get_solution(), libMesh::MeshFunction::gradient(), libMesh::MeshFunction::hessian(), libMesh::SystemSubsetBySubdomain::init(), libMesh::System::local_dof_indices(), max_constraint_error(), libMesh::WeightedPatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::BoundaryProjectSolution::operator()(), libMesh::ProjectSolution::operator()(), libMesh::PatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::MeshFunction::operator()(), libMesh::SparsityPattern::Build::operator()(), libMesh::ErrorVector::plot_error(), libMesh::FEMContext::pre_fe_reinit(), scatter_constraints(), libMesh::HPCoarsenTest::select_refinement(), libMesh::EnsightIO::write_scalar_ascii(), and libMesh::EnsightIO::write_vector_ascii().

01590 {
01591   START_LOG("dof_indices()", "DofMap");
01592 
01593   libmesh_assert(elem);
01594 
01595   const unsigned int n_nodes = elem->n_nodes();
01596   const ElemType type        = elem->type();
01597   const unsigned int sys_num = this->sys_number();
01598   const unsigned int n_vars  = this->n_variables();
01599   const unsigned int dim     = elem->dim();
01600 
01601   // Clear the DOF indices vector
01602   di.clear();
01603 
01604 #ifdef DEBUG
01605   // Check that sizes match in DEBUG mode
01606   unsigned int tot_size = 0;
01607 #endif
01608 
01609   // Create a vector to indicate which
01610   // SCALAR variables have been requested
01611   std::vector<unsigned int> SCALAR_var_numbers;
01612   SCALAR_var_numbers.clear();
01613 
01614   // Get the dof numbers
01615   for (unsigned int v=0; v<n_vars; v++)
01616     if ((v == vn) || (vn == libMesh::invalid_uint))
01617     {
01618       if(this->variable(v).type().family == SCALAR)
01619       {
01620         // We asked for this variable, so add it to the vector.
01621         SCALAR_var_numbers.push_back(v);
01622 
01623 #ifdef DEBUG
01624         FEType fe_type = this->variable_type(v);
01625         tot_size += FEInterface::n_dofs(dim,
01626                                         fe_type,
01627                                         type);
01628 #endif
01629       }
01630       else
01631       if (this->variable(v).active_on_subdomain(elem->subdomain_id()))
01632         { // Do this for all the variables if one was not specified
01633           // or just for the specified variable
01634 
01635           // Increase the polynomial order on p refined elements
01636           FEType fe_type = this->variable_type(v);
01637           fe_type.order = static_cast<Order>(fe_type.order +
01638                                              elem->p_level());
01639 
01640           const bool extra_hanging_dofs =
01641             FEInterface::extra_hanging_dofs(fe_type);
01642 
01643 #ifdef DEBUG
01644           tot_size += FEInterface::n_dofs(dim,
01645                                           fe_type,
01646                                           type);
01647 #endif
01648 
01649           // Get the node-based DOF numbers
01650           for (unsigned int n=0; n<n_nodes; n++)
01651             {
01652               const Node* node      = elem->get_node(n);
01653 
01654               // There is a potential problem with h refinement.  Imagine a
01655               // quad9 that has a linear FE on it.  Then, on the hanging side,
01656               // it can falsely identify a DOF at the mid-edge node. This is why
01657               // we call FEInterface instead of node->n_comp() directly.
01658               const unsigned int nc = FEInterface::n_dofs_at_node (dim,
01659                                                                    fe_type,
01660                                                                    type,
01661                                                                    n);
01662 
01663               // If this is a non-vertex on a hanging node with extra
01664               // degrees of freedom, we use the non-vertex dofs (which
01665               // come in reverse order starting from the end, to
01666               // simplify p refinement)
01667               if (extra_hanging_dofs && !elem->is_vertex(n))
01668                 {
01669                   const int dof_offset = node->n_comp(sys_num,v) - nc;
01670 
01671                   // We should never have fewer dofs than necessary on a
01672                   // node unless we're getting indices on a parent element,
01673                   // and we should never need the indices on such a node
01674                   if (dof_offset < 0)
01675                     {
01676                       libmesh_assert(!elem->active());
01677                       di.resize(di.size() + nc, DofObject::invalid_id);
01678                     }
01679                   else
01680                     for (int i=node->n_comp(sys_num,v)-1; i>=dof_offset; i--)
01681                       {
01682                         libmesh_assert_not_equal_to (node->dof_number(sys_num,v,i),
01683                                                      DofObject::invalid_id);
01684                         di.push_back(node->dof_number(sys_num,v,i));
01685                       }
01686                 }
01687               // If this is a vertex or an element without extra hanging
01688               // dofs, our dofs come in forward order coming from the
01689               // beginning
01690               else
01691                 for (unsigned int i=0; i<nc; i++)
01692                   {
01693                     libmesh_assert_not_equal_to (node->dof_number(sys_num,v,i),
01694                                                  DofObject::invalid_id);
01695                     di.push_back(node->dof_number(sys_num,v,i));
01696                   }
01697             }
01698 
01699           // If there are any element-based DOF numbers, get them
01700           const unsigned int nc = FEInterface::n_dofs_per_elem(dim,
01701                                                                fe_type,
01702                                                                type);
01703           // We should never have fewer dofs than necessary on an
01704           // element unless we're getting indices on a parent element,
01705           // and we should never need those indices
01706           if (nc != 0)
01707             {
01708               if (elem->n_systems() > sys_num &&
01709                   nc <= elem->n_comp(sys_num,v))
01710                 {
01711                   for (unsigned int i=0; i<nc; i++)
01712                     {
01713                       libmesh_assert_not_equal_to (elem->dof_number(sys_num,v,i),
01714                                                    DofObject::invalid_id);
01715 
01716                       di.push_back(elem->dof_number(sys_num,v,i));
01717                     }
01718                 }
01719               else
01720                 {
01721                   libmesh_assert(!elem->active() || fe_type.family == LAGRANGE);
01722                   di.resize(di.size() + nc, DofObject::invalid_id);
01723                 }
01724             }
01725         }
01726       } // end loop over variables
01727 
01728   // Finally append any SCALAR dofs that we asked for.
01729   std::vector<dof_id_type> di_new;
01730   std::vector<unsigned int>::iterator it           = SCALAR_var_numbers.begin();
01731   std::vector<unsigned int>::const_iterator it_end = SCALAR_var_numbers.end();
01732   for( ; it != it_end; ++it)
01733   {
01734     this->SCALAR_dof_indices(di_new,*it);
01735     di.insert( di.end(), di_new.begin(), di_new.end());
01736   }
01737 
01738 #ifdef DEBUG
01739     libmesh_assert_equal_to (tot_size, di.size());
01740 #endif
01741 
01742   STOP_LOG("dof_indices()", "DofMap");
01743 }

DofObject * libMesh::DofMap::elem_ptr ( MeshBase mesh,
dof_id_type  i 
) const [private]

An adapter function that returns Elem pointers by index

Definition at line 266 of file dof_map.C.

References libMesh::MeshBase::elem().

Referenced by distribute_dofs().

00267 {
00268   return mesh.elem(i);
00269 }

void libMesh::ReferenceCounter::enable_print_counter_info (  )  [static, inherited]

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

Definition at line 100 of file reference_counter.C.

References libMesh::ReferenceCounter::_enable_print_counter.

00101 {
00102   _enable_print_counter = true;
00103   return;
00104 }

dof_id_type libMesh::DofMap::end_old_dof ( const processor_id_type  proc = libMesh::processor_id()  )  const [inline]

Returns the first old dof index that is after all indices local to subdomain proc. Analogous to the end() member function of STL containers.

Definition at line 431 of file dof_map.h.

References _end_old_df.

00432   { libmesh_assert_less (proc, _end_old_df.size()); return _end_old_df[proc]; }

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

Constrains the numeric vector v, which represents a solution defined on the mesh. This may need to be used after a linear solve, if your linear solver's solutions do not satisfy your DoF constraints to a tight enough tolerance.

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

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

Definition at line 1543 of file dof_map_constraints.C.

References _dof_constraints, libMesh::NumericVector< T >::close(), libMesh::NumericVector< T >::closed(), end_dof(), libMesh::err, first_dof(), libMesh::AutoPtr< Tp >::get(), libMesh::System::get_dof_map(), libMeshEnums::GHOSTED, libMesh::NumericVector< T >::localize(), n_constrained_dofs(), n_dofs(), n_local_dofs(), libMeshEnums::PARALLEL, libMeshEnums::SERIAL, libMesh::NumericVector< T >::set(), libMesh::NumericVector< T >::size(), libMesh::System::solution, and libMesh::NumericVector< T >::type().

Referenced by libMesh::__libmesh_petsc_diff_solver_jacobian(), libMesh::__libmesh_petsc_diff_solver_residual(), libMesh::ImplicitSystem::adjoint_solve(), libMesh::Problem_Interface::computeF(), libMesh::Problem_Interface::computeJacobian(), libMesh::Problem_Interface::computePreconditioner(), DMFunction_libMesh(), DMJacobian_libMesh(), libMesh::System::project_vector(), libMesh::ImplicitSystem::sensitivity_solve(), libMesh::PetscDiffSolver::solve(), libMesh::NewtonSolver::solve(), libMesh::ImplicitSystem::weighted_sensitivity_adjoint_solve(), and libMesh::ImplicitSystem::weighted_sensitivity_solve().

01546 {
01547   parallel_only();
01548 
01549   if (!this->n_constrained_dofs())
01550     return;
01551 
01552   START_LOG("enforce_constraints_exactly()","DofMap");
01553 
01554   if (!v)
01555     v = system.solution.get();
01556 
01557   NumericVector<Number> *v_local  = NULL; // will be initialized below
01558   NumericVector<Number> *v_global = NULL; // will be initialized below
01559   AutoPtr<NumericVector<Number> > v_built;
01560   if (v->type() == SERIAL)
01561     {
01562       v_built = NumericVector<Number>::build();
01563       v_built->init(this->n_dofs(), this->n_local_dofs(), true, PARALLEL);
01564       v_built->close();
01565 
01566       for (dof_id_type i=v_built->first_local_index();
01567            i<v_built->last_local_index(); i++)
01568         v_built->set(i, (*v)(i));
01569       v_built->close();
01570       v_global = v_built.get();
01571 
01572       v_local = v;
01573       libmesh_assert (v_local->closed());
01574     }
01575   else if (v->type() == PARALLEL)
01576     {
01577       v_built = NumericVector<Number>::build();
01578       v_built->init (v->size(), v->size(), true, SERIAL);
01579       v->localize(*v_built);
01580       v_built->close();
01581       v_local = v_built.get();
01582 
01583       v_global = v;
01584     }
01585   else if (v->type() == GHOSTED)
01586     {
01587       v_local = v;
01588       v_global = v;
01589     }
01590   else // unknown v->type()
01591     {
01592       libMesh::err << "ERROR: Unknown v->type() == " << v->type()
01593                     << std::endl;
01594       libmesh_error();
01595     }
01596 
01597   // We should never hit these asserts because we should error-out in
01598   // else clause above.  Just to be sure we don't try to use v_local
01599   // and v_global uninitialized...
01600   libmesh_assert(v_local);
01601   libmesh_assert(v_global);
01602   libmesh_assert_equal_to (this, &(system.get_dof_map()));
01603 
01604   DofConstraints::const_iterator c_it = _dof_constraints.begin();
01605   const DofConstraints::const_iterator c_end = _dof_constraints.end();
01606 
01607   for ( ; c_it != c_end; ++c_it)
01608     {
01609       dof_id_type constrained_dof = c_it->first;
01610       if (constrained_dof < this->first_dof() ||
01611           constrained_dof >= this->end_dof())
01612         continue;
01613 
01614       const DofConstraintRow constraint_row = c_it->second.first;
01615 
01616       Number exact_value = homogeneous ?
01617         0 : c_it->second.second;
01618       for (DofConstraintRow::const_iterator
01619            j=constraint_row.begin(); j != constraint_row.end();
01620            ++j)
01621         exact_value += j->second * (*v_local)(j->first);
01622 
01623       v_global->set(constrained_dof, exact_value);
01624     }
01625 
01626   // If the old vector was serial, we probably need to send our values
01627   // to other processors
01628   if (v->type() == SERIAL)
01629     {
01630 #ifndef NDEBUG
01631       v_global->close();
01632 #endif
01633       v_global->localize (*v);
01634     }
01635   v->close();
01636 
01637   STOP_LOG("enforce_constraints_exactly()","DofMap");
01638 }

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

Builds the local element vector Ue from the global vector Ug, accounting for any constrained degrees of freedom. For an element without constrained degrees of freedom this is the trivial mapping $ Ue[i] = Ug[dof_indices[i]] $

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

Definition at line 1501 of file dof_map.C.

References build_constraint_matrix_and_vector(), libMesh::DenseVectorBase< T >::el(), libMesh::NumericVector< T >::first_local_index(), is_constrained_dof(), libMesh::NumericVector< T >::last_local_index(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::NumericVector< T >::size(), libMesh::DenseVectorBase< T >::size(), and libMesh::DenseVectorBase< T >::zero().

01504 {
01505 #ifdef LIBMESH_ENABLE_AMR
01506 
01507   // Trivial mapping
01508   libmesh_assert_equal_to (dof_indices_in.size(), Ue.size());
01509   bool has_constrained_dofs = false;
01510 
01511   for (unsigned int il=0; 
01512        il != libmesh_cast_int<unsigned int>(dof_indices_in.size()); il++)
01513     {
01514       const dof_id_type ig = dof_indices_in[il];
01515 
01516       if (this->is_constrained_dof (ig)) has_constrained_dofs = true;
01517 
01518       libmesh_assert_less (ig, Ug.size());
01519 
01520       Ue.el(il) = Ug(ig);
01521     }
01522 
01523   // If the element has any constrained DOFs then we need
01524   // to account for them in the mapping.  This will handle
01525   // the case that the input vector is not constrained.
01526   if (has_constrained_dofs)
01527     {
01528       // Copy the input DOF indices.
01529       std::vector<dof_id_type> constrained_dof_indices(dof_indices_in);
01530 
01531       DenseMatrix<Number> C;
01532       DenseVector<Number> H;
01533         
01534       this->build_constraint_matrix_and_vector (C, H, constrained_dof_indices);
01535 
01536       libmesh_assert_equal_to (dof_indices_in.size(), C.m());
01537       libmesh_assert_equal_to (constrained_dof_indices.size(), C.n());
01538 
01539       // zero-out Ue
01540       Ue.zero();
01541 
01542       // compute Ue = C Ug, with proper mapping.
01543       const unsigned int n_original_dofs =
01544         libmesh_cast_int<unsigned int>(dof_indices_in.size());
01545       for (unsigned int i=0; i != n_original_dofs; i++)
01546         {
01547           Ue.el(i) = H(i);
01548           
01549           const unsigned int n_constrained =
01550             libmesh_cast_int<unsigned int>(constrained_dof_indices.size());
01551           for (unsigned int j=0; j<n_constrained; j++)
01552             {
01553               const dof_id_type jg = constrained_dof_indices[j];
01554               
01555 //          If Ug is a serial or ghosted vector, then this assert is
01556 //          overzealous.  If Ug is a parallel vector, then this assert
01557 //          is redundant.
01558 //          libmesh_assert ((jg >= Ug.first_local_index()) &&
01559 //                  (jg <  Ug.last_local_index()));
01560 
01561               Ue.el(i) += C(i,j)*Ug(jg);
01562             }
01563         }
01564     }
01565 
01566 #else
01567 
01568   // Trivial mapping
01569 
01570   const unsigned int n_original_dofs =
01571     libmesh_cast_int<unsigned int>(dof_indices_in.size());
01572 
01573   libmesh_assert_equal_to (n_original_dofs, Ue.size());
01574 
01575   for (unsigned int il=0; il<n_original_dofs; il++)
01576     {
01577       const dof_id_type ig = dof_indices_in[il];
01578 
01579       libmesh_assert ((ig >= Ug.first_local_index()) && (ig <  Ug.last_local_index()));
01580 
01581       Ue.el(il) = Ug(ig);
01582     }
01583 
01584 #endif
01585 }

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

Finds all the DofObjects associated with the set in objs. This will account for off-element couplings via hanging nodes.

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

Finds all the DOFS associated with the element DOFs elem_dofs. This will account for off-element couplings via hanging nodes.

Definition at line 2077 of file dof_map.C.

References _dof_constraints, and is_constrained_dof().

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

02078 {
02079   typedef std::set<dof_id_type> RCSet;
02080 
02081   // First insert the DOFS we already depend on into the set.
02082   RCSet dof_set (elem_dofs.begin(), elem_dofs.end());
02083 
02084   bool done = true;
02085 
02086   // Next insert any dofs those might be constrained in terms
02087   // of.  Note that in this case we may not be done:  Those may
02088   // in turn depend on others.  So, we need to repeat this process
02089   // in that case until the system depends only on unconstrained
02090   // degrees of freedom.
02091   for (unsigned int i=0; i<elem_dofs.size(); i++)
02092     if (this->is_constrained_dof(elem_dofs[i]))
02093       {
02094         // If the DOF is constrained
02095         DofConstraints::const_iterator
02096           pos = _dof_constraints.find(elem_dofs[i]);
02097 
02098         libmesh_assert (pos != _dof_constraints.end());
02099 
02100         const DofConstraintRow& constraint_row = pos->second.first;
02101 
02102 // adaptive p refinement currently gives us lots of empty constraint
02103 // rows - we should optimize those DoFs away in the future.  [RHS]
02104 //      libmesh_assert (!constraint_row.empty());
02105 
02106         DofConstraintRow::const_iterator it     = constraint_row.begin();
02107         DofConstraintRow::const_iterator it_end = constraint_row.end();
02108 
02109 
02110         // Add the DOFs this dof is constrained in terms of.
02111         // note that these dofs might also be constrained, so
02112         // we will need to call this function recursively.
02113         for ( ; it != it_end; ++it)
02114           if (!dof_set.count (it->first))
02115             {
02116               dof_set.insert (it->first);
02117               done = false;
02118             }
02119         }
02120 
02121 
02122   // If not done then we need to do more work
02123   // (obviously :-) )!
02124   if (!done)
02125     {
02126       // Fill the vector with the contents of the set
02127       elem_dofs.clear();
02128       elem_dofs.insert (elem_dofs.end(),
02129                         dof_set.begin(), dof_set.end());
02130 
02131 
02132       // May need to do this recursively.  It is possible
02133       // that we just replaced a constrained DOF with another
02134       // constrained DOF.
02135       this->find_connected_dofs (elem_dofs);
02136 
02137     } // end if (!done)
02138 }

dof_id_type libMesh::DofMap::first_old_dof ( const processor_id_type  proc = libMesh::processor_id()  )  const [inline]

Returns the first old dof index that is local to partition proc.

Definition at line 404 of file dof_map.h.

References _first_old_df.

00405   { libmesh_assert_less (proc, _first_old_df.size()); return _first_old_df[proc]; }

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

Definition at line 786 of file dof_map.h.

References _dirichlet_boundaries.

00787     {
00788       return _dirichlet_boundaries;
00789     }

std::string libMesh::ReferenceCounter::get_info (  )  [static, inherited]

Gets a string containing the reference information.

Definition at line 47 of file reference_counter.C.

References libMesh::ReferenceCounter::_counts, and libMesh::Quality::name().

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

00048 {
00049 #if defined(LIBMESH_ENABLE_REFERENCE_COUNTING) && defined(DEBUG)
00050 
00051   std::ostringstream oss;
00052 
00053   oss << '\n'
00054       << " ---------------------------------------------------------------------------- \n"
00055       << "| Reference count information                                                |\n"
00056       << " ---------------------------------------------------------------------------- \n";
00057 
00058   for (Counts::iterator it = _counts.begin();
00059        it != _counts.end(); ++it)
00060     {
00061       const std::string name(it->first);
00062       const unsigned int creations    = it->second.first;
00063       const unsigned int destructions = it->second.second;
00064 
00065       oss << "| " << name << " reference count information:\n"
00066           << "|  Creations:    " << creations    << '\n'
00067           << "|  Destructions: " << destructions << '\n';
00068     }
00069 
00070   oss << " ---------------------------------------------------------------------------- \n";
00071 
00072   return oss.str();
00073 
00074 #else
00075 
00076   return "";
00077 
00078 #endif
00079 }

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

Gets summary info about the sparsity bandwidth and constraints.

Definition at line 2780 of file dof_map.C.

References _dof_constraints, _matrices, _n_nz, _n_oz, _node_constraints, libMesh::CommWorld, end, end_dof(), first_dof(), libMesh::Parallel::Communicator::max(), std::max(), libMesh::processor_id(), libMesh::DofObject::processor_id(), and libMesh::Parallel::Communicator::sum().

Referenced by libMesh::System::get_info(), and print_info().

02781 {
02782   std::ostringstream os;
02783 
02784   // If we didn't calculate the exact sparsity pattern, the threaded
02785   // sparsity pattern assembly may have just given us an upper bound
02786   // on sparsity.
02787   const char* may_equal = " <= ";
02788 
02789   // If we calculated the exact sparsity pattern, then we can report
02790   // exact bandwidth figures:
02791   std::vector<SparseMatrix<Number>* >::const_iterator
02792     pos = _matrices.begin(),
02793     end = _matrices.end();
02794 
02795   for (; pos != end; ++pos)
02796     if ((*pos)->need_full_sparsity_pattern())
02797       may_equal = " = ";
02798 
02799   dof_id_type max_n_nz = 0, max_n_oz = 0;
02800   long double avg_n_nz = 0, avg_n_oz = 0;
02801 
02802   if (_n_nz)
02803     {
02804       for (std::size_t i = 0; i != _n_nz->size(); ++i)
02805         {
02806           max_n_nz = std::max(max_n_nz, (*_n_nz)[i]);
02807           avg_n_nz += (*_n_nz)[i];
02808         }
02809 
02810       std::size_t n_nz_size = _n_nz->size();
02811 
02812       CommWorld.max(max_n_nz);
02813       CommWorld.sum(avg_n_nz);
02814       CommWorld.sum(n_nz_size);
02815 
02816       avg_n_nz /= std::max(n_nz_size,std::size_t(1));
02817 
02818       libmesh_assert(_n_oz);
02819 
02820       for (std::size_t i = 0; i != (*_n_oz).size(); ++i)
02821         {
02822           max_n_oz = std::max(max_n_oz, (*_n_oz)[i]);
02823           avg_n_oz += (*_n_oz)[i];
02824         }
02825 
02826       std::size_t n_oz_size = _n_oz->size();
02827 
02828       CommWorld.max(max_n_oz);
02829       CommWorld.sum(avg_n_oz);
02830       CommWorld.sum(n_oz_size);
02831 
02832       avg_n_oz /= std::max(n_oz_size,std::size_t(1));
02833     }
02834 
02835   os << "    DofMap Sparsity\n      Average  On-Processor Bandwidth"
02836      << may_equal << avg_n_nz << '\n';
02837 
02838   os << "      Average Off-Processor Bandwidth"
02839      << may_equal << avg_n_oz << '\n';
02840 
02841   os << "      Maximum  On-Processor Bandwidth"
02842      << may_equal << max_n_nz << '\n';
02843 
02844   os << "      Maximum Off-Processor Bandwidth"
02845      << may_equal << max_n_oz << std::endl;
02846 
02847 #ifdef LIBMESH_ENABLE_CONSTRAINTS
02848 
02849   std::size_t n_constraints = 0, max_constraint_length = 0,
02850               n_rhss = 0;
02851   long double avg_constraint_length = 0.;
02852 
02853   for (DofConstraints::const_iterator it=_dof_constraints.begin();
02854        it != _dof_constraints.end(); ++it)
02855     {
02856       // Only count local constraints, then sum later
02857       const dof_id_type constrained_dof = it->first;
02858       if (constrained_dof < this->first_dof() ||
02859           constrained_dof >= this->end_dof())
02860         continue;
02861 
02862       const DofConstraintRow& row = it->second.first;
02863       std::size_t rowsize = row.size();
02864 
02865       max_constraint_length = std::max(max_constraint_length,
02866                                        rowsize);
02867       avg_constraint_length += rowsize;
02868       n_constraints++;
02869 
02870       if (it->second.second != Number(0))
02871         n_rhss++;
02872     }
02873 
02874   CommWorld.sum(n_constraints);
02875   CommWorld.sum(n_rhss);
02876   CommWorld.sum(avg_constraint_length);
02877   CommWorld.max(max_constraint_length);
02878 
02879   os << "    DofMap Constraints\n      Number of DoF Constraints = "
02880      << n_constraints;
02881   if (n_rhss)
02882     os << '\n'
02883        << "      Number of Heterogenous Constraints= " << n_rhss;
02884   if (n_constraints)
02885     {
02886       avg_constraint_length /= n_constraints;
02887 
02888       os << '\n'
02889          << "      Average DoF Constraint Length= " << avg_constraint_length;
02890     }
02891 
02892 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02893   std::size_t n_node_constraints = 0, max_node_constraint_length = 0,
02894               n_node_rhss = 0;
02895   long double avg_node_constraint_length = 0.;
02896 
02897   for (NodeConstraints::const_iterator it=_node_constraints.begin();
02898        it != _node_constraints.end(); ++it)
02899     {
02900       // Only count local constraints, then sum later
02901       const Node *node = it->first;
02902       if (node->processor_id() != libMesh::processor_id())
02903         continue;
02904 
02905       const NodeConstraintRow& row = it->second.first;
02906       std::size_t rowsize = row.size();
02907 
02908       max_node_constraint_length = std::max(max_node_constraint_length,
02909                                             rowsize);
02910       avg_node_constraint_length += rowsize;
02911       n_node_constraints++;
02912 
02913       if (it->second.second != Point(0))
02914         n_node_rhss++;
02915     }
02916 
02917   CommWorld.sum(n_node_constraints);
02918   CommWorld.sum(n_node_rhss);
02919   CommWorld.sum(avg_node_constraint_length);
02920   CommWorld.max(max_node_constraint_length);
02921 
02922   os << "\n      Number of Node Constraints = " << n_node_constraints;
02923   if (n_node_rhss)
02924     os << '\n'
02925        << "      Number of Heterogenous Node Constraints= " << n_node_rhss;
02926   if (n_node_constraints)
02927     {
02928       avg_node_constraint_length /= n_node_constraints;
02929       os << "\n      Maximum Node Constraint Length= " << max_node_constraint_length
02930          << '\n'
02931          << "      Average Node Constraint Length= " << avg_node_constraint_length;
02932     }
02933 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02934 
02935   os << std::endl;
02936 
02937 #endif // LIBMESH_ENABLE_CONSTRAINTS
02938 
02939   return os.str();
02940 }

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

Gets a string reporting all DoF and Node constraints local to this processor. If print_nonlocal is true, then nonlocal constraints which are locally known are included.

Definition at line 1027 of file dof_map_constraints.C.

References _dof_constraints, _node_constraints, end_dof(), first_dof(), libMesh::DofObject::id(), libMesh::processor_id(), and libMesh::DofObject::processor_id().

Referenced by print_dof_constraints().

01028 {
01029   std::ostringstream os;
01030 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
01031   if (print_nonlocal)
01032     os << "All ";
01033   else
01034     os << "Local ";
01035 
01036   os << "Node Constraints:"
01037      << std::endl;
01038 
01039   for (NodeConstraints::const_iterator it=_node_constraints.begin();
01040        it != _node_constraints.end(); ++it)
01041     {
01042       const Node *node = it->first;
01043 
01044       // Skip non-local nodes if requested
01045       if (!print_nonlocal &&
01046           node->processor_id() != libMesh::processor_id())
01047         continue;
01048 
01049       const NodeConstraintRow& row = it->second.first;
01050       const Point& offset = it->second.second;
01051 
01052       os << "Constraints for Node id " << node->id()
01053          << ": \t";
01054 
01055       for (NodeConstraintRow::const_iterator pos=row.begin();
01056            pos != row.end(); ++pos)
01057         os << " (" << pos->first->id() << ","
01058            << pos->second << ")\t";
01059 
01060       os << "rhs: " << offset;
01061 
01062       os << std::endl;
01063     }
01064 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
01065 
01066   if (print_nonlocal)
01067     os << "All ";
01068   else
01069     os << "Local ";
01070 
01071   os << "DoF Constraints:"
01072      << std::endl;
01073 
01074   for (DofConstraints::const_iterator it=_dof_constraints.begin();
01075        it != _dof_constraints.end(); ++it)
01076     {
01077       const dof_id_type i = it->first;
01078 
01079       // Skip non-local dofs if requested
01080       if (!print_nonlocal &&
01081           ((i < this->first_dof()) ||
01082            (i >= this->end_dof())))
01083         continue;
01084 
01085       const DofConstraintRow& row = it->second.first;
01086       const Number rhs = it->second.second;
01087 
01088       os << "Constraints for DoF " << i
01089          << ": \t";
01090 
01091       for (DofConstraintRow::const_iterator pos=row.begin();
01092            pos != row.end(); ++pos)
01093         os << " (" << pos->first << ","
01094            << pos->second << ")\t";
01095 
01096       os << "rhs: " << rhs;
01097 
01098       os << std::endl;
01099     }
01100 
01101   return os.str();
01102 }

const std::vector<dof_id_type>& libMesh::DofMap::get_n_nz (  )  const [inline]

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

Definition at line 296 of file dof_map.h.

References _n_nz.

Referenced by libMesh::PetscMatrix< T >::init(), libMesh::LaspackMatrix< T >::init(), and libMesh::EpetraMatrix< T >::update_sparsity_pattern().

00296                                                  {
00297     libmesh_assert(_n_nz);
00298     return *_n_nz;
00299   }

const std::vector<dof_id_type>& libMesh::DofMap::get_n_oz (  )  const [inline]

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

Definition at line 307 of file dof_map.h.

References _n_oz.

Referenced by libMesh::PetscMatrix< T >::init(), libMesh::LaspackMatrix< T >::init(), and libMesh::EpetraMatrix< T >::update_sparsity_pattern().

00307                                                  {
00308     libmesh_assert(_n_oz);
00309     return *_n_oz;
00310   }

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

Definition at line 763 of file dof_map.h.

References _periodic_boundaries.

00764     {
00765       return _periodic_boundaries;
00766     }

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

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

Definition at line 288 of file dof_map.h.

References _send_list.

Referenced by libMesh::UnsteadySolver::adjoint_advance_timestep(), libMesh::UnsteadySolver::advance_timestep(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::UnsteadySolver::init_data(), libMesh::System::re_update(), libMesh::UnsteadySolver::reinit(), and libMesh::UnsteadySolver::retrieve_timestep().

00288 { return _send_list; }

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

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

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

Definition at line 1260 of file dof_map_constraints.C.

References libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::right_multiply(), libMesh::DenseVector< T >::size(), libMesh::DenseMatrix< T >::vector_mult(), and libMesh::DenseMatrix< T >::vector_mult_transpose().

01264 {
01265   libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
01266   libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
01267   libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
01268 
01269   // check for easy return
01270   if (this->_dof_constraints.empty())
01271     return;
01272 
01273   // The constrained matrix is built up as C^T K C.
01274   // The constrained RHS is built up as C^T (F - K H)
01275   DenseMatrix<Number> C;
01276   DenseVector<Number> H;
01277 
01278   this->build_constraint_matrix_and_vector (C, H, elem_dofs);
01279 
01280   START_LOG("hetero_cnstrn_elem_mat_vec()", "DofMap");
01281 
01282   // It is possible that the matrix is not constrained at all.
01283   if ((C.m() == matrix.m()) &&
01284       (C.n() == elem_dofs.size())) // It the matrix is constrained
01285     {
01286       // Compute matrix/vector product K H
01287       DenseVector<Number> KH;
01288       matrix.vector_mult(KH, H);
01289 
01290       // Compute the matrix-vector product C^T (F - KH)
01291       DenseVector<Number> F_minus_KH(rhs);
01292       F_minus_KH -= KH;
01293       C.vector_mult_transpose(rhs, F_minus_KH);
01294 
01295       // Compute the matrix-matrix-matrix product C^T K C
01296       matrix.left_multiply_transpose  (C);
01297       matrix.right_multiply (C);
01298 
01299       libmesh_assert_equal_to (matrix.m(), matrix.n());
01300       libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
01301       libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
01302 
01303       for (unsigned int i=0; i<elem_dofs.size(); i++)
01304         if (this->is_constrained_dof(elem_dofs[i]))
01305           {
01306             for (unsigned int j=0; j<matrix.n(); j++)
01307               matrix(i,j) = 0.;
01308 
01309             // If the DOF is constrained
01310             matrix(i,i) = 1.;
01311 
01312             // This will put a nonsymmetric entry in the constraint
01313             // row to ensure that the linear system produces the
01314             // correct value for the constrained DOF.
01315             if (asymmetric_constraint_rows)
01316               {
01317                 DofConstraints::const_iterator
01318                   pos = _dof_constraints.find(elem_dofs[i]);
01319 
01320                 libmesh_assert (pos != _dof_constraints.end());
01321 
01322                 const DofConstraintRow& constraint_row = pos->second.first;
01323 
01324 // p refinement creates empty constraint rows
01325 //          libmesh_assert (!constraint_row.empty());
01326 
01327                 for (DofConstraintRow::const_iterator
01328                        it=constraint_row.begin(); it != constraint_row.end();
01329                      ++it)
01330                   for (unsigned int j=0; j<elem_dofs.size(); j++)
01331                     if (elem_dofs[j] == it->first)
01332                       matrix(i,j) = -it->second;
01333 
01334                 rhs(i) = pos->second.second;
01335               }
01336             else
01337               rhs(i) = 0.;
01338           }
01339 
01340     } // end if is constrained...
01341 
01342   STOP_LOG("hetero_cnstrn_elem_mat_vec()", "DofMap");
01343 }

void libMesh::ReferenceCounter::increment_constructor_count ( const std::string &  name  )  [inline, protected, inherited]

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

Definition at line 163 of file reference_counter.h.

References libMesh::ReferenceCounter::_counts, and libMesh::Threads::spin_mtx.

Referenced by libMesh::ReferenceCountedObject< RBParametrized >::ReferenceCountedObject().

00164 {
00165   Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
00166   std::pair<unsigned int, unsigned int>& p = _counts[name];
00167 
00168   p.first++;
00169 }

void libMesh::ReferenceCounter::increment_destructor_count ( const std::string &  name  )  [inline, protected, inherited]

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

Definition at line 176 of file reference_counter.h.

References libMesh::ReferenceCounter::_counts, and libMesh::Threads::spin_mtx.

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

00177 {
00178   Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
00179   std::pair<unsigned int, unsigned int>& p = _counts[name];
00180 
00181   p.second++;
00182 }

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

Invalidates all active DofObject dofs for this system

Definition at line 777 of file dof_map.C.

References libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::MeshBase::nodes_begin(), libMesh::MeshBase::nodes_end(), and sys_number().

Referenced by distribute_dofs(), and reinit().

00778 {
00779   const unsigned int sys_num = this->sys_number();
00780 
00781   // All the nodes
00782   MeshBase::node_iterator       node_it  = mesh.nodes_begin();
00783   const MeshBase::node_iterator node_end = mesh.nodes_end();
00784 
00785   for ( ; node_it != node_end; ++node_it)
00786     (*node_it)->invalidate_dofs(sys_num);
00787 
00788   // All the elements
00789   MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
00790   const MeshBase::element_iterator elem_end = mesh.active_elements_end();
00791 
00792   for ( ; elem_it != elem_end; ++elem_it)
00793     (*elem_it)->invalidate_dofs(sys_num);
00794 }

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

Matrices should not be attached more than once. We can test for an already-attached matrix if necessary using is_attached

Definition at line 251 of file dof_map.C.

References _matrices.

Referenced by libMesh::ImplicitSystem::init_matrices().

00252 {
00253   return (std::find(_matrices.begin(), _matrices.end(),
00254                             &matrix) != _matrices.end());
00255 }

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

Referenced by allgather_recursive_constraints(), and scatter_constraints().

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

Definition at line 183 of file dof_map.C.

References _periodic_boundaries.

00184 {
00185   if (_periodic_boundaries->count(boundaryid) != 0)
00186     return true;
00187 
00188   return false;
00189 }

dof_id_type libMesh::DofMap::last_dof ( const processor_id_type  proc = libMesh::processor_id()  )  const [inline]

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

References _end_df.

00413                                                                                    {
00414     libmesh_deprecated();
00415     libmesh_assert_less (proc, _end_df.size());
00416     return libmesh_cast_int<dof_id_type>(_end_df[proc] - 1);
00417   }

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

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

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

Definition at line 1643 of file dof_map_constraints.C.

References _dof_constraints, std::abs(), libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), build_constraint_matrix(), libMesh::NumericVector< T >::closed(), dof_indices(), libMesh::NumericVector< T >::first_local_index(), libMesh::AutoPtr< Tp >::get(), libMesh::System::get_dof_map(), libMesh::System::get_mesh(), is_constrained_dof(), libMesh::NumericVector< T >::last_local_index(), libMesh::DenseMatrixBase< T >::m(), std::max(), mesh, libMesh::DenseMatrixBase< T >::n(), libMesh::Real, and libMesh::System::solution.

01645 {
01646   if (!v)
01647     v = system.solution.get();
01648   NumericVector<Number> &vec = *v;
01649 
01650   // We'll assume the vector is closed
01651   libmesh_assert (vec.closed());
01652 
01653   Real max_absolute_error = 0., max_relative_error = 0.;
01654 
01655   const MeshBase &mesh = system.get_mesh();
01656 
01657   libmesh_assert_equal_to (this, &(system.get_dof_map()));
01658 
01659   // indices on each element
01660   std::vector<dof_id_type> local_dof_indices;
01661 
01662   MeshBase::const_element_iterator       elem_it  =
01663     mesh.active_local_elements_begin();
01664   const MeshBase::const_element_iterator elem_end =
01665     mesh.active_local_elements_end();
01666 
01667   for ( ; elem_it != elem_end; ++elem_it)
01668     {
01669       const Elem* elem = *elem_it;
01670 
01671       this->dof_indices(elem, local_dof_indices);
01672       std::vector<dof_id_type> raw_dof_indices = local_dof_indices;
01673 
01674       // Constraint matrix for each element
01675       DenseMatrix<Number> C;
01676 
01677       this->build_constraint_matrix (C, local_dof_indices);
01678 
01679       // Continue if the element is unconstrained
01680       if (!C.m())
01681         continue;
01682 
01683       libmesh_assert_equal_to (C.m(), raw_dof_indices.size());
01684       libmesh_assert_equal_to (C.n(), local_dof_indices.size());
01685 
01686       for (unsigned int i=0; i!=C.m(); ++i)
01687         {
01688           // Recalculate any constrained dof owned by this processor
01689           dof_id_type global_dof = raw_dof_indices[i];
01690           if (this->is_constrained_dof(global_dof) &&
01691               global_dof >= vec.first_local_index() &&
01692               global_dof < vec.last_local_index())
01693           {
01694             DofConstraints::const_iterator
01695                   pos = _dof_constraints.find(global_dof);
01696 
01697             libmesh_assert (pos != _dof_constraints.end());
01698 
01699             Number exact_value = pos->second.second;
01700             for (unsigned int j=0; j!=C.n(); ++j)
01701               {
01702                 if (local_dof_indices[j] != global_dof)
01703                   exact_value += C(i,j) *
01704                     vec(local_dof_indices[j]);
01705               }
01706 
01707             max_absolute_error = std::max(max_absolute_error,
01708               std::abs(vec(global_dof) - exact_value));
01709             max_relative_error = std::max(max_relative_error,
01710               std::abs(vec(global_dof) - exact_value)
01711               / std::abs(exact_value));
01712           }
01713         }
01714     }
01715 
01716   return std::pair<Real, Real>(max_absolute_error, max_relative_error);
01717 }

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

Definition at line 835 of file dof_map_constraints.C.

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

Referenced by enforce_constraints_exactly().

00836 {
00837   parallel_only();
00838 
00839   dof_id_type nc_dofs = this->n_local_constrained_dofs();
00840   CommWorld.sum(nc_dofs);
00841   return nc_dofs;
00842 }

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

Definition at line 506 of file dof_map.h.

References _node_constraints.

00507   { return libmesh_cast_int<dof_id_type>(_node_constraints.size()); }

dof_id_type libMesh::DofMap::n_dofs_on_processor ( const processor_id_type  proc  )  const [inline]

Returns the number of degrees of freedom on partition proc.

Definition at line 389 of file dof_map.h.

References _end_df, and _first_df.

Referenced by libMesh::PetscMatrix< T >::init(), libMesh::LaspackMatrix< T >::init(), libMesh::SparsityPattern::Build::join(), n_local_dofs(), libMesh::SparsityPattern::Build::operator()(), libMesh::SparsityPattern::Build::parallel_sync(), and libMesh::EpetraMatrix< T >::update_sparsity_pattern().

00389                                                                       {
00390     libmesh_assert_less (proc, _first_df.size());
00391     return libmesh_cast_int<dof_id_type>(_end_df[proc] - _first_df[proc]);
00392   }

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

Definition at line 845 of file dof_map_constraints.C.

References _dof_constraints, end_dof(), and first_dof().

Referenced by n_constrained_dofs().

00846 {
00847   const DofConstraints::const_iterator lower =
00848     _dof_constraints.lower_bound(this->first_dof()),
00849                                        upper =
00850     _dof_constraints.upper_bound(this->end_dof()-1);
00851 
00852   return std::distance(lower, upper);
00853 }

dof_id_type libMesh::DofMap::n_local_dofs (  )  const [inline]
Returns:
the number of degrees of freedom on this processor.

Definition at line 383 of file dof_map.h.

References n_dofs_on_processor(), and libMesh::processor_id().

Referenced by enforce_constraints_exactly().

00384   { return this->n_dofs_on_processor (libMesh::processor_id()); }

static unsigned int libMesh::ReferenceCounter::n_objects (  )  [inline, static, inherited]

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

Definition at line 79 of file reference_counter.h.

References libMesh::ReferenceCounter::_n_objects.

00080   { return _n_objects; }

dof_id_type libMesh::DofMap::n_old_dofs (  )  const [inline]
Returns:
the total number of degrees of freedom on old_dof_objects

Definition at line 822 of file dof_map.h.

References _n_old_dfs.

00822 { return _n_old_dfs; }

dof_id_type libMesh::DofMap::n_SCALAR_dofs (  )  const [inline]
Returns:
the number of SCALAR dofs.

Definition at line 378 of file dof_map.h.

References _n_SCALAR_dofs.

00378 { return _n_SCALAR_dofs; }

unsigned int libMesh::DofMap::n_variable_groups (  )  const [inline]

Returns the number of variables in the global solution vector. Defaults to 1, should be 1 for a scalar equation, 3 for 2D incompressible Navier Stokes (u,v,p), etc...

Definition at line 359 of file dof_map.h.

References _variable_groups.

Referenced by distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), reinit(), and set_nonlocal_dof_objects().

00360   { return libmesh_cast_int<unsigned int>(_variable_groups.size()); }

unsigned int libMesh::DofMap::n_variables (  )  const [inline]

Returns the number of variables in the global solution vector. Defaults to 1, should be 1 for a scalar equation, 3 for 2D incompressible Navier Stokes (u,v,p), etc...

Definition at line 367 of file dof_map.h.

References _variables.

Referenced by create_dof_constraints(), DMLibMeshSetSystem(), dof_indices(), old_dof_indices(), libMesh::SparsityPattern::Build::operator()(), and use_coupled_neighbor_dofs().

00368   { return libmesh_cast_int<unsigned int>(_variables.size()); }

NodeConstraints::const_iterator libMesh::DofMap::node_constraint_rows_begin (  )  const [inline]

Returns an iterator pointing to the first Node constraint row

Definition at line 571 of file dof_map.h.

References _node_constraints.

00572     { return _node_constraints.begin(); }

NodeConstraints::const_iterator libMesh::DofMap::node_constraint_rows_end (  )  const [inline]

Returns an iterator pointing just past the last Node constraint row

Definition at line 577 of file dof_map.h.

References _node_constraints.

00578     { return _node_constraints.end(); }

DofObject * libMesh::DofMap::node_ptr ( MeshBase mesh,
dof_id_type  i 
) const [private]

An adapter function that returns Node pointers by index

Definition at line 259 of file dof_map.C.

References libMesh::MeshBase::node_ptr().

Referenced by distribute_dofs().

00260 {
00261   return mesh.node_ptr(i);
00262 }

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

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

Definition at line 1835 of file dof_map.C.

References libMesh::Elem::active(), libMesh::Elem::dim(), libMesh::DofObject::dof_number(), libMesh::FEInterface::extra_hanging_dofs(), libMesh::FEType::family, libMesh::Elem::get_node(), libMesh::DofObject::invalid_id, libMesh::invalid_uint, libMesh::Elem::is_vertex(), libMesh::Elem::JUST_COARSENED, libMesh::Elem::JUST_REFINED, libMeshEnums::LAGRANGE, libMesh::DofObject::n_comp(), n_dofs(), libMesh::FEInterface::n_dofs_at_node(), libMesh::FEInterface::n_dofs_per_elem(), libMesh::Elem::n_nodes(), n_nodes, libMesh::DofObject::n_systems(), n_variables(), n_vars, libMesh::DofObject::old_dof_object, libMesh::FEType::order, libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::Elem::refinement_flag(), libMeshEnums::SCALAR, SCALAR_dof_indices(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::Elem::type(), variable(), and variable_type().

Referenced by libMesh::FEGenericBase< OutputType >::coarsened_dof_values().

01838 {
01839   START_LOG("old_dof_indices()", "DofMap");
01840 
01841   libmesh_assert(elem);
01842   libmesh_assert(elem->old_dof_object);
01843 
01844 
01845   const unsigned int n_nodes = elem->n_nodes();
01846   const ElemType type        = elem->type();
01847   const unsigned int sys_num = this->sys_number();
01848   const unsigned int n_vars  = this->n_variables();
01849   const unsigned int dim     = elem->dim();
01850 
01851   // Clear the DOF indices vector.
01852   di.clear();
01853 
01854 #ifdef DEBUG
01855   // Check that sizes match
01856   unsigned int tot_size = 0;
01857 #endif
01858 
01859   // Create a vector to indicate which
01860   // SCALAR variables have been requested
01861   std::vector<unsigned int> SCALAR_var_numbers;
01862   SCALAR_var_numbers.clear();
01863 
01864   // Get the dof numbers
01865   for (unsigned int v=0; v<n_vars; v++)
01866     if ((v == vn) || (vn == libMesh::invalid_uint))
01867     {
01868       if(this->variable(v).type().family == SCALAR)
01869         {
01870           // We asked for this variable, so add it to the vector.
01871           SCALAR_var_numbers.push_back(v);
01872 
01873 #ifdef DEBUG
01874           FEType fe_type = this->variable_type(v);
01875           tot_size += FEInterface::n_dofs(dim,
01876                                           fe_type,
01877                                           type);
01878 #endif
01879         }
01880       else
01881       if (this->variable(v).active_on_subdomain(elem->subdomain_id()))
01882         { // Do this for all the variables if one was not specified
01883           // or just for the specified variable
01884 
01885           // Increase the polynomial order on p refined elements,
01886           // but make sure you get the right polynomial order for
01887           // the OLD degrees of freedom
01888           int p_adjustment = 0;
01889           if (elem->p_refinement_flag() == Elem::JUST_REFINED)
01890             {
01891               libmesh_assert_greater (elem->p_level(), 0);
01892               p_adjustment = -1;
01893             }
01894           else if (elem->p_refinement_flag() == Elem::JUST_COARSENED)
01895             {
01896               p_adjustment = 1;
01897             }
01898           FEType fe_type = this->variable_type(v);
01899           fe_type.order = static_cast<Order>(fe_type.order +
01900                                              elem->p_level() +
01901                                              p_adjustment);
01902 
01903           const bool extra_hanging_dofs =
01904             FEInterface::extra_hanging_dofs(fe_type);
01905 
01906 #ifdef DEBUG
01907           tot_size += FEInterface::n_dofs(dim,
01908                                           fe_type,
01909                                           type);
01910 #endif
01911 
01912           // Get the node-based DOF numbers
01913           for (unsigned int n=0; n<n_nodes; n++)
01914             {
01915               const Node* node      = elem->get_node(n);
01916 
01917               // There is a potential problem with h refinement.  Imagine a
01918               // quad9 that has a linear FE on it.  Then, on the hanging side,
01919               // it can falsely identify a DOF at the mid-edge node. This is why
01920               // we call FEInterface instead of node->n_comp() directly.
01921               const unsigned int nc = FEInterface::n_dofs_at_node (dim,
01922                                                                    fe_type,
01923                                                                    type,
01924                                                                    n);
01925               libmesh_assert(node->old_dof_object);
01926 
01927               // If this is a non-vertex on a hanging node with extra
01928               // degrees of freedom, we use the non-vertex dofs (which
01929               // come in reverse order starting from the end, to
01930               // simplify p refinement)
01931               if (extra_hanging_dofs && !elem->is_vertex(n))
01932                 {
01933                   const int dof_offset =
01934                     node->old_dof_object->n_comp(sys_num,v) - nc;
01935 
01936                   // We should never have fewer dofs than necessary on a
01937                   // node unless we're getting indices on a parent element
01938                   // or a just-coarsened element
01939                   if (dof_offset < 0)
01940                     {
01941                       libmesh_assert(!elem->active() || elem->refinement_flag() ==
01942                                      Elem::JUST_COARSENED);
01943                       di.resize(di.size() + nc, DofObject::invalid_id);
01944                     }
01945                   else
01946                     for (int i=node->old_dof_object->n_comp(sys_num,v)-1;
01947                          i>=dof_offset; i--)
01948                       {
01949                         libmesh_assert_not_equal_to (node->old_dof_object->dof_number(sys_num,v,i),
01950                                                      DofObject::invalid_id);
01951                         di.push_back(node->old_dof_object->dof_number(sys_num,v,i));
01952                       }
01953                 }
01954               // If this is a vertex or an element without extra hanging
01955               // dofs, our dofs come in forward order coming from the
01956               // beginning
01957               else
01958                 for (unsigned int i=0; i<nc; i++)
01959                   {
01960                     libmesh_assert_not_equal_to (node->old_dof_object->dof_number(sys_num,v,i),
01961                                                  DofObject::invalid_id);
01962                     di.push_back(node->old_dof_object->dof_number(sys_num,v,i));
01963                   }
01964             }
01965 
01966           // If there are any element-based DOF numbers, get them
01967           const unsigned int nc = FEInterface::n_dofs_per_elem(dim,
01968                                                                fe_type,
01969                                                                type);
01970 
01971           // We should never have fewer dofs than necessary on an
01972           // element unless we're getting indices on a parent element
01973           // or a just-coarsened element
01974           if (nc != 0)
01975             {
01976               if (elem->old_dof_object->n_systems() > sys_num &&
01977                   nc <= elem->old_dof_object->n_comp(sys_num,v))
01978                 {
01979                   libmesh_assert(elem->old_dof_object);
01980 
01981                   for (unsigned int i=0; i<nc; i++)
01982                     {
01983                       libmesh_assert_not_equal_to (elem->old_dof_object->dof_number(sys_num,v,i),
01984                                                    DofObject::invalid_id);
01985 
01986                       di.push_back(elem->old_dof_object->dof_number(sys_num,v,i));
01987                     }
01988                 }
01989               else
01990                 {
01991                   libmesh_assert(!elem->active() || fe_type.family == LAGRANGE ||
01992                                  elem->refinement_flag() == Elem::JUST_COARSENED);
01993                   di.resize(di.size() + nc, DofObject::invalid_id);
01994                 }
01995             }
01996         }
01997     } // end loop over variables
01998 
01999   // Finally append any SCALAR dofs that we asked for.
02000   std::vector<dof_id_type> di_new;
02001   std::vector<unsigned int>::iterator it           = SCALAR_var_numbers.begin();
02002   std::vector<unsigned int>::const_iterator it_end = SCALAR_var_numbers.end();
02003   for( ; it != it_end; ++it)
02004   {
02005     this->SCALAR_dof_indices(di_new,*it,true);
02006     di.insert( di.end(), di_new.begin(), di_new.end());
02007   }
02008 
02009 #ifdef DEBUG
02010   libmesh_assert_equal_to (tot_size, di.size());
02011 #endif
02012 
02013   STOP_LOG("old_dof_indices()", "DofMap");
02014 }

void libMesh::DofMap::prepare_send_list (  ) 

Takes the _send_list vector (which may have duplicate entries) and sorts it. The duplicate entries are then removed, resulting in a sorted _send_list with unique entries. Also calls any user-provided methods for adding to the send list.

Definition at line 1377 of file dof_map.C.

References _augment_send_list, _extra_send_list_context, _extra_send_list_function, _send_list, libMesh::DofMap::AugmentSendList::augment_send_list(), libMesh::out, and swap().

Referenced by libMesh::EquationSystems::allgather(), and libMesh::EquationSystems::reinit().

01378 {
01379   START_LOG("prepare_send_list()", "DofMap");
01380 
01381   // Check to see if we have any extra stuff to add to the send_list
01382   if (_extra_send_list_function)
01383     {
01384       if (_augment_send_list)
01385         {
01386           libmesh_here();
01387           libMesh::out << "WARNING:  You have specified both an extra send list function and object.\n"
01388                        << "          Are you sure this is what you meant to do??"
01389                        << std::endl;
01390         }
01391 
01392       _extra_send_list_function(_send_list, _extra_send_list_context);
01393     }
01394 
01395   if (_augment_send_list)
01396     _augment_send_list->augment_send_list (_send_list);
01397 
01398   // First sort the send list.  After this
01399   // duplicated elements will be adjacent in the
01400   // vector
01401   std::sort(_send_list.begin(), _send_list.end());
01402 
01403   // Now use std::unique to remove duplicate entries
01404   std::vector<dof_id_type>::iterator new_end =
01405     std::unique (_send_list.begin(), _send_list.end());
01406 
01407   // Remove the end of the send_list.  Use the "swap trick"
01408   // from Effective STL
01409   std::vector<dof_id_type> (_send_list.begin(), new_end).swap (_send_list);
01410 
01411   STOP_LOG("prepare_send_list()", "DofMap");
01412 }

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

Prints (from processor 0) all DoF and Node constraints. If print_nonlocal is true, then each constraint is printed once for each processor that knows about it, which may be useful for ParallelMesh debugging.

Definition at line 1001 of file dof_map_constraints.C.

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

01003 {
01004   parallel_only();
01005 
01006   std::string local_constraints =
01007     this->get_local_constraints(print_nonlocal);
01008 
01009   if (libMesh::processor_id())
01010     {
01011       CommWorld.send(0, local_constraints);
01012     }
01013   else
01014     {
01015       os << "Processor 0:\n";
01016       os << local_constraints;
01017 
01018       for (processor_id_type i=1; i<libMesh::n_processors(); ++i)
01019         {
01020           CommWorld.receive(i, local_constraints);
01021           os << "Processor " << i << ":\n";
01022           os << local_constraints;
01023         }
01024     }
01025 }

void libMesh::ReferenceCounter::print_info ( std::ostream &  out = libMesh::out  )  [static, inherited]

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

Definition at line 88 of file reference_counter.C.

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

00089 {
00090   if( _enable_print_counter ) out_stream << ReferenceCounter::get_info();
00091 }

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

Prints summary info about the sparsity bandwidth and constraints.

Definition at line 2773 of file dof_map.C.

References get_info().

02774 {
02775   os << this->get_info();
02776 }

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

Postprocesses any constrained degrees of freedom to be constrained only in terms of unconstrained dofs, then adds unconstrained dofs to the send_list and prepares that for use. This should be run after both system (create_dof_constraints) and user constraints have all been added.

Definition at line 2484 of file dof_map_constraints.C.

References _dof_constraints, add_constraints_to_send_list(), allgather_recursive_constraints(), libMesh::MeshBase::is_serial(), libMesh::Real, and scatter_constraints().

Referenced by libMesh::EquationSystems::allgather(), and libMesh::EquationSystems::reinit().

02485 {
02486   // With a parallelized Mesh, we've computed our local constraints,
02487   // but they may depend on non-local constraints that we'll need to
02488   // take into account.
02489   if (!mesh.is_serial())
02490     this->allgather_recursive_constraints(mesh);
02491 
02492   // Create a set containing the DOFs we already depend on
02493   typedef std::set<dof_id_type> RCSet;
02494   RCSet unexpanded_set;
02495 
02496   for (DofConstraints::iterator i = _dof_constraints.begin();
02497          i != _dof_constraints.end(); ++i)
02498     unexpanded_set.insert(i->first);
02499 
02500   while (!unexpanded_set.empty())
02501     for (RCSet::iterator i = unexpanded_set.begin();
02502          i != unexpanded_set.end(); /* nothing */)
02503       {
02504         // If the DOF is constrained
02505         DofConstraints::iterator
02506           pos = _dof_constraints.find(*i);
02507 
02508         libmesh_assert (pos != _dof_constraints.end());
02509 
02510         DofConstraintRow& constraint_row = pos->second.first;
02511 
02512         Number& constraint_rhs = pos->second.second;
02513 
02514         std::vector<dof_id_type> constraints_to_expand;
02515 
02516         for (DofConstraintRow::const_iterator
02517                it=constraint_row.begin(); it != constraint_row.end();
02518              ++it)
02519           if (it->first != *i && this->is_constrained_dof(it->first))
02520             {
02521               unexpanded_set.insert(it->first);
02522               constraints_to_expand.push_back(it->first);
02523             }
02524 
02525         for (std::size_t j = 0; j != constraints_to_expand.size();
02526              ++j)
02527           {
02528             dof_id_type expandable = constraints_to_expand[j];
02529 
02530             const Real this_coef = constraint_row[expandable];
02531 
02532             DofConstraints::const_iterator
02533               subpos = _dof_constraints.find(expandable);
02534 
02535             libmesh_assert (subpos != _dof_constraints.end());
02536 
02537             const DofConstraintRow& subconstraint_row = subpos->second.first;
02538 
02539             for (DofConstraintRow::const_iterator
02540                    it=subconstraint_row.begin();
02541                    it != subconstraint_row.end(); ++it)
02542               {
02543                 constraint_row[it->first] += it->second * this_coef;
02544               }
02545             constraint_rhs += subpos->second.second * this_coef;
02546 
02547             constraint_row.erase(expandable);
02548           }
02549 
02550         if (constraints_to_expand.empty())
02551           unexpanded_set.erase(i++);
02552         else
02553           i++;
02554       }
02555 
02556   // In parallel we can't guarantee that nodes/dofs which constrain
02557   // others are on processors which are aware of that constraint, yet
02558   // we need such awareness for sparsity pattern generation.  So send
02559   // other processors any constraints they might need to know about.
02560   if (!mesh.is_serial())
02561     this->scatter_constraints(mesh);
02562 
02563   // Now that we have our root constraint dependencies sorted out, add
02564   // them to the send_list
02565   this->add_constraints_to_send_list();
02566 }

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

Reinitialize the underlying data strucures conformal to the current mesh.

Definition at line 422 of file dof_map.C.

References _n_SCALAR_dofs, libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::Variable::active_on_subdomain(), libMesh::Elem::dim(), libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), libMesh::Utility::enum_to_string(), libMesh::err, libMesh::FEInterface::extra_hanging_dofs(), libMesh::FEType::family, libMesh::Elem::get_node(), libMesh::DofObject::has_dofs(), invalidate_dofs(), libMesh::MeshBase::is_prepared(), libMesh::Elem::is_vertex(), libMesh::Elem::JUST_REFINED, std::max(), libMesh::FEInterface::max_order(), libMesh::DofObject::n_comp_group(), libMesh::FEInterface::n_dofs_at_node(), libMesh::FEInterface::n_dofs_per_elem(), libMesh::Elem::n_nodes(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::MeshBase::nodes_begin(), libMesh::MeshBase::nodes_end(), libMesh::DofObject::old_dof_object, libMesh::FEType::order, libMesh::Elem::p_level(), libMesh::Elem::refinement_flag(), libMeshEnums::SCALAR, libMesh::DofObject::set_n_comp_group(), libMesh::DofObject::set_old_dof_object(), libMesh::Elem::set_p_level(), libMesh::DofObject::set_vg_dof_base(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::Elem::type(), libMesh::Variable::type(), variable_group(), and libMesh::DofObject::vg_dof_base().

Referenced by distribute_dofs().

00423 {
00424   libmesh_assert (mesh.is_prepared());
00425 
00426   START_LOG("reinit()", "DofMap");
00427 
00428   const unsigned int
00429     sys_num      = this->sys_number(),
00430     n_var_groups = this->n_variable_groups();
00431 
00432   // The DofObjects need to know how many variable groups we have, and
00433   // how many variables there are in each group.
00434   std::vector<unsigned int> n_vars_per_group;  n_vars_per_group.reserve (n_var_groups);
00435   
00436   for (unsigned int vg=0; vg<n_var_groups; vg++)
00437     n_vars_per_group.push_back (this->variable_group(vg).n_variables());
00438   
00439 #ifdef LIBMESH_ENABLE_AMR
00440 
00441   //------------------------------------------------------------
00442   // Clear the old_dof_objects for all the nodes
00443   // and elements so that we can overwrite them
00444   {
00445     MeshBase::node_iterator       node_it  = mesh.nodes_begin();
00446     const MeshBase::node_iterator node_end = mesh.nodes_end();
00447 
00448     for ( ; node_it != node_end; ++node_it)
00449       {
00450         (*node_it)->clear_old_dof_object();
00451         libmesh_assert (!(*node_it)->old_dof_object);
00452       }
00453 
00454     MeshBase::element_iterator       elem_it  = mesh.elements_begin();
00455     const MeshBase::element_iterator elem_end = mesh.elements_end();
00456 
00457     for ( ; elem_it != elem_end; ++elem_it)
00458       {
00459         (*elem_it)->clear_old_dof_object();
00460         libmesh_assert (!(*elem_it)->old_dof_object);
00461       }
00462   }
00463 
00464 
00465   //------------------------------------------------------------
00466   // Set the old_dof_objects for the elements that
00467   // weren't just created, if these old dof objects
00468   // had variables
00469   {
00470     MeshBase::element_iterator       elem_it  = mesh.elements_begin();
00471     const MeshBase::element_iterator elem_end = mesh.elements_end();
00472 
00473     for ( ; elem_it != elem_end; ++elem_it)
00474       {
00475         Elem* elem = *elem_it;
00476 
00477         // Skip the elements that were just refined
00478         if (elem->refinement_flag() == Elem::JUST_REFINED) continue;
00479 
00480         for (unsigned int n=0; n<elem->n_nodes(); n++)
00481           {
00482             Node* node = elem->get_node(n);
00483 
00484             if (node->old_dof_object == NULL)
00485               if (node->has_dofs(sys_num))
00486                 node->set_old_dof_object();
00487           }
00488 
00489         libmesh_assert (!elem->old_dof_object);
00490 
00491         if (elem->has_dofs(sys_num))
00492           elem->set_old_dof_object();
00493       }
00494   }
00495 
00496 #endif // #ifdef LIBMESH_ENABLE_AMR
00497 
00498 
00499   //------------------------------------------------------------
00500   // Then set the number of variables for each \p DofObject
00501   // equal to n_variables() for this system.  This will
00502   // handle new \p DofObjects that may have just been created
00503   {
00504     // All the nodes
00505     MeshBase::node_iterator       node_it  = mesh.nodes_begin();
00506     const MeshBase::node_iterator node_end = mesh.nodes_end();
00507 
00508     for ( ; node_it != node_end; ++node_it)
00509       (*node_it)->set_n_vars_per_group(sys_num, n_vars_per_group);
00510 
00511     // All the elements
00512     MeshBase::element_iterator       elem_it  = mesh.elements_begin();
00513     const MeshBase::element_iterator elem_end = mesh.elements_end();
00514 
00515     for ( ; elem_it != elem_end; ++elem_it)
00516       (*elem_it)->set_n_vars_per_group(sys_num, n_vars_per_group);
00517   }
00518 
00519 
00520   // Zero _n_SCALAR_dofs, it will be updated below.
00521   this->_n_SCALAR_dofs = 0;
00522 
00523   //------------------------------------------------------------
00524   // Next allocate space for the DOF indices
00525   for (unsigned int vg=0; vg<n_var_groups; vg++)
00526     {
00527       const VariableGroup &vg_description = this->variable_group(vg);
00528       
00529       const unsigned int n_var_in_group = vg_description.n_variables();
00530       const FEType& base_fe_type        = vg_description.type();
00531 
00532       // Don't need to loop over elements for a SCALAR variable
00533       // Just increment _n_SCALAR_dofs
00534       if(base_fe_type.family == SCALAR)
00535         {
00536           this->_n_SCALAR_dofs += base_fe_type.order*n_var_in_group;
00537           continue;
00538         }
00539 
00540       // This should be constant even on p-refined elements
00541       const bool extra_hanging_dofs =
00542         FEInterface::extra_hanging_dofs(base_fe_type);
00543 
00544       // For all the active elements
00545       MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
00546       const MeshBase::element_iterator elem_end = mesh.active_elements_end();
00547 
00548       // Count vertex degrees of freedom first
00549       for ( ; elem_it != elem_end; ++elem_it)
00550         {
00551           Elem* elem  = *elem_it;
00552           libmesh_assert(elem);
00553 
00554           // Skip the numbering if this variable is
00555           // not active on this element's subdomain
00556           if (!vg_description.active_on_subdomain(elem->subdomain_id()))
00557             continue;
00558 
00559           const ElemType type = elem->type();
00560           const unsigned int dim = elem->dim();
00561           
00562           FEType fe_type = base_fe_type;
00563 
00564 #ifdef LIBMESH_ENABLE_AMR
00565           // Make sure we haven't done more p refinement than we can
00566           // handle
00567           if (elem->p_level() + base_fe_type.order >
00568               FEInterface::max_order(base_fe_type, type))
00569             {
00570 #  ifdef DEBUG
00571               if (FEInterface::max_order(base_fe_type,type) <
00572                   static_cast<unsigned int>(base_fe_type.order))
00573                 {
00574                   libMesh::err
00575                     << "ERROR: Finite element "
00576                     << Utility::enum_to_string(base_fe_type.family)
00577                     << " on geometric element "
00578                     << Utility::enum_to_string(type) << std::endl
00579                     << "only supports FEInterface::max_order = "
00580                     << FEInterface::max_order(base_fe_type,type)
00581                     << ", not fe_type.order = " << base_fe_type.order
00582                     << std::endl;
00583 
00584                   libmesh_error();
00585                 }
00586               
00587               libMesh::err
00588                 << "WARNING: Finite element "
00589                 << Utility::enum_to_string(base_fe_type.family)
00590                 << " on geometric element "
00591                 << Utility::enum_to_string(type) << std::endl
00592                 << "could not be p refined past FEInterface::max_order = "
00593                 << FEInterface::max_order(base_fe_type,type)
00594                 << std::endl;
00595 #  endif
00596               elem->set_p_level(FEInterface::max_order(base_fe_type,type)
00597                                 - base_fe_type.order);
00598             }
00599 #endif
00600 
00601           fe_type.order = static_cast<Order>(fe_type.order +
00602                                              elem->p_level());
00603 
00604           // Allocate the vertex DOFs
00605           for (unsigned int n=0; n<elem->n_nodes(); n++)
00606             {
00607               Node* node = elem->get_node(n);
00608 
00609               if (elem->is_vertex(n))
00610                 {
00611                   const unsigned int old_node_dofs =
00612                     node->n_comp_group(sys_num, vg);
00613 
00614                   const unsigned int vertex_dofs =
00615                     std::max(FEInterface::n_dofs_at_node(dim, fe_type,
00616                                                          type, n),
00617                              old_node_dofs);
00618 
00619                   // Some discontinuous FEs have no vertex dofs
00620                   if (vertex_dofs > old_node_dofs)
00621                     {
00622                       node->set_n_comp_group(sys_num, vg,
00623                                              vertex_dofs);
00624                       
00625                       // Abusing dof_number to set a "this is a
00626                       // vertex" flag
00627                       node->set_vg_dof_base(sys_num, vg,
00628                                             vertex_dofs);
00629                       
00630                       // std::cout << "sys_num,vg,old_node_dofs,vertex_dofs="
00631                       //                << sys_num << ","
00632                       //                << vg << ","
00633                       //                << old_node_dofs << ","
00634                       //                << vertex_dofs << '\n',
00635                       //        node->debug_buffer();
00636 
00637                       // libmesh_assert_equal_to (vertex_dofs, node->n_comp(sys_num, vg));
00638                       // libmesh_assert_equal_to (vertex_dofs, node->vg_dof_base(sys_num, vg));
00639                     }
00640                 }
00641             }
00642         } // done counting vertex dofs
00643 
00644       // count edge & face dofs next
00645       elem_it = mesh.active_elements_begin();
00646 
00647       for ( ; elem_it != elem_end; ++elem_it)
00648         {
00649           Elem* elem = *elem_it;
00650           libmesh_assert(elem);
00651 
00652           // Skip the numbering if this variable is
00653           // not active on this element's subdomain
00654           if (!vg_description.active_on_subdomain(elem->subdomain_id()))
00655             continue;
00656 
00657           const ElemType type = elem->type();
00658           const unsigned int dim = elem->dim();
00659 
00660           FEType fe_type = base_fe_type;
00661           fe_type.order = static_cast<Order>(fe_type.order +
00662                                              elem->p_level());
00663 
00664           // Allocate the edge and face DOFs
00665           for (unsigned int n=0; n<elem->n_nodes(); n++)
00666             {
00667               Node* node = elem->get_node(n);
00668 
00669               const unsigned int old_node_dofs =
00670                 node->n_comp_group(sys_num, vg);
00671 
00672               const unsigned int vertex_dofs = old_node_dofs?
00673                 libmesh_cast_int<unsigned int>(node->vg_dof_base (sys_num,vg)):0;
00674 
00675               const unsigned int new_node_dofs =
00676                 FEInterface::n_dofs_at_node(dim, fe_type, type, n);
00677 
00678               // We've already allocated vertex DOFs
00679               if (elem->is_vertex(n))
00680                 {
00681                   libmesh_assert_greater_equal (old_node_dofs, vertex_dofs);
00682                   // //if (vertex_dofs < new_node_dofs)
00683                   //   std::cout << "sys_num,vg,old_node_dofs,vertex_dofs,new_node_dofs="
00684                   //          << sys_num << ","
00685                   //          << vg << ","
00686                   //          << old_node_dofs << ","
00687                   //          << vertex_dofs << ","
00688                   //          << new_node_dofs << '\n',
00689                   //     node->debug_buffer();
00690                   
00691                   libmesh_assert_greater_equal (vertex_dofs,   new_node_dofs);
00692                 }
00693               // We need to allocate the rest
00694               else
00695                 {
00696                   // If this has no dofs yet, it needs no vertex
00697                   // dofs, so we just give it edge or face dofs
00698                   if (!old_node_dofs)
00699                     {
00700                       node->set_n_comp_group(sys_num, vg,
00701                                              new_node_dofs);
00702                       // Abusing dof_number to set a "this has no
00703                       // vertex dofs" flag
00704                       if (new_node_dofs)
00705                         node->set_vg_dof_base(sys_num, vg,
00706                                               0);
00707                     }
00708 
00709                   // If this has dofs, but has no vertex dofs,
00710                   // it may still need more edge or face dofs if
00711                   // we're p-refined.
00712                   else if (vertex_dofs == 0)
00713                     {
00714                       if (new_node_dofs > old_node_dofs)
00715                         {
00716                           node->set_n_comp_group(sys_num, vg,
00717                                                  new_node_dofs);
00718                           
00719                           node->set_vg_dof_base(sys_num, vg,
00720                                                 vertex_dofs);
00721                         }
00722                     }
00723                   // If this is another element's vertex,
00724                   // add more (non-overlapping) edge/face dofs if
00725                   // necessary
00726                   else if (extra_hanging_dofs)
00727                     {
00728                       if (new_node_dofs > old_node_dofs - vertex_dofs)
00729                         {
00730                           node->set_n_comp_group(sys_num, vg,
00731                                                  vertex_dofs + new_node_dofs);
00732                           
00733                           node->set_vg_dof_base(sys_num, vg,
00734                                                 vertex_dofs);
00735                         }
00736                     }
00737                   // If this is another element's vertex, add any
00738                   // (overlapping) edge/face dofs if necessary
00739                   else
00740                     {
00741                       libmesh_assert_greater_equal (old_node_dofs, vertex_dofs);
00742                       if (new_node_dofs > old_node_dofs)
00743                         {
00744                           node->set_n_comp_group(sys_num, vg,
00745                                                  new_node_dofs);
00746                           
00747                           node->set_vg_dof_base (sys_num, vg,
00748                                                  vertex_dofs);
00749                         }
00750                     }
00751                 }
00752             }
00753           // Allocate the element DOFs
00754           const unsigned int dofs_per_elem =
00755                           FEInterface::n_dofs_per_elem(dim, fe_type,
00756                                                        type);
00757 
00758           elem->set_n_comp_group(sys_num, vg, dofs_per_elem);
00759 
00760         }
00761     } // end loop over variable groups
00762 
00763   // Calling DofMap::reinit() by itself makes little sense,
00764   // so we won't bother with nonlocal DofObjects.
00765   // Those will be fixed by distribute_dofs
00766 
00767   //------------------------------------------------------------
00768   // Finally, clear all the current DOF indices
00769   // (distribute_dofs expects them cleared!)
00770   this->invalidate_dofs(mesh);
00771 
00772   STOP_LOG("reinit()", "DofMap");
00773 }

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

Removes the specified Dirichlet boundary from the system.

Definition at line 3082 of file dof_map_constraints.C.

References _dirichlet_boundaries, libMesh::DirichletBoundary::b, end, and libMesh::DirichletBoundary::variables.

03083 {
03084   // Find a boundary condition matching the one to be removed
03085   std::vector<DirichletBoundary *>::iterator it = _dirichlet_boundaries->begin();
03086   std::vector<DirichletBoundary *>::iterator end = _dirichlet_boundaries->end();
03087   for (; it != end; ++it)
03088     {
03089       DirichletBoundary *bdy = *it;
03090 
03091       if ((bdy->b == boundary_to_remove.b) &&
03092            bdy->variables == boundary_to_remove.variables)
03093         break;
03094     }
03095 
03096   // Delete it and remove it
03097   libmesh_assert (it != end);
03098   delete *it;
03099   _dirichlet_boundaries->erase(it);
03100 }

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

Fills the vector di with the global degree of freedom indices corresponding to the SCALAR variable vn. If old_dofs=true, the old SCALAR dof indices are returned. Note that we do not need to pass in an element since SCALARs are global variables.

Referenced by dof_indices(), old_dof_indices(), libMesh::System::project_vector(), libMesh::System::read_parallel_data(), libMesh::System::read_SCALAR_dofs(), libMesh::System::write_parallel_data(), and libMesh::System::write_SCALAR_dofs().

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

Sends constraint equations to constraining processors

Definition at line 2569 of file dof_map_constraints.C.

References _dof_constraints, _end_df, _node_constraints, libMesh::MeshBase::active_not_local_elements_begin(), libMesh::MeshBase::active_not_local_elements_end(), libMesh::CommWorld, dof_indices(), end, libMesh::DofObject::id(), is_constrained_dof(), is_constrained_node(), libMesh::Parallel::Communicator::max(), libMesh::n_processors(), libMesh::MeshBase::node_ptr(), libMesh::DofObject::processor_id(), libMesh::processor_id(), libMesh::Parallel::Communicator::send_receive(), and libMesh::Parallel::Communicator::send_receive_packed_range().

Referenced by process_constraints().

02570 {
02571   // At this point each processor with a constrained node knows
02572   // the corresponding constraint row, but we also need each processor
02573   // with a constrainer node to know the corresponding row(s).
02574 
02575   // This function must be run on all processors at once
02576   parallel_only();
02577 
02578   // Return immediately if there's nothing to gather
02579   if (libMesh::n_processors() == 1)
02580     return;
02581 
02582   // We might get to return immediately if none of the processors
02583   // found any constraints
02584   unsigned int has_constraints = !_dof_constraints.empty()
02585 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02586                                  || !_node_constraints.empty()
02587 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02588                                  ;
02589   CommWorld.max(has_constraints);
02590   if (!has_constraints)
02591     return;
02592 
02593 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02594   std::vector<std::set<dof_id_type> > pushed_node_ids(libMesh::n_processors());
02595 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02596 
02597   std::vector<std::set<dof_id_type> > pushed_ids(libMesh::n_processors());
02598 
02599   // Collect the dof constraints I need to push to each processor
02600   dof_id_type constrained_proc_id = 0;
02601   for (DofConstraints::iterator i = _dof_constraints.begin();
02602          i != _dof_constraints.end(); ++i)
02603     {
02604       const dof_id_type constrained = i->first;
02605       while (constrained >= _end_df[constrained_proc_id])
02606         constrained_proc_id++;
02607 
02608       if (constrained_proc_id != libMesh::processor_id())
02609         continue;
02610 
02611       DofConstraintRow &row = i->second.first;
02612       for (DofConstraintRow::iterator j = row.begin();
02613            j != row.end(); ++j)
02614         {
02615           const dof_id_type constraining = j->first;
02616 
02617           processor_id_type constraining_proc_id = 0;
02618           while (constraining >= _end_df[constraining_proc_id])
02619             constraining_proc_id++;
02620 
02621           if (constraining_proc_id != libMesh::processor_id() &&
02622               constraining_proc_id != constrained_proc_id)
02623             pushed_ids[constraining_proc_id].insert(constrained);
02624         }
02625     }
02626 
02627 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02628   // Collect the node constraints to push to each processor
02629   for (NodeConstraints::iterator i = _node_constraints.begin();
02630          i != _node_constraints.end(); ++i)
02631     {
02632       const Node *constrained = i->first;
02633 
02634       if (constrained->processor_id() != libMesh::processor_id())
02635         continue;
02636 
02637       NodeConstraintRow &row = i->second.first;
02638       for (NodeConstraintRow::iterator j = row.begin();
02639            j != row.end(); ++j)
02640         {
02641           const Node *constraining = j->first;
02642 
02643           if (constraining->processor_id() != libMesh::processor_id() &&
02644               constraining->processor_id() != constrained->processor_id())
02645             pushed_node_ids[constraining->processor_id()].insert(constrained->id());
02646         }
02647     }
02648 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02649 
02650   // Now trade constraint rows
02651   for (processor_id_type p = 0; p != libMesh::n_processors(); ++p)
02652     {
02653       // Push to processor procup while receiving from procdown
02654       processor_id_type procup = (libMesh::processor_id() + p) %
02655                                   libMesh::n_processors();
02656       processor_id_type procdown = (libMesh::n_processors() +
02657                                     libMesh::processor_id() - p) %
02658                                     libMesh::n_processors();
02659 
02660       // Pack the dof constraint rows and rhs's to push to procup
02661       const std::size_t pushed_ids_size = pushed_ids[procup].size();
02662       std::vector<std::vector<dof_id_type> > pushed_keys(pushed_ids_size);
02663       std::vector<std::vector<Real> > pushed_vals(pushed_ids_size);
02664       std::vector<Number> pushed_rhss(pushed_ids_size);
02665 
02666       std::set<dof_id_type>::const_iterator it;
02667       std::size_t push_i;
02668       for (push_i = 0, it = pushed_ids[procup].begin();
02669            it != pushed_ids[procup].end(); ++push_i, ++it)
02670         {
02671           const dof_id_type constrained = *it;
02672           DofConstraintRow &row = _dof_constraints[constrained].first;
02673           std::size_t row_size = row.size();
02674           pushed_keys[push_i].reserve(row_size);
02675           pushed_vals[push_i].reserve(row_size);
02676           for (DofConstraintRow::iterator j = row.begin();
02677                j != row.end(); ++j)
02678             {
02679               pushed_keys[push_i].push_back(j->first);
02680               pushed_vals[push_i].push_back(j->second);
02681             }
02682           pushed_rhss[push_i] = _dof_constraints[constrained].second;
02683         }
02684 
02685 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02686       // Pack the node constraint rows to push to procup
02687       const std::size_t pushed_node_ids_size = pushed_node_ids[procup].size();
02688       std::vector<std::vector<dof_id_type> > pushed_node_keys(pushed_node_ids_size);
02689       std::vector<std::vector<Real> > pushed_node_vals(pushed_node_ids_size);
02690       std::vector<Point> pushed_node_offsets(pushed_node_ids_size);
02691       std::set<const Node*> pushed_nodes;
02692 
02693       for (push_i = 0, it = pushed_node_ids[procup].begin();
02694            it != pushed_node_ids[procup].end(); ++push_i, ++it)
02695         {
02696           const Node *constrained = mesh.node_ptr(*it);
02697               
02698           if (constrained->processor_id() != procdown)
02699             pushed_nodes.insert(constrained);
02700 
02701           NodeConstraintRow &row = _node_constraints[constrained].first;
02702           std::size_t row_size = row.size();
02703           pushed_node_keys[push_i].reserve(row_size);
02704           pushed_node_vals[push_i].reserve(row_size);
02705           for (NodeConstraintRow::iterator j = row.begin();
02706                j != row.end(); ++j)
02707             {
02708               const Node* constraining = j->first;
02709 
02710               pushed_node_keys[push_i].push_back(constraining->id());
02711               pushed_node_vals[push_i].push_back(j->second);
02712               
02713               if (constraining->processor_id() != procup)
02714                 pushed_nodes.insert(constraining);
02715             }
02716           pushed_node_offsets[push_i] = _node_constraints[constrained].second;
02717         }
02718 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02719 
02720       // Trade pushed dof constraint rows
02721       std::vector<dof_id_type> pushed_ids_from_me
02722         (pushed_ids[procup].begin(), pushed_ids[procup].end());
02723       std::vector<dof_id_type> pushed_ids_to_me;
02724       std::vector<std::vector<dof_id_type> > pushed_keys_to_me;
02725       std::vector<std::vector<Real> > pushed_vals_to_me;
02726       std::vector<Number> pushed_rhss_to_me;
02727       CommWorld.send_receive(procup, pushed_ids_from_me,
02728                              procdown, pushed_ids_to_me);
02729       CommWorld.send_receive(procup, pushed_keys,
02730                              procdown, pushed_keys_to_me);
02731       CommWorld.send_receive(procup, pushed_vals,
02732                              procdown, pushed_vals_to_me);
02733       CommWorld.send_receive(procup, pushed_rhss,
02734                              procdown, pushed_rhss_to_me);
02735       libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_keys_to_me.size());
02736       libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_vals_to_me.size());
02737       libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_rhss_to_me.size());
02738 
02739 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02740       // Trade pushed node constraint rows
02741       std::vector<dof_id_type> pushed_node_ids_from_me
02742         (pushed_node_ids[procup].begin(), pushed_node_ids[procup].end());
02743       std::vector<dof_id_type> pushed_node_ids_to_me;
02744       std::vector<std::vector<dof_id_type> > pushed_node_keys_to_me;
02745       std::vector<std::vector<Real> > pushed_node_vals_to_me;
02746       std::vector<Point> pushed_node_offsets_to_me;
02747       CommWorld.send_receive(procup, pushed_node_ids_from_me,
02748                              procdown, pushed_node_ids_to_me);
02749       CommWorld.send_receive(procup, pushed_node_keys,
02750                              procdown, pushed_node_keys_to_me);
02751       CommWorld.send_receive(procup, pushed_node_vals,
02752                              procdown, pushed_node_vals_to_me);
02753       CommWorld.send_receive(procup, pushed_node_offsets,
02754                              procdown, pushed_node_offsets_to_me);
02755 
02756       // Constraining nodes might not even exist on our subset of
02757       // a distributed mesh, so let's make them exist.
02758       CommWorld.send_receive_packed_range
02759         (procup, &mesh, pushed_nodes.begin(), pushed_nodes.end(),
02760          procdown, &mesh, mesh_inserter_iterator<Node>(mesh));
02761 
02762       libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_keys_to_me.size());
02763       libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_vals_to_me.size());
02764       libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_offsets_to_me.size());
02765 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02766 
02767       // Add the dof constraints that I've been sent
02768       for (std::size_t i = 0; i != pushed_ids_to_me.size(); ++i)
02769         {
02770           libmesh_assert_equal_to (pushed_keys_to_me[i].size(), pushed_vals_to_me[i].size());
02771 
02772           dof_id_type constrained = pushed_ids_to_me[i];
02773 
02774           // If we don't already have a constraint for this dof,
02775           // add the one we were sent
02776           if (!this->is_constrained_dof(constrained))
02777             {
02778               DofConstraintRow &row = _dof_constraints[constrained].first;
02779               for (std::size_t j = 0; j != pushed_keys_to_me[i].size(); ++j)
02780                 {
02781                   row[pushed_keys_to_me[i][j]] = pushed_vals_to_me[i][j];
02782                 }
02783               _dof_constraints[constrained].second = pushed_rhss_to_me[i];
02784             }
02785         }
02786 
02787 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
02788       // Add the node constraints that I've been sent
02789       for (std::size_t i = 0; i != pushed_node_ids_to_me.size(); ++i)
02790         {
02791           libmesh_assert_equal_to (pushed_node_keys_to_me[i].size(), pushed_node_vals_to_me[i].size());
02792 
02793           dof_id_type constrained_id = pushed_node_ids_to_me[i];
02794 
02795           // If we don't already have a constraint for this node,
02796           // add the one we were sent
02797           const Node *constrained = mesh.node_ptr(constrained_id);
02798           if (!this->is_constrained_node(constrained))
02799             {
02800               NodeConstraintRow &row = _node_constraints[constrained].first;
02801               for (std::size_t j = 0; j != pushed_node_keys_to_me[i].size(); ++j)
02802                 {
02803                   const Node *key_node = mesh.node_ptr(pushed_node_keys_to_me[i][j]);
02804                   libmesh_assert(key_node);
02805                   row[key_node] = pushed_node_vals_to_me[i][j];
02806                 }
02807               _node_constraints[constrained].second = pushed_node_offsets_to_me[i];
02808             }
02809         }
02810 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
02811     }
02812 
02813   // Next we need to push constraints to processors which don't own
02814   // the constrained dof, don't own the constraining dof, but own an
02815   // element supporting the constraining dof.
02816   //
02817   // We need to be able to quickly look up constrained dof ids by what
02818   // constrains them, so that we can handle the case where we see a
02819   // foreign element containing one of our constraining DoF ids and we
02820   // need to push that constraint.
02821   //
02822   // Getting distributed adaptive sparsity patterns right is hard.
02823 
02824   typedef std::map<dof_id_type, std::set<dof_id_type> > DofConstrainsMap;
02825   DofConstrainsMap dof_id_constrains;
02826 
02827   for (DofConstraints::iterator i = _dof_constraints.begin();
02828          i != _dof_constraints.end(); ++i)
02829     {
02830       const dof_id_type constrained = i->first;
02831       DofConstraintRow &row = i->second.first;
02832       for (DofConstraintRow::iterator j = row.begin();
02833            j != row.end(); ++j)
02834         {
02835           const dof_id_type constraining = j->first;
02836 
02837           dof_id_type constraining_proc_id = 0;
02838           while (constraining >= _end_df[constraining_proc_id])
02839             constraining_proc_id++;
02840 
02841           if (constraining_proc_id == libMesh::processor_id())
02842             dof_id_constrains[constraining].insert(constrained);
02843         }
02844     }
02845 
02846   // Loop over all foreign elements, find any supporting our
02847   // constrained dof indices.
02848   pushed_ids.clear();
02849   pushed_ids.resize(libMesh::n_processors());
02850 
02851   MeshBase::const_element_iterator it = mesh.active_not_local_elements_begin(),
02852                                   end = mesh.active_not_local_elements_end();
02853   for (; it != end; ++it)
02854     {
02855       const Elem *elem = *it;
02856 
02857       std::vector<dof_id_type> my_dof_indices;
02858       this->dof_indices (elem, my_dof_indices);
02859 
02860       for (std::size_t i=0; i != my_dof_indices.size(); ++i)
02861         {
02862           DofConstrainsMap::const_iterator dcmi =
02863             dof_id_constrains.find(my_dof_indices[i]);
02864           if (dcmi != dof_id_constrains.end())
02865             {
02866               for (DofConstrainsMap::mapped_type::const_iterator mti =
02867                      dcmi->second.begin();
02868                    mti != dcmi->second.end(); ++mti)
02869                 {
02870                   const dof_id_type constrained = *mti;
02871                   
02872                   dof_id_type the_constrained_proc_id = 0;
02873                   while (constrained >= _end_df[the_constrained_proc_id])
02874                     the_constrained_proc_id++;
02875 
02876                   const dof_id_type elemproc = elem->processor_id();
02877                   if (elemproc != the_constrained_proc_id)
02878                     pushed_ids[elemproc].insert(constrained);
02879                 }
02880             }
02881         }
02882     }
02883 
02884   // One last trade of constraint rows
02885   for (processor_id_type p = 0; p != libMesh::n_processors(); ++p)
02886     {
02887       // Push to processor procup while receiving from procdown
02888       processor_id_type procup = (libMesh::processor_id() + p) %
02889                                   libMesh::n_processors();
02890       processor_id_type procdown = (libMesh::n_processors() +
02891                                     libMesh::processor_id() - p) %
02892                                     libMesh::n_processors();
02893 
02894       // Pack the dof constraint rows and rhs's to push to procup
02895       const std::size_t pushed_ids_size = pushed_ids[procup].size();
02896       std::vector<std::vector<dof_id_type> > pushed_keys(pushed_ids_size);
02897       std::vector<std::vector<Real> > pushed_vals(pushed_ids_size);
02898       std::vector<Number> pushed_rhss(pushed_ids_size);
02899 
02900       // As long as we're declaring them outside the loop, let's initialize them too!
02901       std::set<dof_id_type>::const_iterator pushed_ids_iter = pushed_ids[procup].begin();
02902       std::size_t push_i = 0;
02903       for ( ; pushed_ids_iter != pushed_ids[procup].end(); ++push_i, ++pushed_ids_iter)
02904         {
02905           const dof_id_type constrained = *pushed_ids_iter;
02906           DofConstraintRow &row = _dof_constraints[constrained].first;
02907           std::size_t row_size = row.size();
02908           pushed_keys[push_i].reserve(row_size);
02909           pushed_vals[push_i].reserve(row_size);
02910           for (DofConstraintRow::iterator j = row.begin();
02911                j != row.end(); ++j)
02912             {
02913               pushed_keys[push_i].push_back(j->first);
02914               pushed_vals[push_i].push_back(j->second);
02915             }
02916           pushed_rhss[push_i] = _dof_constraints[constrained].second;
02917         }
02918 
02919       // Trade pushed dof constraint rows
02920       std::vector<dof_id_type> pushed_ids_from_me
02921         (pushed_ids[procup].begin(), pushed_ids[procup].end());
02922       std::vector<dof_id_type> pushed_ids_to_me;
02923       std::vector<std::vector<dof_id_type> > pushed_keys_to_me;
02924       std::vector<std::vector<Real> > pushed_vals_to_me;
02925       std::vector<Number> pushed_rhss_to_me;
02926       CommWorld.send_receive(procup, pushed_ids_from_me,
02927                              procdown, pushed_ids_to_me);
02928       CommWorld.send_receive(procup, pushed_keys,
02929                              procdown, pushed_keys_to_me);
02930       CommWorld.send_receive(procup, pushed_vals,
02931                              procdown, pushed_vals_to_me);
02932       CommWorld.send_receive(procup, pushed_rhss,
02933                              procdown, pushed_rhss_to_me);
02934       libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_keys_to_me.size());
02935       libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_vals_to_me.size());
02936       libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_rhss_to_me.size());
02937 
02938       // Add the dof constraints that I've been sent
02939       for (std::size_t i = 0; i != pushed_ids_to_me.size(); ++i)
02940         {
02941           libmesh_assert_equal_to (pushed_keys_to_me[i].size(), pushed_vals_to_me[i].size());
02942 
02943           dof_id_type constrained = pushed_ids_to_me[i];
02944 
02945           // If we don't already have a constraint for this dof,
02946           // add the one we were sent
02947           if (!this->is_constrained_dof(constrained))
02948             {
02949               DofConstraintRow &row = _dof_constraints[constrained].first;
02950               for (std::size_t j = 0; j != pushed_keys_to_me[i].size(); ++j)
02951                 {
02952                   row[pushed_keys_to_me[i][j]] = pushed_vals_to_me[i][j];
02953                 }
02954               _dof_constraints[constrained].second = pushed_rhss_to_me[i];
02955             }
02956         }
02957     }
02958 }

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

Helper function for distributing dofs in parallel

Definition at line 274 of file dof_map.C.

References libMesh::Parallel::Communicator::allgather(), libMesh::CommWorld, libMesh::DofObject::dof_number(), libMesh::DofObject::id(), libMesh::DofObject::invalid_id, libMesh::DofObject::invalid_processor_id, libMesh::DofObject::n_comp(), libMesh::DofObject::n_comp_group(), libMesh::n_processors(), libMesh::DofObject::n_var_groups(), n_variable_groups(), libMesh::DofObject::n_vars(), libMesh::processor_id(), libMesh::DofObject::processor_id(), libMesh::Parallel::Communicator::send_receive(), libMesh::DofObject::set_n_comp_group(), libMesh::DofObject::set_vg_dof_base(), sys_number(), and libMesh::DofObject::vg_dof_base().

Referenced by distribute_dofs().

00278 {
00279   // This function must be run on all processors at once
00280   parallel_only();
00281 
00282   // First, iterate over local objects to find out how many
00283   // are on each processor
00284   std::vector<dof_id_type>
00285     ghost_objects_from_proc(libMesh::n_processors(), 0);
00286 
00287   iterator_type it  = objects_begin;
00288 
00289   for (; it != objects_end; ++it)
00290     {
00291       DofObject *obj = *it;
00292 
00293       if (obj)
00294         {
00295           processor_id_type obj_procid = obj->processor_id();
00296           // We'd better be completely partitioned by now
00297           libmesh_assert_not_equal_to (obj_procid, DofObject::invalid_processor_id);
00298           ghost_objects_from_proc[obj_procid]++;
00299         }
00300     }
00301 
00302   std::vector<dof_id_type> objects_on_proc(libMesh::n_processors(), 0);
00303   CommWorld.allgather(ghost_objects_from_proc[libMesh::processor_id()],
00304                       objects_on_proc);
00305 
00306 #ifdef DEBUG
00307   for (processor_id_type p=0; p != libMesh::n_processors(); ++p)
00308     libmesh_assert_less_equal (ghost_objects_from_proc[p], objects_on_proc[p]);
00309 #endif
00310 
00311   // Request sets to send to each processor
00312   std::vector<std::vector<dof_id_type> >
00313     requested_ids(libMesh::n_processors());
00314 
00315   // We know how many of our objects live on each processor, so
00316   // reserve() space for requests from each.
00317   for (processor_id_type p=0; p != libMesh::n_processors(); ++p)
00318     if (p != libMesh::processor_id())
00319       requested_ids[p].reserve(ghost_objects_from_proc[p]);
00320 
00321   for (it = objects_begin; it != objects_end; ++it)
00322     {
00323       DofObject *obj = *it;
00324       if (obj->processor_id() != DofObject::invalid_processor_id)
00325         requested_ids[obj->processor_id()].push_back(obj->id());
00326     }
00327 #ifdef DEBUG
00328   for (processor_id_type p=0; p != libMesh::n_processors(); ++p)
00329     libmesh_assert_equal_to (requested_ids[p].size(), ghost_objects_from_proc[p]);
00330 #endif
00331 
00332   // Next set ghost object n_comps from other processors
00333   for (processor_id_type p=1; p != libMesh::n_processors(); ++p)
00334     {
00335       // Trade my requests with processor procup and procdown
00336       processor_id_type procup = (libMesh::processor_id() + p) %
00337                                   libMesh::n_processors();
00338       processor_id_type procdown = (libMesh::n_processors() +
00339                                     libMesh::processor_id() - p) %
00340                                     libMesh::n_processors();
00341       std::vector<dof_id_type> request_to_fill;
00342       CommWorld.send_receive(procup, requested_ids[procup],
00343                              procdown, request_to_fill);
00344 
00345       // Fill those requests
00346       const unsigned int
00347         sys_num      = this->sys_number(),
00348         n_var_groups = this->n_variable_groups();
00349 
00350       std::vector<dof_id_type> ghost_data
00351         (request_to_fill.size() * 2 * n_var_groups);
00352 
00353       for (std::size_t i=0; i != request_to_fill.size(); ++i)
00354         {
00355           DofObject *requested = (this->*objects)(mesh, request_to_fill[i]);
00356           libmesh_assert(requested);
00357           libmesh_assert_equal_to (requested->processor_id(), libMesh::processor_id());
00358           libmesh_assert_equal_to (requested->n_var_groups(sys_num), n_var_groups);
00359           for (unsigned int vg=0; vg != n_var_groups; ++vg)
00360             {
00361               unsigned int n_comp_g =
00362                 requested->n_comp_group(sys_num, vg);
00363               ghost_data[i*2*n_var_groups+vg] = n_comp_g;
00364               dof_id_type my_first_dof = n_comp_g ?
00365                 requested->vg_dof_base(sys_num, vg) : 0;
00366               libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
00367               ghost_data[i*2*n_var_groups+n_var_groups+vg] = my_first_dof;
00368             }
00369         }
00370 
00371       // Trade back the results
00372       std::vector<dof_id_type> filled_request;
00373       CommWorld.send_receive(procdown, ghost_data,
00374                              procup, filled_request);
00375 
00376       // And copy the id changes we've now been informed of
00377       libmesh_assert_equal_to (filled_request.size(),
00378                               requested_ids[procup].size() * 2 * n_var_groups);
00379       for (std::size_t i=0; i != requested_ids[procup].size(); ++i)
00380         {
00381           DofObject *requested = (this->*objects)(mesh, requested_ids[procup][i]);
00382           libmesh_assert(requested);
00383           libmesh_assert_equal_to (requested->processor_id(), procup);
00384           for (unsigned int vg=0; vg != n_var_groups; ++vg)
00385             {
00386               unsigned int n_comp_g =
00387                 libmesh_cast_int<unsigned int>(filled_request[i*2*n_var_groups+vg]);
00388               requested->set_n_comp_group(sys_num, vg, n_comp_g);
00389               if (n_comp_g)
00390                 {
00391                   dof_id_type my_first_dof =
00392                     filled_request[i*2*n_var_groups+n_var_groups+vg];
00393                   libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
00394                   requested->set_vg_dof_base
00395                     (sys_num, vg, my_first_dof);
00396                 }
00397             }
00398         }
00399     }
00400 
00401 #ifdef DEBUG
00402   // Double check for invalid dofs
00403   for (it = objects_begin; it != objects_end; ++it)
00404     {
00405       DofObject *obj = *it;
00406       libmesh_assert (obj);
00407       unsigned int num_variables = obj->n_vars(this->sys_number());
00408       for (unsigned int v=0; v != num_variables; ++v)
00409         {
00410           unsigned int n_comp =
00411             obj->n_comp(this->sys_number(), v);
00412           dof_id_type my_first_dof = n_comp ?
00413             obj->dof_number(this->sys_number(), v, 0) : 0;
00414           libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
00415         }
00416     }
00417 #endif
00418 }

unsigned int libMesh::DofMap::sys_number (  )  const [inline]
bool libMesh::DofMap::use_coupled_neighbor_dofs ( const MeshBase mesh  )  const

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

Definition at line 1416 of file dof_map.C.

References libMesh::FEAbstract::build(), libMeshEnums::DISCONTINUOUS, libMesh::MeshBase::mesh_dimension(), n_variables(), libMesh::on_command_line(), and variable_type().

01417 {
01418   // If we were asked on the command line, then we need to
01419   // include sensitivities between neighbor degrees of freedom
01420   bool implicit_neighbor_dofs =
01421     libMesh::on_command_line ("--implicit_neighbor_dofs");
01422 
01423   // look at all the variables in this system.  If every one is
01424   // discontinuous then the user must be doing DG/FVM, so be nice
01425   // and  force implicit_neighbor_dofs=true
01426   {
01427     bool all_discontinuous_dofs = true;
01428 
01429     for (unsigned int var=0; var<this->n_variables(); var++)
01430       if (FEAbstract::build (mesh.mesh_dimension(),
01431                              this->variable_type(var))->get_continuity() !=  DISCONTINUOUS)
01432         all_discontinuous_dofs = false;
01433 
01434     if (all_discontinuous_dofs)
01435       implicit_neighbor_dofs = true;
01436   }
01437 
01438   return implicit_neighbor_dofs;
01439 }

const Variable & libMesh::DofMap::variable ( const unsigned int  c  )  const [inline]
Returns:
the variable description object for variable c.

Definition at line 1180 of file dof_map.h.

References _variables.

Referenced by DMLibMeshSetSystem(), dof_indices(), old_dof_indices(), libMesh::BoundaryProjectSolution::operator()(), libMesh::ProjectFEMSolution::operator()(), and libMesh::ProjectSolution::operator()().

01181 {
01182   libmesh_assert_less (c, _variables.size());
01183 
01184   return _variables[c];
01185 }

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

Definition at line 1170 of file dof_map.h.

References _variable_groups.

Referenced by distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), libMesh::System::get_info(), and reinit().

01171 {
01172   libmesh_assert_less (g, _variable_groups.size());
01173 
01174   return _variable_groups[g];
01175 }

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

Definition at line 1200 of file dof_map.h.

References _variable_groups.

01201 {
01202   libmesh_assert_less (vg, _variable_groups.size());
01203 
01204   return _variable_groups[vg].type().order;
01205 }

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

Definition at line 1220 of file dof_map.h.

References _variable_groups.

01221 {
01222   libmesh_assert_less (vg, _variable_groups.size());
01223 
01224   return _variable_groups[vg].type();
01225 }

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

Definition at line 1190 of file dof_map.h.

References _variables.

01191 {
01192   libmesh_assert_less (c, _variables.size());
01193 
01194   return _variables[c].type().order;
01195 }


Friends And Related Function Documentation

friend class SparsityPattern::Build [friend]

Definition at line 1155 of file dof_map.h.


Member Data Documentation

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

Definition at line 1055 of file dof_map.h.

Referenced by attach_extra_send_list_object(), and prepare_send_list().

Funtion object to call to add extra entries to the sparsity pattern

Definition at line 1038 of file dof_map.h.

Referenced by attach_extra_sparsity_object().

Data structure containing Dirichlet functions. The ith entry is the constraint matrix row for boundaryid i.

Definition at line 1152 of file dof_map.h.

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

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

bool libMesh::ReferenceCounter::_enable_print_counter = true [static, protected, inherited]

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

Definition at line 137 of file reference_counter.h.

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

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

Last DOF index (plus 1) on processor p.

Definition at line 1027 of file dof_map.h.

Referenced by allgather_recursive_constraints(), clear(), distribute_dofs(), end_dof(), last_dof(), n_dofs_on_processor(), and scatter_constraints().

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

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

Definition at line 1119 of file dof_map.h.

Referenced by clear(), distribute_dofs(), and end_old_dof().

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

Definition at line 1065 of file dof_map.h.

Referenced by attach_extra_send_list_function(), and prepare_send_list().

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

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

Referenced by attach_extra_send_list_function(), and prepare_send_list().

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

Definition at line 1050 of file dof_map.h.

Referenced by attach_extra_sparsity_function().

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

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

Referenced by attach_extra_sparsity_function().

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

First DOF index on processor p.

Definition at line 1022 of file dof_map.h.

Referenced by clear(), distribute_dofs(), first_dof(), and n_dofs_on_processor().

First old DOF index on processor p.

Definition at line 1114 of file dof_map.h.

Referenced by clear(), distribute_dofs(), and first_old_dof().

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

Additional matrices handled by this object. These pointers do not handle the memory, instead, System, who told DofMap about them, owns them.

Definition at line 1017 of file dof_map.h.

Referenced by attach_matrix(), clear(), compute_sparsity(), DofMap(), get_info(), and is_attached().

Mutual exclusion object to enable thread-safe reference counting.

Definition at line 131 of file reference_counter.h.

Total number of degrees of freedom.

Definition at line 1096 of file dof_map.h.

Referenced by clear(), distribute_dofs(), and n_dofs().

std::vector<dof_id_type>* libMesh::DofMap::_n_nz [private]

The number of on-processor nonzeros in my portion of the global matrix. If need_full_sparsity_pattern is true, this will just be a pointer into the corresponding sparsity pattern vector. Otherwise we have to new/delete it ourselves.

Definition at line 1085 of file dof_map.h.

Referenced by attach_matrix(), clear_sparsity(), compute_sparsity(), get_info(), and get_n_nz().

Threads::atomic< unsigned int > libMesh::ReferenceCounter::_n_objects [static, protected, inherited]

The number of objects. Print the reference count information when the number returns to 0.

Definition at line 126 of file reference_counter.h.

Referenced by libMesh::ReferenceCounter::n_objects(), libMesh::ReferenceCounter::ReferenceCounter(), and libMesh::ReferenceCounter::~ReferenceCounter().

Total number of degrees of freedom on old dof objects

Definition at line 1109 of file dof_map.h.

Referenced by clear(), distribute_dofs(), and n_old_dofs().

std::vector<dof_id_type>* libMesh::DofMap::_n_oz [private]

The number of off-processor nonzeros in my portion of the global matrix; allocated similar to _n_nz.

Definition at line 1091 of file dof_map.h.

Referenced by attach_matrix(), clear_sparsity(), compute_sparsity(), get_info(), and get_n_oz().

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

Definition at line 1102 of file dof_map.h.

Referenced by distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), n_SCALAR_dofs(), and reinit().

Data structure containing periodic boundaries. The ith entry is the constraint matrix row for boundaryid i.

Definition at line 1144 of file dof_map.h.

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

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

A list containing all the global DOF indicies that affect the solution on my subdomain.

Definition at line 1033 of file dof_map.h.

Referenced by add_constraints_to_send_list(), add_neighbors_to_send_list(), all_semilocal_indices(), clear(), distribute_dofs(), get_send_list(), and prepare_send_list().

The sparsity pattern of the global matrix, kept around if it might be needed by future additions of the same type of matrix.

Definition at line 1077 of file dof_map.h.

Referenced by attach_matrix(), clear_sparsity(), and compute_sparsity().

const unsigned int libMesh::DofMap::_sys_number [private]

The number of the system we manage DOFs for.

Definition at line 1010 of file dof_map.h.

Referenced by sys_number().

The finite element type for each variable.

Definition at line 1005 of file dof_map.h.

Referenced by add_variable_group(), clear(), n_variable_groups(), variable_group(), variable_group_order(), and variable_group_type().

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

The finite element type for each variable.

Definition at line 1000 of file dof_map.h.

Referenced by add_variable_group(), clear(), n_variables(), variable(), variable_order(), and variable_type().

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

Definition at line 1071 of file dof_map.h.

Referenced by attach_matrix(), clear(), clear_sparsity(), and compute_sparsity().


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

Site Created By: libMesh Developers
Last modified: February 05 2013 19:55:15 UTC

Hosted By:
SourceForge.net Logo