$extrastylesheet
#include <dof_map.h>

Classes | |
| class | AugmentSendList |
| class | AugmentSparsityPattern |
Public Member Functions | |
| DofMap (const unsigned int sys_number, const ParallelObject &parent_decomp) | |
| ~DofMap () | |
| void | attach_matrix (SparseMatrix< Number > &matrix) |
| bool | is_attached (SparseMatrix< Number > &matrix) |
| void | distribute_dofs (MeshBase &) |
| void | compute_sparsity (const MeshBase &) |
| void | clear_sparsity () |
| void | attach_extra_sparsity_object (DofMap::AugmentSparsityPattern &asp) |
| void | attach_extra_sparsity_function (void(*func)(SparsityPattern::Graph &sparsity, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *), void *context=NULL) |
| void | attach_extra_send_list_object (DofMap::AugmentSendList &asl) |
| void | attach_extra_send_list_function (void(*func)(std::vector< dof_id_type > &, void *), void *context=NULL) |
| void | prepare_send_list () |
| const std::vector< dof_id_type > & | get_send_list () const |
| const std::vector< dof_id_type > & | get_n_nz () const |
| const std::vector< dof_id_type > & | get_n_oz () const |
| void | add_variable_group (const VariableGroup &var_group) |
| const VariableGroup & | variable_group (const unsigned int c) const |
| const Variable & | variable (const unsigned int c) const |
| Order | variable_order (const unsigned int c) const |
| Order | variable_group_order (const unsigned int vg) const |
| const FEType & | variable_type (const unsigned int c) const |
| const FEType & | variable_group_type (const unsigned int vg) const |
| unsigned int | n_variable_groups () const |
| unsigned int | n_variables () const |
| bool | has_blocked_representation () const |
| unsigned int | block_size () const |
| dof_id_type | n_dofs () const |
| dof_id_type | n_SCALAR_dofs () const |
| dof_id_type | n_local_dofs () const |
| dof_id_type | n_dofs_on_processor (const processor_id_type proc) const |
| dof_id_type | first_dof (const processor_id_type proc) const |
| dof_id_type | first_dof () const |
| dof_id_type | first_old_dof (const processor_id_type proc) const |
| dof_id_type | first_old_dof () const |
| dof_id_type | last_dof (const processor_id_type proc) const |
| dof_id_type | last_dof () const |
| dof_id_type | end_dof (const processor_id_type proc) const |
| dof_id_type | end_dof () const |
| dof_id_type | end_old_dof (const processor_id_type proc) const |
| dof_id_type | end_old_dof () const |
| void | dof_indices (const Elem *const elem, std::vector< dof_id_type > &di) const |
| void | dof_indices (const Elem *const elem, std::vector< dof_id_type > &di, const unsigned int vn) 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 |
| void | set_implicit_neighbor_dofs (bool implicit_neighbor_dofs) |
| 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 |
| void | local_variable_indices (std::vector< dof_id_type > &idx, const MeshBase &mesh, unsigned int var_num) 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_adjoint_constraint_row (const unsigned int qoi_index, const dof_id_type dof_number, const DofConstraintRow &constraint_row, const Number constraint_rhs, const bool forbid_constraint_overwrite) |
| 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 |
| void | stash_dof_constraints () |
| void | unstash_dof_constraints () |
| NodeConstraints::const_iterator | node_constraint_rows_begin () const |
| NodeConstraints::const_iterator | node_constraint_rows_end () const |
| bool | is_constrained_dof (const dof_id_type dof) const |
| bool | has_heterogenous_adjoint_constraints (const unsigned int qoi_num) const |
| Number | has_heterogenous_adjoint_constraint (const unsigned int qoi_num, const dof_id_type dof) const |
| DofConstraintValueMap & | get_primal_constraint_values () |
| bool | is_constrained_node (const Node *node) const |
| void | print_dof_constraints (std::ostream &os=libMesh::out, bool print_nonlocal=false) const |
| std::string | get_local_constraints (bool print_nonlocal=false) const |
| std::pair< Real, Real > | max_constraint_error (const System &system, NumericVector< Number > *v=NULL) const |
| void | constrain_element_matrix (DenseMatrix< Number > &matrix, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const |
| void | constrain_element_matrix (DenseMatrix< Number > &matrix, std::vector< dof_id_type > &row_dofs, std::vector< dof_id_type > &col_dofs, bool asymmetric_constraint_rows=true) const |
| void | constrain_element_vector (DenseVector< Number > &rhs, std::vector< dof_id_type > &dofs, bool asymmetric_constraint_rows=true) const |
| void | constrain_element_matrix_and_vector (DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const |
| void | heterogenously_constrain_element_matrix_and_vector (DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true, int qoi_index=-1) const |
| void | heterogenously_constrain_element_vector (const DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true, int qoi_index=-1) const |
| void | 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 | enforce_adjoint_constraints_exactly (NumericVector< Number > &v, unsigned int q) const |
| void | add_periodic_boundary (const PeriodicBoundaryBase &periodic_boundary) |
| void | add_periodic_boundary (const PeriodicBoundaryBase &boundary, const PeriodicBoundaryBase &inverse_boundary) |
| bool | is_periodic_boundary (const boundary_id_type boundaryid) const |
| PeriodicBoundaries * | get_periodic_boundaries () |
| void | add_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary) |
| void | add_adjoint_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary, unsigned int q) |
| void | remove_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary) |
| void | remove_adjoint_dirichlet_boundary (const DirichletBoundary &dirichlet_boundary, unsigned int q) |
| const DirichletBoundaries * | get_dirichlet_boundaries () const |
| DirichletBoundaries * | get_dirichlet_boundaries () |
| bool | has_adjoint_dirichlet_boundaries (unsigned int q) const |
| const DirichletBoundaries * | get_adjoint_dirichlet_boundaries (unsigned int q) const |
| DirichletBoundaries * | get_adjoint_dirichlet_boundaries (unsigned int q) |
| 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 |
| const Parallel::Communicator & | comm () const |
| processor_id_type | n_processors () const |
| processor_id_type | processor_id () 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) |
Protected Attributes | |
| const Parallel::Communicator & | _communicator |
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 | |
| void | _dof_indices (const Elem *const elem, std::vector< dof_id_type > &di, const unsigned int v, const Node *const *nodes, unsigned int n_nodes#ifdef DEBUG, std::size_t &tot_size#endif) const |
| UniquePtr< SparsityPattern::Build > | build_sparsity (const MeshBase &mesh) const |
| void | invalidate_dofs (MeshBase &mesh) const |
| DofObject * | node_ptr (MeshBase &mesh, dof_id_type i) const |
| DofObject * | elem_ptr (MeshBase &mesh, dof_id_type i) const |
| template<typename iterator_type > | |
| void | set_nonlocal_dof_objects (iterator_type objects_begin, iterator_type objects_end, MeshBase &mesh, dofobject_accessor objects) |
| void | distribute_local_dofs_var_major (dof_id_type &next_free_dof, MeshBase &mesh) |
| void | distribute_local_dofs_node_major (dof_id_type &next_free_dof, MeshBase &mesh) |
| void | add_neighbors_to_send_list (MeshBase &mesh) |
| void | build_constraint_matrix (DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const |
| void | build_constraint_matrix_and_vector (DenseMatrix< Number > &C, DenseVector< Number > &H, std::vector< dof_id_type > &elem_dofs, int qoi_index=-1, 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 > | _first_scalar_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 |
| UniquePtr< 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 |
| std::vector< dof_id_type > | _first_old_scalar_df |
| DofConstraints | _dof_constraints |
| DofConstraints | _stashed_dof_constraints |
| DofConstraintValueMap | _primal_constraint_values |
| AdjointDofConstraintValues | _adjoint_constraint_values |
| NodeConstraints | _node_constraints |
| PeriodicBoundaries * | _periodic_boundaries |
| DirichletBoundaries * | _dirichlet_boundaries |
| std::vector < DirichletBoundaries * > | _adjoint_dirichlet_boundaries |
| bool | _implicit_neighbor_dofs_initialized |
| bool | _implicit_neighbor_dofs |
Friends | |
| class | SparsityPattern::Build |
This class handles the numbering of degrees of freedom on a mesh. For systems of equations the class supports a fixed number of variables. The degrees of freedom are numbered such that sequential, contiguous blocks belong to distinct processors. This is so that the resulting data structures will work well with parallel linear algebra packages.
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] |
| libMesh::DofMap::DofMap | ( | const unsigned int | sys_number, |
| const ParallelObject & | parent_decomp | ||
| ) | [explicit] |
Constructor. Requires the number of the system for which we will be numbering degrees of freedom & the parent object we are contained in, which defines our communication space.
Definition at line 128 of file dof_map.C.
References _matrices.
: ParallelObject (parent_decomp), _dof_coupling(NULL), _variables(), _variable_groups(), _sys_number(number), _matrices(), _first_df(), _end_df(), _first_scalar_df(), _send_list(), _augment_sparsity_pattern(NULL), _extra_sparsity_function(NULL), _extra_sparsity_context(NULL), _augment_send_list(NULL), _extra_send_list_function(NULL), _extra_send_list_context(NULL), need_full_sparsity_pattern(false), _n_nz(NULL), _n_oz(NULL), _n_dfs(0), _n_SCALAR_dofs(0) #ifdef LIBMESH_ENABLE_AMR , _n_old_dfs(0), _first_old_df(), _end_old_df(), _first_old_scalar_df() #endif #ifdef LIBMESH_ENABLE_CONSTRAINTS , _dof_constraints() , _stashed_dof_constraints() , _primal_constraint_values() , _adjoint_constraint_values() #endif #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS , _node_constraints() #endif #ifdef LIBMESH_ENABLE_PERIODIC , _periodic_boundaries(new PeriodicBoundaries) #endif #ifdef LIBMESH_ENABLE_DIRICHLET , _dirichlet_boundaries(new DirichletBoundaries) , _adjoint_dirichlet_boundaries() #endif , _implicit_neighbor_dofs_initialized(false), _implicit_neighbor_dofs(false) { _matrices.clear(); }
Destructor.
Definition at line 182 of file dof_map.C.
References _adjoint_dirichlet_boundaries, _dirichlet_boundaries, _periodic_boundaries, and clear().
{
this->clear();
#ifdef LIBMESH_ENABLE_PERIODIC
delete _periodic_boundaries;
#endif
#ifdef LIBMESH_ENABLE_DIRICHLET
delete _dirichlet_boundaries;
for (unsigned int q = 0; q != _adjoint_dirichlet_boundaries.size(); ++q)
delete _adjoint_dirichlet_boundaries[q];
#endif
}
| void libMesh::DofMap::_dof_indices | ( | const Elem *const | elem, |
| std::vector< dof_id_type > & | di, | ||
| const unsigned int | v, | ||
| const Node *const * | nodes, | ||
| unsigned int n_nodes#ifdef | DEBUG, | ||
| std::size_t &tot_size# | endif | ||
| ) | const [private] |
Helper function that gets the dof indices on the current element for a non-SCALAR type variable.
| tot_size | In DEBUG mode this will add up the total number of dof indices that should have been added to di. |
Definition at line 1966 of file dof_map.C.
References libMesh::Elem::active(), libMesh::Variable::active_on_subdomain(), libMesh::Elem::dim(), libMesh::DofObject::dof_number(), libMesh::FEInterface::extra_hanging_dofs(), libMesh::FEType::family, libMesh::DofObject::invalid_id, libMesh::Elem::is_vertex(), libMesh::LAGRANGE, libMesh::libmesh_assert(), libMesh::DofObject::n_comp(), n_dofs(), libMesh::FEInterface::n_dofs_at_node(), libMesh::FEInterface::n_dofs_per_elem(), n_nodes, libMesh::DofObject::n_systems(), libMesh::FEType::order, libMesh::Elem::p_level(), libMesh::SUBDIVISION, libMesh::Elem::subdomain_id(), sys_number(), libMesh::Variable::type(), libMesh::Elem::type(), and variable().
Referenced by dof_indices().
{
// This internal function is only useful on valid elements
libmesh_assert(elem);
const Variable & var = this->variable(v);
if (var.active_on_subdomain(elem->subdomain_id()))
{
const ElemType type = elem->type();
const unsigned int sys_num = this->sys_number();
const unsigned int dim = elem->dim();
// Increase the polynomial order on p refined elements
FEType fe_type = var.type();
fe_type.order = static_cast<Order>(fe_type.order +
elem->p_level());
const bool extra_hanging_dofs =
FEInterface::extra_hanging_dofs(fe_type);
#ifdef DEBUG
// The number of dofs per element is non-static for subdivision FE
if (fe_type.family == SUBDIVISION)
tot_size += n_nodes;
else
tot_size += FEInterface::n_dofs(dim,fe_type,type);
#endif
// Get the node-based DOF numbers
for (unsigned int n=0; n<n_nodes; n++)
{
const Node* node = nodes[n];
// There is a potential problem with h refinement. Imagine a
// quad9 that has a linear FE on it. Then, on the hanging side,
// it can falsely identify a DOF at the mid-edge node. This is why
// we call FEInterface instead of node->n_comp() directly.
const unsigned int nc = FEInterface::n_dofs_at_node (dim,
fe_type,
type,
n);
// If this is a non-vertex on a hanging node with extra
// degrees of freedom, we use the non-vertex dofs (which
// come in reverse order starting from the end, to
// simplify p refinement)
if (extra_hanging_dofs && !elem->is_vertex(n))
{
const int dof_offset = node->n_comp(sys_num,v) - nc;
// We should never have fewer dofs than necessary on a
// node unless we're getting indices on a parent element,
// and we should never need the indices on such a node
if (dof_offset < 0)
{
libmesh_assert(!elem->active());
di.resize(di.size() + nc, DofObject::invalid_id);
}
else
for (int i=node->n_comp(sys_num,v)-1; i>=dof_offset; i--)
{
libmesh_assert_not_equal_to (node->dof_number(sys_num,v,i),
DofObject::invalid_id);
di.push_back(node->dof_number(sys_num,v,i));
}
}
// If this is a vertex or an element without extra hanging
// dofs, our dofs come in forward order coming from the
// beginning
else
for (unsigned int i=0; i<nc; i++)
{
libmesh_assert_not_equal_to (node->dof_number(sys_num,v,i),
DofObject::invalid_id);
di.push_back(node->dof_number(sys_num,v,i));
}
}
// If there are any element-based DOF numbers, get them
const unsigned int nc = FEInterface::n_dofs_per_elem(dim,
fe_type,
type);
// We should never have fewer dofs than necessary on an
// element unless we're getting indices on a parent element,
// and we should never need those indices
if (nc != 0)
{
if (elem->n_systems() > sys_num &&
nc <= elem->n_comp(sys_num,v))
{
for (unsigned int i=0; i<nc; i++)
{
libmesh_assert_not_equal_to (elem->dof_number(sys_num,v,i),
DofObject::invalid_id);
di.push_back(elem->dof_number(sys_num,v,i));
}
}
else
{
libmesh_assert(!elem->active() || fe_type.family == LAGRANGE || fe_type.family == SUBDIVISION);
di.resize(di.size() + nc, DofObject::invalid_id);
}
}
}
}
| void libMesh::DofMap::add_adjoint_constraint_row | ( | const unsigned int | qoi_index, |
| const dof_id_type | dof_number, | ||
| const DofConstraintRow & | constraint_row, | ||
| const Number | constraint_rhs, | ||
| const bool | forbid_constraint_overwrite | ||
| ) |
Adds a copy of the user-defined row to the constraint matrix, using an inhomogeneous right-hand-side for the adjoint constraint equation.
forbid_constraint_overwrite here only tests for overwriting the rhs. This method should only be used when an equivalent constraint (with a potentially different rhs) already exists for the primal problem.
Definition at line 1188 of file dof_map_constraints.C.
{
// Optionally allow the user to overwrite constraints. Defaults to false.
if (forbid_constraint_overwrite)
{
if (!this->is_constrained_dof(dof_number))
libmesh_error_msg("ERROR: DOF " << dof_number << " has no corresponding primal constraint!");
#ifndef NDEBUG
// No way to do this without a non-normalized tolerance?
/*
// If the user passed in more than just the rhs, let's check the
// coefficients for consistency
if (!constraint_row.empty())
{
DofConstraintRow row = _dof_constraints[dof_number];
for (DofConstraintRow::const_iterator pos=row.begin();
pos != row.end(); ++pos)
{
libmesh_assert(constraint_row.find(pos->first)->second
== pos->second);
}
}
if (_adjoint_constraint_values[qoi_index].find(dof_number) !=
_adjoint_constraint_values[qoi_index].end())
libmesh_assert_equal_to
(_adjoint_constraint_values[qoi_index][dof_number],
constraint_rhs);
*/
#endif
}
// Creates the map of rhs values if it doesn't already exist; then
// adds the current value to that map
_adjoint_constraint_values[qoi_index].insert(std::make_pair(dof_number, constraint_rhs));
}
| void libMesh::DofMap::add_adjoint_dirichlet_boundary | ( | const DirichletBoundary & | dirichlet_boundary, |
| unsigned int | q | ||
| ) |
Adds a copy of the specified Dirichlet boundary to the system, corresponding to the adjoint problem defined by Quantity of Interest q.
Definition at line 3788 of file dof_map_constraints.C.
{
unsigned int old_size = cast_int<unsigned int>
(_adjoint_dirichlet_boundaries.size());
for (unsigned int i = old_size; i <= qoi_index; ++i)
_adjoint_dirichlet_boundaries.push_back(new DirichletBoundaries());
_adjoint_dirichlet_boundaries[qoi_index]->push_back
(new DirichletBoundary(dirichlet_boundary));
}
| 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 1173 of file dof_map_constraints.C.
{
// Optionally allow the user to overwrite constraints. Defaults to false.
if (forbid_constraint_overwrite)
if (this->is_constrained_dof(dof_number))
libmesh_error_msg("ERROR: DOF " << dof_number << " was already constrained!");
_dof_constraints.insert(std::make_pair(dof_number, constraint_row));
_primal_constraint_values.insert(std::make_pair(dof_number, constraint_rhs));
}
| 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 662 of file dof_map.h.
References add_constraint_row().
Referenced by add_constraint_row().
{ add_constraint_row(dof_number, constraint_row, 0., forbid_constraint_overwrite); }
| 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 3666 of file dof_map_constraints.C.
References libMesh::n_processors().
{
// This function must be run on all processors at once
parallel_object_only();
// Return immediately if there's nothing to gather
if (this->n_processors() == 1)
return;
// We might get to return immediately if none of the processors
// found any constraints
unsigned int has_constraints = !_dof_constraints.empty();
this->comm().max(has_constraints);
if (!has_constraints)
return;
for (DofConstraints::iterator i = _dof_constraints.begin();
i != _dof_constraints.end(); ++i)
{
dof_id_type constrained_dof = i->first;
// We only need the dependencies of our own constrained dofs
if (constrained_dof < this->first_dof() ||
constrained_dof >= this->end_dof())
continue;
DofConstraintRow& constraint_row = i->second;
for (DofConstraintRow::const_iterator
j=constraint_row.begin(); j != constraint_row.end();
++j)
{
dof_id_type constraint_dependency = j->first;
// No point in adding one of our own dofs to the send_list
if (constraint_dependency >= this->first_dof() &&
constraint_dependency < this->end_dof())
continue;
_send_list.push_back(constraint_dependency);
}
}
}
| void libMesh::DofMap::add_dirichlet_boundary | ( | const DirichletBoundary & | dirichlet_boundary | ) |
Adds a copy of the specified Dirichlet boundary to the system.
Definition at line 3781 of file dof_map_constraints.C.
{
_dirichlet_boundaries->push_back(new DirichletBoundary(dirichlet_boundary));
}
| 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 1402 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(), libMesh::Variable::active_on_subdomain(), dof_indices(), libMesh::DofObject::dof_number(), end_dof(), libMesh::FEType::family, first_dof(), libMesh::Elem::get_node(), libMesh::MeshBase::max_node_id(), libMesh::DofObject::n_comp(), libMesh::Elem::n_neighbors(), libMesh::Elem::n_nodes(), n_variables(), n_vars, libMesh::DofObject::n_vars(), libMesh::Elem::neighbor(), libMesh::Elem::node(), libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), libMesh::SCALAR, SCALAR_dof_indices(), libMesh::START_LOG(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::Variable::type(), and variable().
Referenced by distribute_dofs().
{
START_LOG("add_neighbors_to_send_list()", "DofMap");
const unsigned int sys_num = this->sys_number();
//-------------------------------------------------------------------------
// We need to add the DOFs from elements that live on neighboring processors
// that are neighbors of the elements on the local processor
//-------------------------------------------------------------------------
MeshBase::const_element_iterator local_elem_it
= mesh.active_local_elements_begin();
const MeshBase::const_element_iterator local_elem_end
= mesh.active_local_elements_end();
std::vector<bool> node_on_processor(mesh.max_node_id(), false);
std::vector<dof_id_type> di;
std::vector<const Elem *> family;
// Loop over the active local elements, adding all active elements
// that neighbor an active local element to the send list.
for ( ; local_elem_it != local_elem_end; ++local_elem_it)
{
const Elem* elem = *local_elem_it;
// We may have non-local SCALAR dofs on a local element.
// Normally we'd catch those on neighboring elements, but it's
// possible that the neighbors are of different subdomains and
// the SCALAR isn't supported on them.
for (unsigned int v=0; v<this->n_variables(); v++)
if(this->variable(v).type().family == SCALAR &&
this->variable(v).active_on_subdomain(elem->subdomain_id()))
{
// We asked for this variable, so add it to the vector.
std::vector<dof_id_type> di_new;
this->SCALAR_dof_indices(di_new,v);
for (unsigned int i=0; i != di_new.size(); ++i)
{
const dof_id_type dof_index = di_new[i];
if (dof_index < this->first_dof() ||
dof_index >= this->end_dof())
_send_list.push_back(dof_index);
}
}
// We may have non-local nodes on a local element.
for (unsigned int n=0; n!=elem->n_nodes(); n++)
{
// Flag all the nodes of active local elements as seen, so
// we can add nodal neighbor dofs to the send_list later.
node_on_processor[elem->node(n)] = true;
// Add all remote dofs on these nodes to the send_list.
// This is necessary in case those dofs are *not* also dofs
// on neighbors; e.g. in the case of a HIERARCHIC's local
// side which is only a vertex on the neighbor that owns it.
const Node* node = elem->get_node(n);
const unsigned n_vars = node->n_vars(sys_num);
for (unsigned int v=0; v != n_vars; ++v)
{
const unsigned int n_comp = node->n_comp(sys_num, v);
for (unsigned int c=0; c != n_comp; ++c)
{
const dof_id_type dof_index = node->dof_number(sys_num, v, c);
if (dof_index < this->first_dof() || dof_index >= this->end_dof())
{
_send_list.push_back(dof_index);
// libmesh_here();
// libMesh::out << "sys_num,v,c,dof_index="
// << sys_num << ", "
// << v << ", "
// << c << ", "
// << dof_index << '\n';
// node->debug_buffer();
}
}
}
}
// Loop over the neighbors of those elements
for (unsigned int s=0; s<elem->n_neighbors(); s++)
if (elem->neighbor(s) != NULL)
{
family.clear();
// Find all the active elements that neighbor elem
#ifdef LIBMESH_ENABLE_AMR
if (!elem->neighbor(s)->active())
elem->neighbor(s)->active_family_tree_by_neighbor(family, elem);
else
#endif
family.push_back(elem->neighbor(s));
for (dof_id_type i=0; i!=family.size(); ++i)
// If the neighbor lives on a different processor
if (family[i]->processor_id() != this->processor_id())
{
// Get the DOF indices for this neighboring element
this->dof_indices (family[i], di);
// Insert the remote DOF indices into the send list
for (std::size_t j=0; j != di.size(); ++j)
if (di[j] < this->first_dof() ||
di[j] >= this->end_dof())
_send_list.push_back(di[j]);
}
}
}
// Now loop over all non_local active elements and add any missing
// nodal-only neighbors. This will also get any dofs from nonlocal
// nodes on local elements, because every nonlocal node exists on a
// nonlocal nodal neighbor element.
MeshBase::const_element_iterator elem_it
= mesh.active_elements_begin();
const MeshBase::const_element_iterator elem_end
= mesh.active_elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
const Elem* elem = *elem_it;
// If this is one of our elements, we've already added it
if (elem->processor_id() == this->processor_id())
continue;
// Do we need to add the element DOFs?
bool add_elem_dofs = false;
// Check all the nodes of the element to see if it
// shares a node with us
for (unsigned int n=0; n!=elem->n_nodes(); n++)
if (node_on_processor[elem->node(n)])
add_elem_dofs = true;
// Add the element degrees of freedom if it shares at
// least one node.
if (add_elem_dofs)
{
// Get the DOF indices for this neighboring element
this->dof_indices (elem, di);
// Insert the remote DOF indices into the send list
for (std::size_t j=0; j != di.size(); ++j)
if (di[j] < this->first_dof() ||
di[j] >= this->end_dof())
_send_list.push_back(di[j]);
}
}
STOP_LOG("add_neighbors_to_send_list()", "DofMap");
}
| void libMesh::DofMap::add_periodic_boundary | ( | const PeriodicBoundaryBase & | periodic_boundary | ) |
Adds a copy of the specified periodic boundary to the system.
Definition at line 3889 of file dof_map_constraints.C.
References libMesh::PeriodicBoundaryBase::clone(), libMesh::libmesh_assert(), libMesh::PeriodicBoundaryBase::merge(), libMesh::PeriodicBoundaryBase::myboundary, and libMesh::PeriodicBoundaryBase::pairedboundary.
{
// See if we already have a periodic boundary associated myboundary...
PeriodicBoundaryBase* existing_boundary = _periodic_boundaries->boundary(periodic_boundary.myboundary);
if ( existing_boundary == NULL )
{
// ...if not, clone the input (and its inverse) and add them to the PeriodicBoundaries object
PeriodicBoundaryBase* boundary = periodic_boundary.clone().release();
PeriodicBoundaryBase* inverse_boundary = periodic_boundary.clone(PeriodicBoundaryBase::INVERSE).release();
// _periodic_boundaries takes ownership of the pointers
_periodic_boundaries->insert(std::make_pair(boundary->myboundary, boundary));
_periodic_boundaries->insert(std::make_pair(inverse_boundary->myboundary, inverse_boundary));
}
else
{
// ...otherwise, merge this object's variable IDs with the existing boundary object's.
existing_boundary->merge(periodic_boundary);
// Do the same merging process for the inverse boundary. Note: the inverse better already exist!
PeriodicBoundaryBase* inverse_boundary = _periodic_boundaries->boundary(periodic_boundary.pairedboundary);
libmesh_assert(inverse_boundary);
inverse_boundary->merge(periodic_boundary);
}
}
| void libMesh::DofMap::add_periodic_boundary | ( | const PeriodicBoundaryBase & | boundary, |
| const PeriodicBoundaryBase & | inverse_boundary | ||
| ) |
Add a periodic boundary pair
| boundary | - primary boundary |
| inverse_boundary | - inverse boundary |
Definition at line 3919 of file dof_map_constraints.C.
References libMesh::PeriodicBoundaryBase::clone(), libMesh::PeriodicBoundaryBase::myboundary, and libMesh::PeriodicBoundaryBase::pairedboundary.
{
libmesh_assert_equal_to (boundary.myboundary, inverse_boundary.pairedboundary);
libmesh_assert_equal_to (boundary.pairedboundary, inverse_boundary.myboundary);
// Allocate copies on the heap. The _periodic_boundaries object will manage this memory.
// Note: this also means that the copy constructor for the PeriodicBoundary (or user class
// derived therefrom) must be implemented!
// PeriodicBoundary* p_boundary = new PeriodicBoundary(boundary);
// PeriodicBoundary* p_inverse_boundary = new PeriodicBoundary(inverse_boundary);
// We can't use normal copy construction since this leads to slicing with derived classes.
// Use clone() "virtual constructor" instead. But, this *requires* user to override the clone()
// method. Note also that clone() allocates memory. In this case, the _periodic_boundaries object
// takes responsibility for cleanup.
PeriodicBoundaryBase* p_boundary = boundary.clone().release();
PeriodicBoundaryBase* p_inverse_boundary = inverse_boundary.clone().release();
// Add the periodic boundary and its inverse to the PeriodicBoundaries data structure. The
// PeriodicBoundaries data structure takes ownership of the pointers.
_periodic_boundaries->insert(std::make_pair(p_boundary->myboundary, p_boundary));
_periodic_boundaries->insert(std::make_pair(p_inverse_boundary->myboundary, p_inverse_boundary));
}
| 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 218 of file dof_map.C.
References _variable_groups, _variables, and libMesh::VariableGroup::n_variables().
{
_variable_groups.push_back(var_group);
VariableGroup &new_var_group = _variable_groups.back();
for (unsigned int var=0; var<new_var_group.n_variables(); var++)
_variables.push_back (new_var_group(var));
}
| 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 2123 of file dof_map.C.
References _send_list, end_dof(), and first_dof().
{
// We're all semilocal unless we find a counterexample
for (std::size_t i=0; i != dof_indices_in.size(); ++i)
{
const dof_id_type di = dof_indices_in[i];
// If it's not in the local indices
if (di < this->first_dof() ||
di >= this->end_dof())
{
// and if it's not in the ghost indices, then we're not
// semilocal
if (!std::binary_search(_send_list.begin(), _send_list.end(), di))
return false;
}
}
return true;
}
| void libMesh::DofMap::allgather_recursive_constraints | ( | MeshBase & | mesh | ) |
Gathers constraint equation dependencies from other processors
Definition at line 2460 of file dof_map_constraints.C.
References libMesh::MeshBase::active_not_local_elements_begin(), libMesh::MeshBase::active_not_local_elements_end(), libMesh::DofObject::dof_number(), end, libMesh::Elem::get_node(), libMesh::DofObject::id(), libMesh::MeshBase::is_serial(), libMesh::libmesh_assert(), libMesh::libmesh_isnan(), mesh, libMesh::DofObject::n_comp(), libMesh::Elem::n_nodes(), libMesh::n_processors(), n_vars, libMesh::DofObject::n_vars(), libMesh::Elem::node(), libMesh::MeshBase::node_ptr(), libMesh::processor_id(), libMesh::DofObject::processor_id(), and libMesh::TypeVector< T >::size().
{
// This function must be run on all processors at once
parallel_object_only();
// Return immediately if there's nothing to gather
if (this->n_processors() == 1)
return;
// We might get to return immediately if none of the processors
// found any constraints
unsigned int has_constraints = !_dof_constraints.empty()
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
|| !_node_constraints.empty()
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
;
this->comm().max(has_constraints);
if (!has_constraints)
return;
// If we have heterogenous adjoint constraints we need to
// communicate those too.
const unsigned int max_qoi_num =
_adjoint_constraint_values.empty() ?
0 : _adjoint_constraint_values.rbegin()->first;
// We might have calculated constraints for constrained dofs
// which have support on other processors.
// Push these out first.
{
std::vector<std::set<dof_id_type> > pushed_ids(this->n_processors());
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
std::vector<std::set<dof_id_type> > pushed_node_ids(this->n_processors());
#endif
const unsigned int sys_num = this->sys_number();
MeshBase::element_iterator
foreign_elem_it = mesh.active_not_local_elements_begin(),
foreign_elem_end = mesh.active_not_local_elements_end();
// Collect the constraints to push to each processor
for (; foreign_elem_it != foreign_elem_end; ++foreign_elem_it)
{
const Elem *elem = *foreign_elem_it;
// Just checking dof_indices on the foreign element isn't
// enough. Consider a central hanging node between a coarse
// Q2/Q1 element and its finer neighbors on a higher-ranked
// processor. The coarse element's processor will own the node,
// and will thereby own the pressure dof on that node, despite
// the fact that that pressure dof doesn't directly exist on the
// coarse element!
//
// So, we loop through dofs manually.
{
const unsigned int n_vars = elem->n_vars(sys_num);
for (unsigned int v=0; v != n_vars; ++v)
{
const unsigned int n_comp = elem->n_comp(sys_num,v);
for (unsigned int c=0; c != n_comp; ++c)
{
const unsigned int id =
elem->dof_number(sys_num,v,c);
if (this->is_constrained_dof(id))
pushed_ids[elem->processor_id()].insert(id);
}
}
}
for (unsigned int n=0; n != elem->n_nodes(); ++n)
{
const Node *node = elem->get_node(n);
const unsigned int n_vars = node->n_vars(sys_num);
for (unsigned int v=0; v != n_vars; ++v)
{
const unsigned int n_comp = node->n_comp(sys_num,v);
for (unsigned int c=0; c != n_comp; ++c)
{
const unsigned int id =
node->dof_number(sys_num,v,c);
if (this->is_constrained_dof(id))
pushed_ids[elem->processor_id()].insert(id);
}
}
}
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
for (unsigned int n=0; n != elem->n_nodes(); ++n)
if (this->is_constrained_node(elem->get_node(n)))
pushed_node_ids[elem->processor_id()].insert(elem->node(n));
#endif
}
// Now trade constraint rows
for (processor_id_type p = 0; p != this->n_processors(); ++p)
{
// Push to processor procup while receiving from procdown
processor_id_type procup =
cast_int<processor_id_type>((this->processor_id() + p) %
this->n_processors());
processor_id_type procdown =
cast_int<processor_id_type>((this->n_processors() +
this->processor_id() - p) %
this->n_processors());
// Pack the dof constraint rows and rhs's to push to procup
const std::size_t pushed_ids_size = pushed_ids[procup].size();
std::vector<std::vector<dof_id_type> > pushed_keys(pushed_ids_size);
std::vector<std::vector<Real> > pushed_vals(pushed_ids_size);
std::vector<Number> pushed_rhss(pushed_ids_size);
std::vector<std::vector<Number> >
pushed_adj_rhss(max_qoi_num,
std::vector<Number>(pushed_ids_size));
std::set<dof_id_type>::const_iterator it = pushed_ids[procup].begin();
for (std::size_t i = 0; it != pushed_ids[procup].end();
++i, ++it)
{
const dof_id_type pushed_id = *it;
DofConstraintRow &row = _dof_constraints[pushed_id];
std::size_t row_size = row.size();
pushed_keys[i].reserve(row_size);
pushed_vals[i].reserve(row_size);
for (DofConstraintRow::iterator j = row.begin();
j != row.end(); ++j)
{
pushed_keys[i].push_back(j->first);
pushed_vals[i].push_back(j->second);
}
DofConstraintValueMap::const_iterator rhsit =
_primal_constraint_values.find(pushed_id);
pushed_rhss[i] =
(rhsit == _primal_constraint_values.end()) ?
0 : rhsit->second;
for (unsigned int q = 0; q != max_qoi_num; ++q)
{
AdjointDofConstraintValues::const_iterator adjoint_map_it =
_adjoint_constraint_values.find(q);
if (adjoint_map_it == _adjoint_constraint_values.end())
continue;
const DofConstraintValueMap &constraint_map =
adjoint_map_it->second;
DofConstraintValueMap::const_iterator rhsit =
constraint_map.find(pushed_id);
pushed_adj_rhss[q][i] =
(rhsit == constraint_map.end()) ?
0 : rhsit->second;
}
}
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
// Pack the node constraint rows to push to procup
const std::size_t pushed_nodes_size = pushed_node_ids[procup].size();
std::vector<std::vector<dof_id_type> > pushed_node_keys(pushed_nodes_size);
std::vector<std::vector<Real> > pushed_node_vals(pushed_nodes_size);
std::vector<Point> pushed_node_offsets(pushed_nodes_size);
std::set<dof_id_type>::const_iterator node_it = pushed_node_ids[procup].begin();
for (std::size_t i = 0; node_it != pushed_node_ids[procup].end();
++i, ++node_it)
{
const Node *node = mesh.node_ptr(*node_it);
NodeConstraintRow &row = _node_constraints[node].first;
std::size_t row_size = row.size();
pushed_node_keys[i].reserve(row_size);
pushed_node_vals[i].reserve(row_size);
for (NodeConstraintRow::iterator j = row.begin();
j != row.end(); ++j)
{
pushed_node_keys[i].push_back(j->first->id());
pushed_node_vals[i].push_back(j->second);
}
pushed_node_offsets[i] = _node_constraints[node].second;
}
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
// Trade pushed dof constraint rows
std::vector<dof_id_type> pushed_ids_from_me
(pushed_ids[procup].begin(), pushed_ids[procup].end());
std::vector<dof_id_type> pushed_ids_to_me;
std::vector<std::vector<dof_id_type> > pushed_keys_to_me;
std::vector<std::vector<Real> > pushed_vals_to_me;
std::vector<Number> pushed_rhss_to_me;
std::vector<std::vector<Number> > pushed_adj_rhss_to_me;
this->comm().send_receive(procup, pushed_ids_from_me,
procdown, pushed_ids_to_me);
this->comm().send_receive(procup, pushed_keys,
procdown, pushed_keys_to_me);
this->comm().send_receive(procup, pushed_vals,
procdown, pushed_vals_to_me);
this->comm().send_receive(procup, pushed_rhss,
procdown, pushed_rhss_to_me);
this->comm().send_receive(procup, pushed_adj_rhss,
procdown, pushed_adj_rhss_to_me);
libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_keys_to_me.size());
libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_vals_to_me.size());
libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_rhss_to_me.size());
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
// Trade pushed node constraint rows
std::vector<dof_id_type> pushed_node_ids_from_me
(pushed_node_ids[procup].begin(), pushed_node_ids[procup].end());
std::vector<dof_id_type> pushed_node_ids_to_me;
std::vector<std::vector<dof_id_type> > pushed_node_keys_to_me;
std::vector<std::vector<Real> > pushed_node_vals_to_me;
std::vector<Point> pushed_node_offsets_to_me;
this->comm().send_receive(procup, pushed_node_ids_from_me,
procdown, pushed_node_ids_to_me);
this->comm().send_receive(procup, pushed_node_keys,
procdown, pushed_node_keys_to_me);
this->comm().send_receive(procup, pushed_node_vals,
procdown, pushed_node_vals_to_me);
this->comm().send_receive(procup, pushed_node_offsets,
procdown, pushed_node_offsets_to_me);
// Note that we aren't doing a send_receive on the Nodes
// themselves. At this point we should only be pushing out
// "raw" constraints, and there should be no
// constrained-by-constrained-by-etc. situations that could
// involve non-semilocal nodes.
libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_keys_to_me.size());
libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_vals_to_me.size());
libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_offsets_to_me.size());
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
// Add the dof constraints that I've been sent
for (std::size_t i = 0; i != pushed_ids_to_me.size(); ++i)
{
libmesh_assert_equal_to (pushed_keys_to_me[i].size(), pushed_vals_to_me[i].size());
dof_id_type constrained = pushed_ids_to_me[i];
// If we don't already have a constraint for this dof,
// add the one we were sent
if (!this->is_constrained_dof(constrained))
{
DofConstraintRow &row = _dof_constraints[constrained];
for (std::size_t j = 0; j != pushed_keys_to_me[i].size(); ++j)
{
row[pushed_keys_to_me[i][j]] = pushed_vals_to_me[i][j];
}
if (libmesh_isnan(pushed_rhss_to_me[i]))
libmesh_assert(pushed_keys_to_me[i].empty());
if (pushed_rhss_to_me[i] != Number(0))
_primal_constraint_values[constrained] = pushed_rhss_to_me[i];
else
_primal_constraint_values.erase(constrained);
for (unsigned int q = 0; q != max_qoi_num; ++q)
{
AdjointDofConstraintValues::iterator adjoint_map_it =
_adjoint_constraint_values.find(q);
if ((adjoint_map_it == _adjoint_constraint_values.end()) &&
pushed_adj_rhss_to_me[q][constrained] == Number(0))
continue;
if (adjoint_map_it == _adjoint_constraint_values.end())
adjoint_map_it = _adjoint_constraint_values.insert
(std::make_pair(q,DofConstraintValueMap())).first;
DofConstraintValueMap &constraint_map =
adjoint_map_it->second;
if (pushed_adj_rhss_to_me[q][i] != Number(0))
constraint_map[constrained] =
pushed_adj_rhss_to_me[q][i];
else
constraint_map.erase(constrained);
}
}
}
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
// Add the node constraints that I've been sent
for (std::size_t i = 0; i != pushed_node_ids_to_me.size(); ++i)
{
libmesh_assert_equal_to (pushed_node_keys_to_me[i].size(), pushed_node_vals_to_me[i].size());
dof_id_type constrained_id = pushed_node_ids_to_me[i];
// If we don't already have a constraint for this node,
// add the one we were sent
const Node *constrained = mesh.node_ptr(constrained_id);
if (!this->is_constrained_node(constrained))
{
NodeConstraintRow &row = _node_constraints[constrained].first;
for (std::size_t j = 0; j != pushed_node_keys_to_me[i].size(); ++j)
{
const Node *key_node = mesh.node_ptr(pushed_node_keys_to_me[i][j]);
libmesh_assert(key_node);
row[key_node] = pushed_node_vals_to_me[i][j];
}
_node_constraints[constrained].second = pushed_node_offsets_to_me[i];
}
}
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
}
}
// Now start checking for any other constraints we need
// to know about, requesting them recursively.
// Create sets containing the DOFs and nodes we already depend on
typedef std::set<dof_id_type> DoF_RCSet;
DoF_RCSet unexpanded_dofs;
for (DofConstraints::iterator i = _dof_constraints.begin();
i != _dof_constraints.end(); ++i)
{
unexpanded_dofs.insert(i->first);
}
typedef std::set<const Node *> Node_RCSet;
Node_RCSet unexpanded_nodes;
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
for (NodeConstraints::iterator i = _node_constraints.begin();
i != _node_constraints.end(); ++i)
{
unexpanded_nodes.insert(i->first);
}
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
// We have to keep recursing while the unexpanded set is
// nonempty on *any* processor
bool unexpanded_set_nonempty = !unexpanded_dofs.empty() ||
!unexpanded_nodes.empty();
this->comm().max(unexpanded_set_nonempty);
while (unexpanded_set_nonempty)
{
// Let's make sure we don't lose sync in this loop.
parallel_object_only();
// Request sets
DoF_RCSet dof_request_set;
Node_RCSet node_request_set;
// Request sets to send to each processor
std::vector<std::vector<dof_id_type> >
requested_dof_ids(this->n_processors()),
requested_node_ids(this->n_processors());
// And the sizes of each
std::vector<dof_id_type>
dof_ids_on_proc(this->n_processors(), 0),
node_ids_on_proc(this->n_processors(), 0);
// Fill (and thereby sort and uniq!) the main request sets
for (DoF_RCSet::iterator i = unexpanded_dofs.begin();
i != unexpanded_dofs.end(); ++i)
{
DofConstraintRow &row = _dof_constraints[*i];
for (DofConstraintRow::iterator j = row.begin();
j != row.end(); ++j)
{
const dof_id_type constraining_dof = j->first;
// If it's non-local and we haven't already got a
// constraint for it, we might need to ask for one
if (((constraining_dof < this->first_dof()) ||
(constraining_dof >= this->end_dof())) &&
!_dof_constraints.count(constraining_dof))
dof_request_set.insert(constraining_dof);
}
}
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
for (Node_RCSet::iterator i = unexpanded_nodes.begin();
i != unexpanded_nodes.end(); ++i)
{
NodeConstraintRow &row = _node_constraints[*i].first;
for (NodeConstraintRow::iterator j = row.begin();
j != row.end(); ++j)
{
const Node* const node = j->first;
libmesh_assert(node);
// If it's non-local and we haven't already got a
// constraint for it, we might need to ask for one
if ((node->processor_id() != this->processor_id()) &&
!_node_constraints.count(node))
node_request_set.insert(node);
}
}
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
// Clear the unexpanded constraint sets; we're about to expand
// them
unexpanded_dofs.clear();
unexpanded_nodes.clear();
// Count requests by processor
processor_id_type proc_id = 0;
for (DoF_RCSet::iterator i = dof_request_set.begin();
i != dof_request_set.end(); ++i)
{
while (*i >= _end_df[proc_id])
proc_id++;
dof_ids_on_proc[proc_id]++;
}
for (Node_RCSet::iterator i = node_request_set.begin();
i != node_request_set.end(); ++i)
{
libmesh_assert(*i);
libmesh_assert_less ((*i)->processor_id(), this->n_processors());
node_ids_on_proc[(*i)->processor_id()]++;
}
for (processor_id_type p = 0; p != this->n_processors(); ++p)
{
requested_dof_ids[p].reserve(dof_ids_on_proc[p]);
requested_node_ids[p].reserve(node_ids_on_proc[p]);
}
// Prepare each processor's request set
proc_id = 0;
for (DoF_RCSet::iterator i = dof_request_set.begin();
i != dof_request_set.end(); ++i)
{
while (*i >= _end_df[proc_id])
proc_id++;
requested_dof_ids[proc_id].push_back(*i);
}
for (Node_RCSet::iterator i = node_request_set.begin();
i != node_request_set.end(); ++i)
{
requested_node_ids[(*i)->processor_id()].push_back((*i)->id());
}
// Now request constraint rows from other processors
for (processor_id_type p=1; p != this->n_processors(); ++p)
{
// Trade my requests with processor procup and procdown
processor_id_type procup =
cast_int<processor_id_type>((this->processor_id() + p) %
this->n_processors());
processor_id_type procdown =
cast_int<processor_id_type>((this->n_processors() +
this->processor_id() - p) %
this->n_processors());
std::vector<dof_id_type> dof_request_to_fill,
node_request_to_fill;
this->comm().send_receive(procup, requested_dof_ids[procup],
procdown, dof_request_to_fill);
this->comm().send_receive(procup, requested_node_ids[procup],
procdown, node_request_to_fill);
// Fill those requests
std::vector<std::vector<dof_id_type> > dof_row_keys(dof_request_to_fill.size()),
node_row_keys(node_request_to_fill.size());
std::vector<std::vector<Real> > dof_row_vals(dof_request_to_fill.size()),
node_row_vals(node_request_to_fill.size());
std::vector<Number> dof_row_rhss(dof_request_to_fill.size());
std::vector<std::vector<Number> >
dof_adj_rhss(max_qoi_num,
std::vector<Number>(dof_request_to_fill.size()));
std::vector<Point> node_row_rhss(node_request_to_fill.size());
for (std::size_t i=0; i != dof_request_to_fill.size(); ++i)
{
dof_id_type constrained = dof_request_to_fill[i];
if (_dof_constraints.count(constrained))
{
DofConstraintRow &row = _dof_constraints[constrained];
std::size_t row_size = row.size();
dof_row_keys[i].reserve(row_size);
dof_row_vals[i].reserve(row_size);
for (DofConstraintRow::iterator j = row.begin();
j != row.end(); ++j)
{
dof_row_keys[i].push_back(j->first);
dof_row_vals[i].push_back(j->second);
// We should never have a 0 constraint
// coefficient; that's implicit via sparse
// constraint storage
libmesh_assert(j->second);
}
DofConstraintValueMap::const_iterator rhsit =
_primal_constraint_values.find(constrained);
dof_row_rhss[i] = (rhsit == _primal_constraint_values.end()) ?
0 : rhsit->second;
for (unsigned int q = 0; q != max_qoi_num; ++q)
{
AdjointDofConstraintValues::const_iterator adjoint_map_it =
_adjoint_constraint_values.find(q);
if (adjoint_map_it == _adjoint_constraint_values.end())
continue;
const DofConstraintValueMap &constraint_map =
adjoint_map_it->second;
DofConstraintValueMap::const_iterator rhsit =
constraint_map.find(constrained);
dof_adj_rhss[q][i] = (rhsit == constraint_map.end()) ?
0 : rhsit->second;
}
}
else
{
// Get NaN from Real, where it should exist, not
// from Number, which may be std::complex, in which
// case quiet_NaN() silently returns zero, rather
// than sanely returning NaN or throwing an
// exception or sending Stroustrop hate mail.
dof_row_rhss[i] =
std::numeric_limits<Real>::quiet_NaN();
// Make sure we don't get caught by "!isnan(NaN)"
// bugs again.
libmesh_assert(libmesh_isnan(dof_row_rhss[i]));
}
}
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
// FIXME - this could be an unordered set, given a
// hash<pointers> specialization
std::set<const Node*> nodes_requested;
for (std::size_t i=0; i != node_request_to_fill.size(); ++i)
{
dof_id_type constrained_id = node_request_to_fill[i];
const Node *constrained_node = mesh.node_ptr(constrained_id);
if (_node_constraints.count(constrained_node))
{
const NodeConstraintRow &row = _node_constraints[constrained_node].first;
std::size_t row_size = row.size();
node_row_keys[i].reserve(row_size);
node_row_vals[i].reserve(row_size);
for (NodeConstraintRow::const_iterator j = row.begin();
j != row.end(); ++j)
{
const Node* node = j->first;
node_row_keys[i].push_back(node->id());
node_row_vals[i].push_back(j->second);
// If we're not sure whether our send
// destination already has this node, let's give
// it a copy.
if (node->processor_id() != procdown)
nodes_requested.insert(node);
// We can have 0 nodal constraint
// coefficients, where no Lagrange constrant
// exists but non-Lagrange basis constraints
// might.
// libmesh_assert(j->second);
}
node_row_rhss[i] = _node_constraints[constrained_node].second;
}
}
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
// Trade back the results
std::vector<std::vector<dof_id_type> > dof_filled_keys,
node_filled_keys;
std::vector<std::vector<Real> > dof_filled_vals,
node_filled_vals;
std::vector<Number> dof_filled_rhss;
std::vector<std::vector<Number> > adj_filled_rhss;
std::vector<Point> node_filled_rhss;
this->comm().send_receive(procdown, dof_row_keys,
procup, dof_filled_keys);
this->comm().send_receive(procdown, dof_row_vals,
procup, dof_filled_vals);
this->comm().send_receive(procdown, dof_row_rhss,
procup, dof_filled_rhss);
this->comm().send_receive(procdown, dof_adj_rhss,
procup, adj_filled_rhss);
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
this->comm().send_receive(procdown, node_row_keys,
procup, node_filled_keys);
this->comm().send_receive(procdown, node_row_vals,
procup, node_filled_vals);
this->comm().send_receive(procdown, node_row_rhss,
procup, node_filled_rhss);
// Constraining nodes might not even exist on our subset of
// a distributed mesh, so let's make them exist.
if (!mesh.is_serial())
this->comm().send_receive_packed_range
(procdown, &mesh, nodes_requested.begin(), nodes_requested.end(),
procup, &mesh, mesh_inserter_iterator<Node>(mesh));
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
libmesh_assert_equal_to (dof_filled_keys.size(), requested_dof_ids[procup].size());
libmesh_assert_equal_to (dof_filled_vals.size(), requested_dof_ids[procup].size());
libmesh_assert_equal_to (dof_filled_rhss.size(), requested_dof_ids[procup].size());
#ifndef NDEBUG
for (unsigned int q=0; q != adj_filled_rhss.size(); ++q)
libmesh_assert_equal_to (adj_filled_rhss[q].size(), requested_dof_ids[procup].size());
#endif
libmesh_assert_equal_to (node_filled_keys.size(), requested_node_ids[procup].size());
libmesh_assert_equal_to (node_filled_vals.size(), requested_node_ids[procup].size());
libmesh_assert_equal_to (node_filled_rhss.size(), requested_node_ids[procup].size());
// Add any new constraint rows we've found
for (std::size_t i=0; i != requested_dof_ids[procup].size(); ++i)
{
libmesh_assert_equal_to (dof_filled_keys[i].size(), dof_filled_vals[i].size());
if (!libmesh_isnan(dof_filled_rhss[i]))
{
dof_id_type constrained = requested_dof_ids[procup][i];
DofConstraintRow &row = _dof_constraints[constrained];
for (std::size_t j = 0; j != dof_filled_keys[i].size(); ++j)
row[dof_filled_keys[i][j]] = dof_filled_vals[i][j];
if (dof_filled_rhss[i] != Number(0))
_primal_constraint_values[constrained] = dof_filled_rhss[i];
else
_primal_constraint_values.erase(constrained);
for (unsigned int q = 0; q != max_qoi_num; ++q)
{
AdjointDofConstraintValues::iterator adjoint_map_it =
_adjoint_constraint_values.find(q);
if ((adjoint_map_it == _adjoint_constraint_values.end()) &&
adj_filled_rhss[q][constrained] == Number(0))
continue;
if (adjoint_map_it == _adjoint_constraint_values.end())
adjoint_map_it = _adjoint_constraint_values.insert
(std::make_pair(q,DofConstraintValueMap())).first;
DofConstraintValueMap &constraint_map =
adjoint_map_it->second;
if (adj_filled_rhss[q][i] != Number(0))
constraint_map[constrained] =
adj_filled_rhss[q][i];
else
constraint_map.erase(constrained);
}
// And prepare to check for more recursive constraints
if (!dof_filled_keys[i].empty())
unexpanded_dofs.insert(constrained);
}
}
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
for (std::size_t i=0; i != requested_node_ids[procup].size(); ++i)
{
libmesh_assert_equal_to (node_filled_keys[i].size(), node_filled_vals[i].size());
if (!node_filled_keys[i].empty())
{
dof_id_type constrained_id = requested_node_ids[procup][i];
const Node* constrained_node = mesh.node_ptr(constrained_id);
NodeConstraintRow &row = _node_constraints[constrained_node].first;
for (std::size_t j = 0; j != node_filled_keys[i].size(); ++j)
{
const Node* key_node =
mesh.node_ptr(node_filled_keys[i][j]);
libmesh_assert(key_node);
row[key_node] = node_filled_vals[i][j];
}
_node_constraints[constrained_node].second = node_filled_rhss[i];
// And prepare to check for more recursive constraints
unexpanded_nodes.insert(constrained_node);
}
}
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
}
// We have to keep recursing while the unexpanded set is
// nonempty on *any* processor
unexpanded_set_nonempty = !unexpanded_dofs.empty() ||
!unexpanded_nodes.empty();
this->comm().max(unexpanded_set_nonempty);
}
}
| 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 298 of file dof_map.h.
References _extra_send_list_context, and _extra_send_list_function.
{ _extra_send_list_function = func; _extra_send_list_context = context; }
| void libMesh::DofMap::attach_extra_send_list_object | ( | DofMap::AugmentSendList & | asl | ) | [inline] |
Attach an object to populate the send_list with extra entries. This should only add to the send list, but no checking is done to enforce this behavior.
This is an advanced function... use at your own peril!
Definition at line 289 of file dof_map.h.
References _augment_send_list.
{
_augment_send_list = &asl;
}
| 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 275 of file dof_map.h.
References _extra_sparsity_context, and _extra_sparsity_function.
{ _extra_sparsity_function = func; _extra_sparsity_context = context; }
| void libMesh::DofMap::attach_extra_sparsity_object | ( | DofMap::AugmentSparsityPattern & | asp | ) | [inline] |
Attach an object to use to populate the sparsity pattern with extra entries.
Care must be taken that when adding entries they are sorted into the Rows
Further, you _must_ modify n_nz and n_oz properly!
This is an advanced function... use at your own peril!
Definition at line 260 of file dof_map.h.
References _augment_sparsity_pattern.
{
_augment_sparsity_pattern = &asp;
}
| 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 230 of file dof_map.C.
References _matrices, _n_nz, _n_oz, _sp, libMesh::SparseMatrix< T >::attach_dof_map(), libMesh::ParallelObject::comm(), libMesh::libmesh_assert(), libMesh::Parallel::Communicator::max(), libMesh::SparseMatrix< T >::need_full_sparsity_pattern(), need_full_sparsity_pattern, and libMesh::SparseMatrix< T >::update_sparsity_pattern().
Referenced by libMesh::EigenSystem::init_matrices(), and libMesh::ImplicitSystem::init_matrices().
{
parallel_object_only();
// We shouldn't be trying to re-attach the same matrices repeatedly
libmesh_assert (std::find(_matrices.begin(), _matrices.end(),
&matrix) == _matrices.end());
_matrices.push_back(&matrix);
matrix.attach_dof_map (*this);
// If we've already computed sparsity, then it's too late
// to wait for "compute_sparsity" to help with sparse matrix
// initialization, and we need to handle this matrix individually
bool computed_sparsity_already =
((_n_nz && !_n_nz->empty()) ||
(_n_oz && !_n_oz->empty()));
this->comm().max(computed_sparsity_already);
if (computed_sparsity_already &&
matrix.need_full_sparsity_pattern())
{
// We'd better have already computed the full sparsity pattern
// if we need it here
libmesh_assert(need_full_sparsity_pattern);
libmesh_assert(_sp.get());
matrix.update_sparsity_pattern (_sp->sparsity_pattern);
}
if (matrix.need_full_sparsity_pattern())
need_full_sparsity_pattern = true;
}
| unsigned int libMesh::DofMap::block_size | ( | ) | const [inline] |
Definition at line 416 of file dof_map.h.
References has_blocked_representation(), and n_variables().
{
#ifdef LIBMESH_ENABLE_BLOCKED_STORAGE
return (this->has_blocked_representation() ? this->n_variables() : 1);
#else
return 1;
#endif
}
| 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 2194 of file dof_map_constraints.C.
References libMesh::libmesh_assert(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::resize(), libMesh::DenseMatrix< T >::right_multiply(), and libMesh::START_LOG().
{
if (!called_recursively) START_LOG("build_constraint_matrix()", "DofMap");
// Create a set containing the DOFs we already depend on
typedef std::set<dof_id_type> RCSet;
RCSet dof_set;
bool we_have_constraints = false;
// Next insert any other dofs the current dofs might be constrained
// in terms of. Note that in this case we may not be done: Those
// may in turn depend on others. So, we need to repeat this process
// in that case until the system depends only on unconstrained
// degrees of freedom.
for (unsigned int i=0; i<elem_dofs.size(); i++)
if (this->is_constrained_dof(elem_dofs[i]))
{
we_have_constraints = true;
// If the DOF is constrained
DofConstraints::const_iterator
pos = _dof_constraints.find(elem_dofs[i]);
libmesh_assert (pos != _dof_constraints.end());
const DofConstraintRow& constraint_row = pos->second;
// Constraint rows in p refinement may be empty
//libmesh_assert (!constraint_row.empty());
for (DofConstraintRow::const_iterator
it=constraint_row.begin(); it != constraint_row.end();
++it)
dof_set.insert (it->first);
}
// May be safe to return at this point
// (but remember to stop the perflog)
if (!we_have_constraints)
{
STOP_LOG("build_constraint_matrix()", "DofMap");
return;
}
for (unsigned int i=0; i != elem_dofs.size(); ++i)
dof_set.erase (elem_dofs[i]);
// If we added any DOFS then we need to do this recursively.
// It is possible that we just added a DOF that is also
// constrained!
//
// Also, we need to handle the special case of an element having DOFs
// constrained in terms of other, local DOFs
if (!dof_set.empty() || // case 1: constrained in terms of other DOFs
!called_recursively) // case 2: constrained in terms of our own DOFs
{
const unsigned int old_size =
cast_int<unsigned int>(elem_dofs.size());
// Add new dependency dofs to the end of the current dof set
elem_dofs.insert(elem_dofs.end(),
dof_set.begin(), dof_set.end());
// Now we can build the constraint matrix.
// Note that resize also zeros for a DenseMatrix<Number>.
C.resize (old_size,
cast_int<unsigned int>(elem_dofs.size()));
// Create the C constraint matrix.
for (unsigned int i=0; i != old_size; i++)
if (this->is_constrained_dof(elem_dofs[i]))
{
// If the DOF is constrained
DofConstraints::const_iterator
pos = _dof_constraints.find(elem_dofs[i]);
libmesh_assert (pos != _dof_constraints.end());
const DofConstraintRow& constraint_row = pos->second;
// p refinement creates empty constraint rows
// libmesh_assert (!constraint_row.empty());
for (DofConstraintRow::const_iterator
it=constraint_row.begin(); it != constraint_row.end();
++it)
for (unsigned int j=0; j != elem_dofs.size(); j++)
if (elem_dofs[j] == it->first)
C(i,j) = it->second;
}
else
{
C(i,i) = 1.;
}
// May need to do this recursively. It is possible
// that we just replaced a constrained DOF with another
// constrained DOF.
DenseMatrix<Number> Cnew;
this->build_constraint_matrix (Cnew, elem_dofs, true);
if ((C.n() == Cnew.m()) &&
(Cnew.n() == elem_dofs.size())) // If the constraint matrix
C.right_multiply(Cnew); // is constrained...
libmesh_assert_equal_to (C.n(), elem_dofs.size());
}
if (!called_recursively) STOP_LOG("build_constraint_matrix()", "DofMap");
}
| void libMesh::DofMap::build_constraint_matrix_and_vector | ( | DenseMatrix< Number > & | C, |
| DenseVector< Number > & | H, | ||
| std::vector< dof_id_type > & | elem_dofs, | ||
| int | qoi_index = -1, |
||
| const bool | called_recursively = false |
||
| ) | const [private] |
Build the constraint matrix C and the forcing vector H associated with the element degree of freedom indices elem_dofs. The optional parameter called_recursively should be left at the default value false. This is used to handle the special case of an element's degrees of freedom being constrained in terms of other, local degrees of freedom. The usual case is for an elements DOFs to be constrained by some other, external DOFs and/or Dirichlet conditions.
The forcing vector will depend on which solution's heterogenous constraints are being applied. For the default qoi_index this will be the primal solutoin; for qoi_index >= 0 the corresponding adjoint solution's constraints will be used.
Definition at line 2312 of file dof_map_constraints.C.
References libMesh::libmesh_assert(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::resize(), libMesh::DenseMatrix< T >::resize(), libMesh::DenseMatrix< T >::right_multiply(), libMesh::START_LOG(), and libMesh::DenseMatrix< T >::vector_mult_add().
Referenced by extract_local_vector().
{
if (!called_recursively)
START_LOG("build_constraint_matrix_and_vector()", "DofMap");
// Create a set containing the DOFs we already depend on
typedef std::set<dof_id_type> RCSet;
RCSet dof_set;
bool we_have_constraints = false;
// Next insert any other dofs the current dofs might be constrained
// in terms of. Note that in this case we may not be done: Those
// may in turn depend on others. So, we need to repeat this process
// in that case until the system depends only on unconstrained
// degrees of freedom.
for (unsigned int i=0; i<elem_dofs.size(); i++)
if (this->is_constrained_dof(elem_dofs[i]))
{
we_have_constraints = true;
// If the DOF is constrained
DofConstraints::const_iterator
pos = _dof_constraints.find(elem_dofs[i]);
libmesh_assert (pos != _dof_constraints.end());
const DofConstraintRow& constraint_row = pos->second;
// Constraint rows in p refinement may be empty
//libmesh_assert (!constraint_row.empty());
for (DofConstraintRow::const_iterator
it=constraint_row.begin(); it != constraint_row.end();
++it)
dof_set.insert (it->first);
}
// May be safe to return at this point
// (but remember to stop the perflog)
if (!we_have_constraints)
{
STOP_LOG("build_constraint_matrix_and_vector()", "DofMap");
return;
}
for (unsigned int i=0; i != elem_dofs.size(); ++i)
dof_set.erase (elem_dofs[i]);
// If we added any DOFS then we need to do this recursively.
// It is possible that we just added a DOF that is also
// constrained!
//
// Also, we need to handle the special case of an element having DOFs
// constrained in terms of other, local DOFs
if (!dof_set.empty() || // case 1: constrained in terms of other DOFs
!called_recursively) // case 2: constrained in terms of our own DOFs
{
const DofConstraintValueMap *rhs_values = NULL;
if (qoi_index < 0)
rhs_values = &_primal_constraint_values;
else
{
const AdjointDofConstraintValues::const_iterator
it = _adjoint_constraint_values.find(qoi_index);
if (it != _adjoint_constraint_values.end())
rhs_values = &it->second;
}
const unsigned int old_size =
cast_int<unsigned int>(elem_dofs.size());
// Add new dependency dofs to the end of the current dof set
elem_dofs.insert(elem_dofs.end(),
dof_set.begin(), dof_set.end());
// Now we can build the constraint matrix and vector.
// Note that resize also zeros for a DenseMatrix and DenseVector
C.resize (old_size,
cast_int<unsigned int>(elem_dofs.size()));
H.resize (old_size);
// Create the C constraint matrix.
for (unsigned int i=0; i != old_size; i++)
if (this->is_constrained_dof(elem_dofs[i]))
{
// If the DOF is constrained
DofConstraints::const_iterator
pos = _dof_constraints.find(elem_dofs[i]);
libmesh_assert (pos != _dof_constraints.end());
const DofConstraintRow& constraint_row = pos->second;
// p refinement creates empty constraint rows
// libmesh_assert (!constraint_row.empty());
for (DofConstraintRow::const_iterator
it=constraint_row.begin(); it != constraint_row.end();
++it)
for (unsigned int j=0; j != elem_dofs.size(); j++)
if (elem_dofs[j] == it->first)
C(i,j) = it->second;
if (rhs_values)
{
DofConstraintValueMap::const_iterator rhsit =
rhs_values->find(elem_dofs[i]);
if (rhsit != rhs_values->end())
H(i) = rhsit->second;
}
}
else
{
C(i,i) = 1.;
}
// May need to do this recursively. It is possible
// that we just replaced a constrained DOF with another
// constrained DOF.
DenseMatrix<Number> Cnew;
DenseVector<Number> Hnew;
this->build_constraint_matrix_and_vector (Cnew, Hnew, elem_dofs,
qoi_index, true);
if ((C.n() == Cnew.m()) && // If the constraint matrix
(Cnew.n() == elem_dofs.size())) // is constrained...
{
C.right_multiply(Cnew);
// If x = Cy + h and y = Dz + g
// Then x = (CD)z + (Cg + h)
C.vector_mult_add(H, 1, Hnew);
}
libmesh_assert_equal_to (C.n(), elem_dofs.size());
}
if (!called_recursively)
STOP_LOG("build_constraint_matrix_and_vector()", "DofMap");
}
| UniquePtr< SparsityPattern::Build > libMesh::DofMap::build_sparsity | ( | const MeshBase & | mesh | ) | const [private] |
Builds a sparsity pattern
Definition at line 55 of file dof_map.C.
References libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::MeshBase::is_prepared(), libMesh::libmesh_assert(), libMesh::out, libMesh::Threads::parallel_reduce(), libMesh::ParallelObject::processor_id(), and libMesh::START_LOG().
Referenced by compute_sparsity().
{
libmesh_assert (mesh.is_prepared());
START_LOG("build_sparsity()", "DofMap");
// Compute the sparsity structure of the global matrix. This can be
// fed into a PetscMatrix to allocate exacly the number of nonzeros
// necessary to store the matrix. This algorithm should be linear
// in the (# of elements)*(# nodes per element)
// We can be more efficient in the threaded sparsity pattern assembly
// if we don't need the exact pattern. For some sparse matrix formats
// a good upper bound will suffice.
// See if we need to include sparsity pattern entries for coupling
// between neighbor dofs
bool implicit_neighbor_dofs = this->use_coupled_neighbor_dofs(mesh);
// We can compute the sparsity pattern in parallel on multiple
// threads. The goal is for each thread to compute the full sparsity
// pattern for a subset of elements. These sparsity patterns can
// be efficiently merged in the SparsityPattern::Build::join()
// method, especially if there is not too much overlap between them.
// Even better, if the full sparsity pattern is not needed then
// the number of nonzeros per row can be estimated from the
// sparsity patterns created on each thread.
UniquePtr<SparsityPattern::Build> sp
(new SparsityPattern::Build (mesh,
*this,
this->_dof_coupling,
implicit_neighbor_dofs,
need_full_sparsity_pattern));
Threads::parallel_reduce (ConstElemRange (mesh.active_local_elements_begin(),
mesh.active_local_elements_end()), *sp);
sp->parallel_sync();
#ifndef NDEBUG
// Avoid declaring these variables unless asserts are enabled.
const processor_id_type proc_id = mesh.processor_id();
const dof_id_type n_dofs_on_proc = this->n_dofs_on_processor(proc_id);
#endif
libmesh_assert_equal_to (sp->sparsity_pattern.size(), n_dofs_on_proc);
STOP_LOG("build_sparsity()", "DofMap");
// Check to see if we have any extra stuff to add to the sparsity_pattern
if (_extra_sparsity_function)
{
if (_augment_sparsity_pattern)
{
libmesh_here();
libMesh::out << "WARNING: You have specified both an extra sparsity function and object.\n"
<< " Are you sure this is what you meant to do??"
<< std::endl;
}
_extra_sparsity_function
(sp->sparsity_pattern, sp->n_nz,
sp->n_oz, _extra_sparsity_context);
}
if (_augment_sparsity_pattern)
_augment_sparsity_pattern->augment_sparsity_pattern
(sp->sparsity_pattern, sp->n_nz, sp->n_oz);
return UniquePtr<SparsityPattern::Build>(sp.release());
}
| void libMesh::DofMap::clear | ( | ) |
Free all memory associated with the object, but keep the mesh pointer.
Definition at line 809 of file dof_map.C.
References _adjoint_constraint_values, _dof_constraints, _end_df, _end_old_df, _first_df, _first_old_df, _first_old_scalar_df, _first_scalar_df, _matrices, _n_dfs, _n_old_dfs, _primal_constraint_values, _send_list, _stashed_dof_constraints, _variable_groups, _variables, clear_sparsity(), and need_full_sparsity_pattern.
Referenced by ~DofMap().
{
// we don't want to clear
// the coupling matrix!
// It should not change...
//_dof_coupling->clear();
_variables.clear();
_variable_groups.clear();
_first_df.clear();
_end_df.clear();
_first_scalar_df.clear();
_send_list.clear();
this->clear_sparsity();
need_full_sparsity_pattern = false;
#ifdef LIBMESH_ENABLE_AMR
_dof_constraints.clear();
_stashed_dof_constraints.clear();
_primal_constraint_values.clear();
_adjoint_constraint_values.clear();
_n_old_dfs = 0;
_first_old_df.clear();
_end_old_df.clear();
_first_old_scalar_df.clear();
#endif
_matrices.clear();
_n_dfs = 0;
}
| void libMesh::DofMap::clear_sparsity | ( | ) |
Clears the sparsity pattern
Definition at line 1698 of file dof_map.C.
References _n_nz, _n_oz, _sp, libMesh::libmesh_assert(), and need_full_sparsity_pattern.
Referenced by clear(), libMesh::ImplicitSystem::reinit(), and libMesh::EigenSystem::reinit().
{
if (need_full_sparsity_pattern)
{
libmesh_assert(_sp.get());
libmesh_assert(!_n_nz || _n_nz == &_sp->n_nz);
libmesh_assert(!_n_oz || _n_oz == &_sp->n_oz);
_sp.reset();
}
else
{
libmesh_assert(!_sp.get());
delete _n_nz;
delete _n_oz;
}
_n_nz = NULL;
_n_oz = NULL;
}
| const Parallel::Communicator& libMesh::ParallelObject::comm | ( | ) | const [inline, inherited] |
Parallel::Communicator object used by this mesh. Definition at line 86 of file parallel_object.h.
References libMesh::ParallelObject::_communicator.
Referenced by libMesh::__libmesh_petsc_diff_solver_monitor(), libMesh::__libmesh_petsc_diff_solver_residual(), libMesh::__libmesh_petsc_snes_residual(), libMesh::MeshRefinement::_coarsen_elements(), libMesh::ExactSolution::_compute_error(), libMesh::MetisPartitioner::_do_partition(), libMesh::ParmetisPartitioner::_do_repartition(), libMesh::UniformRefinementEstimator::_estimate_error(), libMesh::SlepcEigenSolver< T >::_petsc_shell_matrix_get_diagonal(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_get_diagonal(), libMesh::SlepcEigenSolver< T >::_petsc_shell_matrix_mult(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_mult(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_mult_add(), libMesh::EquationSystems::_read_impl(), libMesh::MeshRefinement::_refine_elements(), libMesh::ImplicitSystem::add_matrix(), libMesh::System::add_vector(), libMesh::UnstructuredMesh::all_second_order(), libMesh::LaplaceMeshSmoother::allgather_graph(), libMesh::FEMSystem::assemble_qoi(), libMesh::MeshCommunication::assign_global_indices(), libMesh::ParmetisPartitioner::assign_partitioning(), attach_matrix(), libMesh::MeshTools::bounding_box(), libMesh::MeshBase::cache_elem_dims(), libMesh::System::calculate_norm(), libMesh::MeshRefinement::coarsen_elements(), libMesh::Nemesis_IO_Helper::compute_num_global_elem_blocks(), libMesh::Nemesis_IO_Helper::compute_num_global_nodesets(), libMesh::Nemesis_IO_Helper::compute_num_global_sidesets(), libMesh::Problem_Interface::computeF(), libMesh::Problem_Interface::computeJacobian(), libMesh::Problem_Interface::computePreconditioner(), libMesh::MeshTools::correct_node_proc_ids(), libMesh::MeshCommunication::delete_remote_elements(), distribute_dofs(), DMlibMeshFunction(), DMlibMeshSetSystem_libMesh(), libMesh::MeshRefinement::eliminate_unrefined_patches(), libMesh::WeightedPatchRecoveryErrorEstimator::estimate_error(), libMesh::PatchRecoveryErrorEstimator::estimate_error(), libMesh::JumpErrorEstimator::estimate_error(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::MeshRefinement::flag_elements_by_elem_fraction(), libMesh::MeshRefinement::flag_elements_by_error_fraction(), libMesh::MeshRefinement::flag_elements_by_nelem_target(), libMesh::CondensedEigenSystem::get_eigenpair(), libMesh::ImplicitSystem::get_linear_solver(), libMesh::LocationMap< T >::init(), libMesh::TimeSolver::init(), libMesh::SystemSubsetBySubdomain::init(), libMesh::EigenSystem::init_data(), libMesh::EigenSystem::init_matrices(), libMesh::ParmetisPartitioner::initialize(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), libMesh::ParallelMesh::libmesh_assert_valid_parallel_flags(), libMesh::MeshTools::libmesh_assert_valid_procids< Elem >(), libMesh::MeshTools::libmesh_assert_valid_procids< Node >(), libMesh::MeshTools::libmesh_assert_valid_refinement_flags(), libMesh::MeshRefinement::limit_level_mismatch_at_edge(), libMesh::MeshRefinement::limit_level_mismatch_at_node(), libMesh::MeshRefinement::make_coarsening_compatible(), libMesh::MeshCommunication::make_elems_parallel_consistent(), libMesh::MeshRefinement::make_flags_parallel_consistent(), libMesh::MeshCommunication::make_node_ids_parallel_consistent(), libMesh::MeshCommunication::make_node_proc_ids_parallel_consistent(), libMesh::MeshCommunication::make_nodes_parallel_consistent(), libMesh::MeshRefinement::make_refinement_compatible(), libMesh::FEMSystem::mesh_position_set(), libMesh::MeshSerializer::MeshSerializer(), libMesh::ParallelMesh::n_active_elem(), libMesh::MeshTools::n_active_levels(), libMesh::BoundaryInfo::n_boundary_conds(), libMesh::BoundaryInfo::n_edge_conds(), libMesh::CondensedEigenSystem::n_global_non_condensed_dofs(), libMesh::MeshTools::n_levels(), libMesh::BoundaryInfo::n_nodeset_conds(), libMesh::MeshTools::n_p_levels(), libMesh::ParallelMesh::parallel_max_elem_id(), libMesh::ParallelMesh::parallel_max_node_id(), libMesh::ParallelMesh::parallel_n_elem(), libMesh::ParallelMesh::parallel_n_nodes(), libMesh::Partitioner::partition(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::petsc_auto_fieldsplit(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), libMesh::MeshBase::prepare_for_use(), libMesh::System::project_vector(), libMesh::Nemesis_IO::read(), libMesh::XdrIO::read(), libMesh::System::read_header(), libMesh::System::read_legacy_data(), libMesh::System::read_SCALAR_dofs(), libMesh::XdrIO::read_serialized_bc_names(), libMesh::XdrIO::read_serialized_bcs(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::System::read_serialized_vector(), libMesh::MeshBase::recalculate_n_partitions(), libMesh::MeshRefinement::refine_and_coarsen_elements(), libMesh::MeshRefinement::refine_elements(), libMesh::Partitioner::set_node_processor_ids(), set_nonlocal_dof_objects(), libMesh::LaplaceMeshSmoother::smooth(), libMesh::MeshBase::subdomain_ids(), libMesh::BoundaryInfo::sync(), libMesh::Parallel::sync_element_data_by_parent_id(), libMesh::Parallel::sync_node_data_by_element_id(), libMesh::MeshRefinement::test_level_one(), libMesh::MeshRefinement::test_unflagged(), libMesh::MeshTools::total_weight(), libMesh::NameBasedIO::write(), libMesh::CheckpointIO::write(), libMesh::XdrIO::write(), libMesh::LegacyXdrIO::write_mesh(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bcs(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), libMesh::XdrIO::write_serialized_nodesets(), and libMesh::DivaIO::write_stream().
{ return _communicator; }
| 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 1661 of file dof_map.C.
References _matrices, _n_nz, _n_oz, _sp, build_sparsity(), end, and need_full_sparsity_pattern.
Referenced by libMesh::EigenSystem::init_matrices(), libMesh::ImplicitSystem::init_matrices(), libMesh::ImplicitSystem::reinit(), and libMesh::EigenSystem::reinit().
{
_sp = this->build_sparsity(mesh);
// It is possible that some \p SparseMatrix implementations want to
// see it. Let them see it before we throw it away.
std::vector<SparseMatrix<Number>* >::const_iterator
pos = _matrices.begin(),
end = _matrices.end();
// If we need the full sparsity pattern, then we share a view of its
// arrays, and we pass it in to the matrices.
if (need_full_sparsity_pattern)
{
_n_nz = &_sp->n_nz;
_n_oz = &_sp->n_oz;
for (; pos != end; ++pos)
(*pos)->update_sparsity_pattern (_sp->sparsity_pattern);
}
// If we don't need the full sparsity pattern anymore, steal the
// arrays we do need and free the rest of the memory
else
{
if (!_n_nz)
_n_nz = new std::vector<dof_id_type>();
_n_nz->swap(_sp->n_nz);
if (!_n_oz)
_n_oz = new std::vector<dof_id_type>();
_n_oz->swap(_sp->n_oz);
_sp.reset();
}
}
| 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 1838 of file dof_map_constraints.C.
References libMesh::libmesh_assert(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::size(), libMesh::START_LOG(), and libMesh::DenseMatrix< T >::vector_mult_transpose().
{
libmesh_assert_equal_to (v.size(), row_dofs.size());
libmesh_assert_equal_to (w.size(), row_dofs.size());
// check for easy return
if (this->_dof_constraints.empty())
return;
// The constrained RHS is built up as R^T F.
DenseMatrix<Number> R;
this->build_constraint_matrix (R, row_dofs);
START_LOG("cnstrn_elem_dyad_mat()", "DofMap");
// It is possible that the vector is not constrained at all.
if ((R.m() == v.size()) &&
(R.n() == row_dofs.size())) // if the RHS is constrained
{
// Compute the matrix-vector products
DenseVector<Number> old_v(v);
DenseVector<Number> old_w(w);
// compute matrix/vector product
R.vector_mult_transpose(v, old_v);
R.vector_mult_transpose(w, old_w);
libmesh_assert_equal_to (row_dofs.size(), v.size());
libmesh_assert_equal_to (row_dofs.size(), w.size());
/* Constrain only v, not w. */
for (unsigned int i=0; i<row_dofs.size(); i++)
if (this->is_constrained_dof(row_dofs[i]))
{
// If the DOF is constrained
libmesh_assert (_dof_constraints.find(row_dofs[i]) != _dof_constraints.end());
v(i) = 0;
}
} // end if the RHS is constrained.
STOP_LOG("cnstrn_elem_dyad_mat()", "DofMap");
}
| 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 1372 of file dof_map_constraints.C.
References libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::libmesh_assert(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::right_multiply(), and libMesh::START_LOG().
{
libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
// check for easy return
if (this->_dof_constraints.empty())
return;
// The constrained matrix is built up as C^T K C.
DenseMatrix<Number> C;
this->build_constraint_matrix (C, elem_dofs);
START_LOG("constrain_elem_matrix()", "DofMap");
// It is possible that the matrix is not constrained at all.
if ((C.m() == matrix.m()) &&
(C.n() == elem_dofs.size())) // It the matrix is constrained
{
// Compute the matrix-matrix-matrix product C^T K C
matrix.left_multiply_transpose (C);
matrix.right_multiply (C);
libmesh_assert_equal_to (matrix.m(), matrix.n());
libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
for (unsigned int i=0; i<elem_dofs.size(); i++)
// If the DOF is constrained
if (this->is_constrained_dof(elem_dofs[i]))
{
for (unsigned int j=0; j<matrix.n(); j++)
matrix(i,j) = 0.;
matrix(i,i) = 1.;
if (asymmetric_constraint_rows)
{
DofConstraints::const_iterator
pos = _dof_constraints.find(elem_dofs[i]);
libmesh_assert (pos != _dof_constraints.end());
const DofConstraintRow& constraint_row = pos->second;
// This is an overzealous assertion in the presence of
// heterogenous constraints: we now can constrain "u_i = c"
// with no other u_j terms involved.
//
// libmesh_assert (!constraint_row.empty());
for (DofConstraintRow::const_iterator
it=constraint_row.begin(); it != constraint_row.end();
++it)
for (unsigned int j=0; j<elem_dofs.size(); j++)
if (elem_dofs[j] == it->first)
matrix(i,j) = -it->second;
}
}
} // end if is constrained...
STOP_LOG("constrain_elem_matrix()", "DofMap");
}
| 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 1713 of file dof_map_constraints.C.
References libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::libmesh_assert(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::right_multiply(), and libMesh::START_LOG().
{
libmesh_assert_equal_to (row_dofs.size(), matrix.m());
libmesh_assert_equal_to (col_dofs.size(), matrix.n());
// check for easy return
if (this->_dof_constraints.empty())
return;
// The constrained matrix is built up as R^T K C.
DenseMatrix<Number> R;
DenseMatrix<Number> C;
// Safeguard against the user passing us the same
// object for row_dofs and col_dofs. If that is done
// the calls to build_matrix would fail
std::vector<dof_id_type> orig_row_dofs(row_dofs);
std::vector<dof_id_type> orig_col_dofs(col_dofs);
this->build_constraint_matrix (R, orig_row_dofs);
this->build_constraint_matrix (C, orig_col_dofs);
START_LOG("constrain_elem_matrix()", "DofMap");
row_dofs = orig_row_dofs;
col_dofs = orig_col_dofs;
// It is possible that the matrix is not constrained at all.
if ((R.m() == matrix.m()) &&
(R.n() == row_dofs.size()) &&
(C.m() == matrix.n()) &&
(C.n() == col_dofs.size())) // If the matrix is constrained
{
// K_constrained = R^T K C
matrix.left_multiply_transpose (R);
matrix.right_multiply (C);
libmesh_assert_equal_to (matrix.m(), row_dofs.size());
libmesh_assert_equal_to (matrix.n(), col_dofs.size());
for (unsigned int i=0; i<row_dofs.size(); i++)
if (this->is_constrained_dof(row_dofs[i]))
{
for (unsigned int j=0; j<matrix.n(); j++)
{
if(row_dofs[i] != col_dofs[j])
matrix(i,j) = 0.;
else // If the DOF is constrained
matrix(i,j) = 1.;
}
if (asymmetric_constraint_rows)
{
DofConstraints::const_iterator
pos = _dof_constraints.find(row_dofs[i]);
libmesh_assert (pos != _dof_constraints.end());
const DofConstraintRow& constraint_row = pos->second;
libmesh_assert (!constraint_row.empty());
for (DofConstraintRow::const_iterator
it=constraint_row.begin(); it != constraint_row.end();
++it)
for (unsigned int j=0; j<col_dofs.size(); j++)
if (col_dofs[j] == it->first)
matrix(i,j) = -it->second;
}
}
} // end if is constrained...
STOP_LOG("constrain_elem_matrix()", "DofMap");
}
| 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 1444 of file dof_map_constraints.C.
References libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::libmesh_assert(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::right_multiply(), libMesh::DenseVector< T >::size(), libMesh::START_LOG(), and libMesh::DenseMatrix< T >::vector_mult_transpose().
{
libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
// check for easy return
if (this->_dof_constraints.empty())
return;
// The constrained matrix is built up as C^T K C.
// The constrained RHS is built up as C^T F
DenseMatrix<Number> C;
this->build_constraint_matrix (C, elem_dofs);
START_LOG("cnstrn_elem_mat_vec()", "DofMap");
// It is possible that the matrix is not constrained at all.
if ((C.m() == matrix.m()) &&
(C.n() == elem_dofs.size())) // It the matrix is constrained
{
// Compute the matrix-matrix-matrix product C^T K C
matrix.left_multiply_transpose (C);
matrix.right_multiply (C);
libmesh_assert_equal_to (matrix.m(), matrix.n());
libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
for (unsigned int i=0; i<elem_dofs.size(); i++)
if (this->is_constrained_dof(elem_dofs[i]))
{
for (unsigned int j=0; j<matrix.n(); j++)
matrix(i,j) = 0.;
// If the DOF is constrained
matrix(i,i) = 1.;
// This will put a nonsymmetric entry in the constraint
// row to ensure that the linear system produces the
// correct value for the constrained DOF.
if (asymmetric_constraint_rows)
{
DofConstraints::const_iterator
pos = _dof_constraints.find(elem_dofs[i]);
libmesh_assert (pos != _dof_constraints.end());
const DofConstraintRow& constraint_row = pos->second;
// p refinement creates empty constraint rows
// libmesh_assert (!constraint_row.empty());
for (DofConstraintRow::const_iterator
it=constraint_row.begin(); it != constraint_row.end();
++it)
for (unsigned int j=0; j<elem_dofs.size(); j++)
if (elem_dofs[j] == it->first)
matrix(i,j) = -it->second;
}
}
// Compute the matrix-vector product C^T F
DenseVector<Number> old_rhs(rhs);
// compute matrix/vector product
C.vector_mult_transpose(rhs, old_rhs);
} // end if is constrained...
STOP_LOG("cnstrn_elem_mat_vec()", "DofMap");
}
| 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 1796 of file dof_map_constraints.C.
References libMesh::libmesh_assert(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::size(), libMesh::START_LOG(), and libMesh::DenseMatrix< T >::vector_mult_transpose().
{
libmesh_assert_equal_to (rhs.size(), row_dofs.size());
// check for easy return
if (this->_dof_constraints.empty())
return;
// The constrained RHS is built up as R^T F.
DenseMatrix<Number> R;
this->build_constraint_matrix (R, row_dofs);
START_LOG("constrain_elem_vector()", "DofMap");
// It is possible that the vector is not constrained at all.
if ((R.m() == rhs.size()) &&
(R.n() == row_dofs.size())) // if the RHS is constrained
{
// Compute the matrix-vector product
DenseVector<Number> old_rhs(rhs);
R.vector_mult_transpose(rhs, old_rhs);
libmesh_assert_equal_to (row_dofs.size(), rhs.size());
for (unsigned int i=0; i<row_dofs.size(); i++)
if (this->is_constrained_dof(row_dofs[i]))
{
// If the DOF is constrained
libmesh_assert (_dof_constraints.find(row_dofs[i]) != _dof_constraints.end());
rhs(i) = 0;
}
} // end if the RHS is constrained.
STOP_LOG("constrain_elem_vector()", "DofMap");
}
| 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 1889 of file dof_map_constraints.C.
{
// check for easy return
if (this->_dof_constraints.empty())
return;
// All the work is done by \p build_constraint_matrix. We just need
// a dummy matrix.
DenseMatrix<Number> R;
this->build_constraint_matrix (R, dofs);
}
| 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 3716 of file dof_map_constraints.C.
References 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(), n_nodes, libMesh::Elem::n_nodes(), libMesh::Elem::n_sides(), libMesh::FEType::order, libMesh::Elem::p_level(), libMesh::Threads::spin_mtx, and libMesh::Elem::type().
Referenced by libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), and libMesh::FEGenericBase< OutputType >::compute_proj_constraints().
{
// We're constraining dofs on elem which correspond to p refinement
// levels above p - this only makes sense if elem's p refinement
// level is above p.
libmesh_assert_greater (elem->p_level(), p);
libmesh_assert_less (s, elem->n_sides());
const unsigned int sys_num = this->sys_number();
const unsigned int dim = elem->dim();
ElemType type = elem->type();
FEType low_p_fe_type = this->variable_type(var);
FEType high_p_fe_type = this->variable_type(var);
low_p_fe_type.order = static_cast<Order>(low_p_fe_type.order + p);
high_p_fe_type.order = static_cast<Order>(high_p_fe_type.order +
elem->p_level());
const unsigned int n_nodes = elem->n_nodes();
for (unsigned int n = 0; n != n_nodes; ++n)
if (elem->is_node_on_side(n, s))
{
const Node * const node = elem->get_node(n);
const unsigned int low_nc =
FEInterface::n_dofs_at_node (dim, low_p_fe_type, type, n);
const unsigned int high_nc =
FEInterface::n_dofs_at_node (dim, high_p_fe_type, type, n);
// since we may be running this method concurrently
// on multiple threads we need to acquire a lock
// before modifying the _dof_constraints object.
Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
if (elem->is_vertex(n))
{
// Add "this is zero" constraint rows for high p vertex
// dofs
for (unsigned int i = low_nc; i != high_nc; ++i)
{
_dof_constraints[node->dof_number(sys_num,var,i)].clear();
_primal_constraint_values.erase(node->dof_number(sys_num,var,i));
}
}
else
{
const unsigned int total_dofs = node->n_comp(sys_num, var);
libmesh_assert_greater_equal (total_dofs, high_nc);
// Add "this is zero" constraint rows for high p
// non-vertex dofs, which are numbered in reverse
for (unsigned int j = low_nc; j != high_nc; ++j)
{
const unsigned int i = total_dofs - j - 1;
_dof_constraints[node->dof_number(sys_num,var,i)].clear();
_primal_constraint_values.erase(node->dof_number(sys_num,var,i));
}
}
}
}
| DofConstraints::const_iterator libMesh::DofMap::constraint_rows_begin | ( | ) | const [inline] |
Returns an iterator pointing to the first DoF constraint row
Definition at line 670 of file dof_map.h.
References _dof_constraints.
{ 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 676 of file dof_map.h.
References _dof_constraints.
{ 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 1028 of file dof_map_constraints.C.
References libMesh::StoredRange< iterator_type, object_type >::empty(), libMesh::MeshBase::is_prepared(), libMesh::MeshBase::is_serial(), libMesh::libmesh_assert(), libMesh::MeshBase::local_elements_begin(), libMesh::MeshBase::local_elements_end(), libMesh::MeshBase::mesh_dimension(), libMesh::Threads::parallel_for(), libMesh::StoredRange< iterator_type, object_type >::reset(), libMesh::START_LOG(), libMesh::MeshBase::sub_point_locator(), and libMesh::Parallel::verify().
Referenced by libMesh::EquationSystems::allgather(), libMesh::EquationSystems::reinit(), and libMesh::System::reinit_constraints().
{
parallel_object_only();
START_LOG("create_dof_constraints()", "DofMap");
libmesh_assert (mesh.is_prepared());
// We might get constraint equations from AMR hanging nodes in 2D/3D
// or from boundary conditions in any dimension
const bool possible_local_constraints = false
#ifdef LIBMESH_ENABLE_AMR
|| mesh.mesh_dimension() > 1
#endif
#ifdef LIBMESH_ENABLE_PERIODIC
|| !_periodic_boundaries->empty()
#endif
#ifdef LIBMESH_ENABLE_DIRICHLET
|| !_dirichlet_boundaries->empty()
#endif
;
// Even if we don't have constraints, another processor might.
bool possible_global_constraints = possible_local_constraints;
#if defined(LIBMESH_ENABLE_PERIODIC) || defined(LIBMESH_ENABLE_DIRICHLET) || defined(LIBMESH_ENABLE_AMR)
libmesh_assert(this->comm().verify(mesh.is_serial()));
this->comm().max(possible_global_constraints);
#endif
if (!possible_global_constraints)
{
// Clear out any old constraints; maybe the user just deleted
// their last remaining dirichlet/periodic/user constraint?
#ifdef LIBMESH_ENABLE_CONSTRAINTS
_dof_constraints.clear();
_stashed_dof_constraints.clear();
_primal_constraint_values.clear();
_adjoint_constraint_values.clear();
#endif
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
_node_constraints.clear();
#endif
// make sure we stop logging though
STOP_LOG("create_dof_constraints()", "DofMap");
return;
}
// Here we build the hanging node constraints. This is done
// by enforcing the condition u_a = u_b along hanging sides.
// u_a = u_b is collocated at the nodes of side a, which gives
// one row of the constraint matrix.
// Processors only compute their local constraints
ConstElemRange range (mesh.local_elements_begin(),
mesh.local_elements_end());
// Global computation fails if we're using a FEMFunctionBase BC on a
// SerialMesh in parallel
// ConstElemRange range (mesh.elements_begin(),
// mesh.elements_end());
// compute_periodic_constraints requires a point_locator() from our
// Mesh, but point_locator() construction is parallel and threaded.
// Rather than nest threads within threads we'll make sure it's
// preconstructed.
#ifdef LIBMESH_ENABLE_PERIODIC
bool need_point_locator = !_periodic_boundaries->empty() && !range.empty();
this->comm().max(need_point_locator);
if (need_point_locator)
mesh.sub_point_locator();
#endif
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
// recalculate node constraints from scratch
_node_constraints.clear();
Threads::parallel_for (range,
ComputeNodeConstraints (_node_constraints,
*this,
#ifdef LIBMESH_ENABLE_PERIODIC
*_periodic_boundaries,
#endif
mesh));
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
// recalculate dof constraints from scratch
_dof_constraints.clear();
_stashed_dof_constraints.clear();
_primal_constraint_values.clear();
_adjoint_constraint_values.clear();
// Look at all the variables in the system. Reset the element
// range at each iteration -- there is no need to reconstruct it.
for (unsigned int variable_number=0; variable_number<this->n_variables();
++variable_number, range.reset())
Threads::parallel_for (range,
ComputeConstraints (_dof_constraints,
*this,
#ifdef LIBMESH_ENABLE_PERIODIC
*_periodic_boundaries,
#endif
mesh,
variable_number));
#ifdef LIBMESH_ENABLE_DIRICHLET
for (DirichletBoundaries::iterator
i = _dirichlet_boundaries->begin();
i != _dirichlet_boundaries->end(); ++i, range.reset())
{
Threads::parallel_for
(range,
ConstrainDirichlet(*this, mesh, time, **i,
AddPrimalConstraint(*this))
);
}
for (unsigned int qoi_index = 0;
qoi_index != _adjoint_dirichlet_boundaries.size();
++qoi_index)
{
for (DirichletBoundaries::iterator
i = _adjoint_dirichlet_boundaries[qoi_index]->begin();
i != _adjoint_dirichlet_boundaries[qoi_index]->end();
++i, range.reset())
{
Threads::parallel_for
(range,
ConstrainDirichlet(*this, mesh, time, **i,
AddAdjointConstraint(*this, qoi_index))
);
}
}
#endif // LIBMESH_ENABLE_DIRICHLET
STOP_LOG("create_dof_constraints()", "DofMap");
}
| void libMesh::ReferenceCounter::disable_print_counter_info | ( | ) | [static, inherited] |
Definition at line 106 of file reference_counter.C.
References libMesh::ReferenceCounter::_enable_print_counter.
Referenced by libMesh::LibMeshInit::LibMeshInit().
{
_enable_print_counter = false;
return;
}
| 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 845 of file dof_map.C.
References _end_df, _end_old_df, _first_df, _first_old_df, _first_old_scalar_df, _first_scalar_df, _n_dfs, _n_old_dfs, _send_list, add_neighbors_to_send_list(), libMesh::Parallel::Communicator::allgather(), libMesh::ParallelObject::comm(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), libMesh::DofObject::dof_number(), elem_ptr(), libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), end_dof(), libMesh::FEType::family, first_dof(), libMesh::DofObject::invalid_id, invalidate_dofs(), libMesh::MeshBase::is_prepared(), libMesh::libmesh_assert(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), mesh, libMesh::DofObject::n_comp(), n_dofs(), libMesh::ParallelObject::n_processors(), n_SCALAR_dofs(), n_variables(), libMesh::DofObject::n_vars(), node_ptr(), libMesh::MeshBase::nodes_begin(), libMesh::MeshBase::nodes_end(), libMesh::on_command_line(), libMesh::FEType::order, libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), reinit(), libMesh::SCALAR, set_nonlocal_dof_objects(), libMesh::START_LOG(), sys_number(), libMesh::Variable::type(), and variable().
Referenced by libMesh::EquationSystems::allgather(), and libMesh::EquationSystems::reinit().
{
// This function must be run on all processors at once
parallel_object_only();
// Log how long it takes to distribute the degrees of freedom
START_LOG("distribute_dofs()", "DofMap");
libmesh_assert (mesh.is_prepared());
const processor_id_type proc_id = this->processor_id();
const processor_id_type n_proc = this->n_processors();
// libmesh_assert_greater (this->n_variables(), 0);
libmesh_assert_less (proc_id, n_proc);
// re-init in case the mesh has changed
this->reinit(mesh);
// By default distribute variables in a
// var-major fashion, but allow run-time
// specification
bool node_major_dofs = libMesh::on_command_line ("--node_major_dofs");
// The DOF counter, will be incremented as we encounter
// new degrees of freedom
dof_id_type next_free_dof = 0;
// Clear the send list before we rebuild it
_send_list.clear();
// Set temporary DOF indices on this processor
if (node_major_dofs)
this->distribute_local_dofs_node_major (next_free_dof, mesh);
else
this->distribute_local_dofs_var_major (next_free_dof, mesh);
// Get DOF counts on all processors
std::vector<dof_id_type> dofs_on_proc(n_proc, 0);
this->comm().allgather(next_free_dof, dofs_on_proc);
// Resize and fill the _first_df and _end_df arrays
#ifdef LIBMESH_ENABLE_AMR
_first_old_df = _first_df;
_end_old_df = _end_df;
#endif
_first_df.resize(n_proc);
_end_df.resize (n_proc);
// Get DOF offsets
_first_df[0] = 0;
for (processor_id_type i=1; i < n_proc; ++i)
_first_df[i] = _end_df[i-1] = _first_df[i-1] + dofs_on_proc[i-1];
_end_df[n_proc-1] = _first_df[n_proc-1] + dofs_on_proc[n_proc-1];
// Clear all the current DOF indices
// (distribute_dofs expects them cleared!)
this->invalidate_dofs(mesh);
next_free_dof = _first_df[proc_id];
// Set permanent DOF indices on this processor
if (node_major_dofs)
this->distribute_local_dofs_node_major (next_free_dof, mesh);
else
this->distribute_local_dofs_var_major (next_free_dof, mesh);
libmesh_assert_equal_to (next_free_dof, _end_df[proc_id]);
//------------------------------------------------------------
// At this point, all n_comp and dof_number values on local
// DofObjects should be correct, but a ParallelMesh might have
// incorrect values on non-local DofObjects. Let's request the
// correct values from each other processor.
if (this->n_processors() > 1)
{
this->set_nonlocal_dof_objects(mesh.nodes_begin(),
mesh.nodes_end(),
mesh, &DofMap::node_ptr);
this->set_nonlocal_dof_objects(mesh.elements_begin(),
mesh.elements_end(),
mesh, &DofMap::elem_ptr);
}
#ifdef DEBUG
{
const unsigned int
sys_num = this->sys_number();
// Processors should all agree on DoF ids
MeshTools::libmesh_assert_valid_dof_ids(mesh);
// DoF processor ids should match DofObject processor ids
MeshBase::const_node_iterator node_it = mesh.nodes_begin();
const MeshBase::const_node_iterator node_end = mesh.nodes_end();
for ( ; node_it != node_end; ++node_it)
{
DofObject const * const dofobj = *node_it;
const processor_id_type obj_proc_id = dofobj->processor_id();
for (unsigned int v=0; v != dofobj->n_vars(sys_num); ++v)
for (unsigned int c=0; c != dofobj->n_comp(sys_num,v); ++c)
{
const dof_id_type dofid = dofobj->dof_number(sys_num,v,c);
libmesh_assert_greater_equal (dofid, this->first_dof(obj_proc_id));
libmesh_assert_less (dofid, this->end_dof(obj_proc_id));
}
}
MeshBase::const_element_iterator elem_it = mesh.elements_begin();
const MeshBase::const_element_iterator elem_end = mesh.elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
DofObject const * const dofobj = *elem_it;
const processor_id_type obj_proc_id = dofobj->processor_id();
for (unsigned int v=0; v != dofobj->n_vars(sys_num); ++v)
for (unsigned int c=0; c != dofobj->n_comp(sys_num,v); ++c)
{
const dof_id_type dofid = dofobj->dof_number(sys_num,v,c);
libmesh_assert_greater_equal (dofid, this->first_dof(obj_proc_id));
libmesh_assert_less (dofid, this->end_dof(obj_proc_id));
}
}
}
#endif
// Set the total number of degrees of freedom, then start finding
// SCALAR degrees of freedom
#ifdef LIBMESH_ENABLE_AMR
_n_old_dfs = _n_dfs;
_first_old_scalar_df = _first_scalar_df;
#endif
_n_dfs = _end_df[n_proc-1];
_first_scalar_df.clear();
_first_scalar_df.resize(this->n_variables(), DofObject::invalid_id);
dof_id_type current_SCALAR_dof_index = n_dofs() - n_SCALAR_dofs();
// Calculate and cache the initial DoF indices for SCALAR variables.
// This is an O(N_vars) calculation so we want to do it once per
// renumbering rather than once per SCALAR_dof_indices() call
for (unsigned int v=0; v<this->n_variables(); v++)
if(this->variable(v).type().family == SCALAR)
{
_first_scalar_df[v] = current_SCALAR_dof_index;
current_SCALAR_dof_index += this->variable(v).type().order;
}
STOP_LOG("distribute_dofs()", "DofMap");
// Note that in the add_neighbors_to_send_list nodes on processor
// boundaries that are shared by multiple elements are added for
// each element.
this->add_neighbors_to_send_list(mesh);
// Here we used to clean up that data structure; now System and
// EquationSystems call that for us, after we've added constraint
// dependencies to the send_list too.
// this->sort_send_list ();
}
| 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 1100 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::libmesh_assert(), libMesh::MeshTools::libmesh_assert_valid_procids< Node >(), libMesh::MeshBase::local_nodes_begin(), libMesh::MeshBase::local_nodes_end(), mesh, libMesh::DofObject::n_comp(), libMesh::DofObject::n_comp_group(), n_nodes, libMesh::Elem::n_nodes(), libMesh::ParallelObject::n_processors(), libMesh::DofObject::n_var_groups(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::FEType::order, libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), libMesh::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().
{
const unsigned int sys_num = this->sys_number();
const unsigned int n_var_groups = this->n_variable_groups();
//-------------------------------------------------------------------------
// First count and assign temporary numbers to local dofs
MeshBase::element_iterator elem_it = mesh.active_local_elements_begin();
const MeshBase::element_iterator elem_end = mesh.active_local_elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
// Only number dofs connected to active
// elements on this processor.
Elem* elem = *elem_it;
const unsigned int n_nodes = elem->n_nodes();
// First number the nodal DOFS
for (unsigned int n=0; n<n_nodes; n++)
{
Node* node = elem->get_node(n);
for (unsigned vg=0; vg<n_var_groups; vg++)
{
const VariableGroup &vg_description(this->variable_group(vg));
if( (vg_description.type().family != SCALAR) &&
(vg_description.active_on_subdomain(elem->subdomain_id())) )
{
// assign dof numbers (all at once) if this is
// our node and if they aren't already there
if ((node->n_comp_group(sys_num,vg) > 0) &&
(node->processor_id() == this->processor_id()) &&
(node->vg_dof_base(sys_num,vg) ==
DofObject::invalid_id))
{
node->set_vg_dof_base(sys_num,
vg,
next_free_dof);
next_free_dof += (vg_description.n_variables()*
node->n_comp_group(sys_num,vg));
//node->debug_buffer();
}
}
}
}
// Now number the element DOFS
for (unsigned vg=0; vg<n_var_groups; vg++)
{
const VariableGroup &vg_description(this->variable_group(vg));
if ( (vg_description.type().family != SCALAR) &&
(vg_description.active_on_subdomain(elem->subdomain_id())) )
if (elem->n_comp_group(sys_num,vg) > 0)
{
libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg),
DofObject::invalid_id);
elem->set_vg_dof_base(sys_num,
vg,
next_free_dof);
next_free_dof += (vg_description.n_variables()*
elem->n_comp(sys_num,vg));
}
}
} // done looping over elements
// we may have missed assigning DOFs to nodes that we own
// but to which we have no connected elements matching our
// variable restriction criterion. this will happen, for example,
// if variable V is restricted to subdomain S. We may not own
// any elements which live in S, but we may own nodes which are
// *connected* to elements which do. in this scenario these nodes
// will presently have unnumbered DOFs. we need to take care of
// them here since we own them and no other processor will touch them.
{
MeshBase::node_iterator node_it = mesh.local_nodes_begin();
const MeshBase::node_iterator node_end = mesh.local_nodes_end();
for (; node_it != node_end; ++node_it)
{
Node *node = *node_it;
libmesh_assert(node);
for (unsigned vg=0; vg<n_var_groups; vg++)
{
const VariableGroup &vg_description(this->variable_group(vg));
if (node->n_comp_group(sys_num,vg))
if (node->vg_dof_base(sys_num,vg) == DofObject::invalid_id)
{
node->set_vg_dof_base (sys_num,
vg,
next_free_dof);
next_free_dof += (vg_description.n_variables()*
node->n_comp(sys_num,vg));
}
}
}
}
// Finally, count up the SCALAR dofs
this->_n_SCALAR_dofs = 0;
for (unsigned vg=0; vg<n_var_groups; vg++)
{
const VariableGroup &vg_description(this->variable_group(vg));
if( vg_description.type().family == SCALAR )
{
this->_n_SCALAR_dofs += (vg_description.n_variables()*
vg_description.type().order);
continue;
}
}
// Only increment next_free_dof if we're on the processor
// that holds this SCALAR variable
if ( this->processor_id() == (this->n_processors()-1) )
next_free_dof += _n_SCALAR_dofs;
#ifdef DEBUG
{
// libMesh::out << "next_free_dof=" << next_free_dof << std::endl
// << "_n_SCALAR_dofs=" << _n_SCALAR_dofs << std::endl;
// Make sure we didn't miss any nodes
MeshTools::libmesh_assert_valid_procids<Node>(mesh);
MeshBase::node_iterator node_it = mesh.local_nodes_begin();
const MeshBase::node_iterator node_end = mesh.local_nodes_end();
for (; node_it != node_end; ++node_it)
{
Node *obj = *node_it;
libmesh_assert(obj);
unsigned int n_var_g = obj->n_var_groups(this->sys_number());
for (unsigned int vg=0; vg != n_var_g; ++vg)
{
unsigned int n_comp_g =
obj->n_comp_group(this->sys_number(), vg);
dof_id_type my_first_dof = n_comp_g ?
obj->vg_dof_base(this->sys_number(), vg) : 0;
libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
}
}
}
#endif // DEBUG
}
| 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 1255 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::libmesh_assert(), libMesh::MeshTools::libmesh_assert_valid_procids< Node >(), libMesh::MeshBase::local_nodes_begin(), libMesh::MeshBase::local_nodes_end(), mesh, libMesh::DofObject::n_comp_group(), n_nodes, libMesh::Elem::n_nodes(), libMesh::ParallelObject::n_processors(), libMesh::DofObject::n_var_groups(), n_variable_groups(), libMesh::VariableGroup::n_variables(), libMesh::FEType::order, libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), libMesh::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().
{
const unsigned int sys_num = this->sys_number();
const unsigned int n_var_groups = this->n_variable_groups();
//-------------------------------------------------------------------------
// First count and assign temporary numbers to local dofs
for (unsigned vg=0; vg<n_var_groups; vg++)
{
const VariableGroup &vg_description(this->variable_group(vg));
const unsigned int n_vars_in_group = vg_description.n_variables();
// Skip the SCALAR dofs
if (vg_description.type().family == SCALAR)
continue;
MeshBase::element_iterator elem_it = mesh.active_local_elements_begin();
const MeshBase::element_iterator elem_end = mesh.active_local_elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
// Only number dofs connected to active
// elements on this processor.
Elem* elem = *elem_it;
// ... and only variables which are active on
// on this element's subdomain
if (!vg_description.active_on_subdomain(elem->subdomain_id()))
continue;
const unsigned int n_nodes = elem->n_nodes();
// First number the nodal DOFS
for (unsigned int n=0; n<n_nodes; n++)
{
Node* node = elem->get_node(n);
// assign dof numbers (all at once) if this is
// our node and if they aren't already there
if ((node->n_comp_group(sys_num,vg) > 0) &&
(node->processor_id() == this->processor_id()) &&
(node->vg_dof_base(sys_num,vg) ==
DofObject::invalid_id))
{
node->set_vg_dof_base(sys_num,
vg,
next_free_dof);
next_free_dof += (n_vars_in_group*
node->n_comp_group(sys_num,vg));
}
}
// Now number the element DOFS
if (elem->n_comp_group(sys_num,vg) > 0)
{
libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg),
DofObject::invalid_id);
elem->set_vg_dof_base(sys_num,
vg,
next_free_dof);
next_free_dof += (n_vars_in_group*
elem->n_comp_group(sys_num,vg));
}
} // end loop on elements
// we may have missed assigning DOFs to nodes that we own
// but to which we have no connected elements matching our
// variable restriction criterion. this will happen, for example,
// if variable V is restricted to subdomain S. We may not own
// any elements which live in S, but we may own nodes which are
// *connected* to elements which do. in this scenario these nodes
// will presently have unnumbered DOFs. we need to take care of
// them here since we own them and no other processor will touch them.
{
MeshBase::node_iterator node_it = mesh.local_nodes_begin();
const MeshBase::node_iterator node_end = mesh.local_nodes_end();
for (; node_it != node_end; ++node_it)
{
Node *node = *node_it;
libmesh_assert(node);
if (node->n_comp_group(sys_num,vg))
if (node->vg_dof_base(sys_num,vg) == DofObject::invalid_id)
{
node->set_vg_dof_base (sys_num,
vg,
next_free_dof);
next_free_dof += (n_vars_in_group*
node->n_comp_group(sys_num,vg));
}
}
}
} // end loop on variable groups
// Finally, count up the SCALAR dofs
this->_n_SCALAR_dofs = 0;
for (unsigned vg=0; vg<n_var_groups; vg++)
{
const VariableGroup &vg_description(this->variable_group(vg));
if( vg_description.type().family == SCALAR )
{
this->_n_SCALAR_dofs += (vg_description.n_variables()*
vg_description.type().order);
continue;
}
}
// Only increment next_free_dof if we're on the processor
// that holds this SCALAR variable
if ( this->processor_id() == (this->n_processors()-1) )
next_free_dof += _n_SCALAR_dofs;
#ifdef DEBUG
{
// Make sure we didn't miss any nodes
MeshTools::libmesh_assert_valid_procids<Node>(mesh);
MeshBase::node_iterator node_it = mesh.local_nodes_begin();
const MeshBase::node_iterator node_end = mesh.local_nodes_end();
for (; node_it != node_end; ++node_it)
{
Node *obj = *node_it;
libmesh_assert(obj);
unsigned int n_var_g = obj->n_var_groups(this->sys_number());
for (unsigned int vg=0; vg != n_var_g; ++vg)
{
unsigned int n_comp_g =
obj->n_comp_group(this->sys_number(), vg);
dof_id_type my_first_dof = n_comp_g ?
obj->vg_dof_base(this->sys_number(), vg) : 0;
libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
}
}
}
#endif // DEBUG
}
| void libMesh::DofMap::dof_indices | ( | const Elem *const | elem, |
| std::vector< dof_id_type > & | di | ||
| ) | const |
Fills the vector di with the global degree of freedom indices for the element.
Definition at line 1805 of file dof_map.C.
References _dof_indices(), libMesh::Elem::active(), libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::MeshTools::Subdivision::find_one_ring(), libMesh::Elem::get_nodes(), libMesh::Tri3Subdivision::is_ghost(), libMesh::libmesh_assert(), libMesh::Elem::n_nodes(), n_variables(), n_vars, libMesh::FEType::order, libMesh::SCALAR, SCALAR_dof_indices(), libMesh::START_LOG(), libMesh::Elem::subdomain_id(), libMesh::TRI3SUBDIVISION, libMesh::Variable::type(), libMesh::Elem::type(), and variable().
Referenced by libMesh::ExactSolution::_compute_error(), libMesh::UniformRefinementEstimator::_estimate_error(), add_neighbors_to_send_list(), libMesh::HPCoarsenTest::add_projection(), 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::AdjointRefinementEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::EquationSystems::get_solution(), libMesh::MeshFunction::gradient(), libMesh::MeshFunction::hessian(), libMesh::SystemSubsetBySubdomain::init(), libMesh::System::local_dof_indices(), libMesh::DGFEMContext::neighbor_side_fe_reinit(), libMesh::WeightedPatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::SparsityPattern::Build::operator()(), libMesh::PatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::ProjectSolution::operator()(), libMesh::MeshFunction::operator()(), libMesh::BoundaryProjectSolution::operator()(), libMesh::ErrorVector::plot_error(), libMesh::FEMContext::pre_fe_reinit(), libMesh::HPCoarsenTest::select_refinement(), libMesh::EnsightIO::write_scalar_ascii(), and libMesh::EnsightIO::write_vector_ascii().
{
// We now allow elem==NULL to request just SCALAR dofs
// libmesh_assert(elem);
// If we are asking for current indices on an element, it ought to
// be an active element (or a Side proxy, which also thinks it's
// active)
libmesh_assert(!elem || elem->active());
START_LOG("dof_indices()", "DofMap");
// Clear the DOF indices vector
di.clear();
const unsigned int n_vars = this->n_variables();
#ifdef DEBUG
// Check that sizes match in DEBUG mode
std::size_t tot_size = 0;
#endif
if (elem && elem->type() == TRI3SUBDIVISION)
{
// Subdivision surface FE require the 1-ring around elem
const Tri3Subdivision* sd_elem = static_cast<const Tri3Subdivision*>(elem);
// Ghost subdivision elements have no real dofs
if (!sd_elem->is_ghost())
{
// Determine the nodes contributing to element elem
std::vector<Node*> elem_nodes;
MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
// Get the dof numbers
for (unsigned int v=0; v<n_vars; v++)
{
if(this->variable(v).type().family == SCALAR &&
this->variable(v).active_on_subdomain(elem->subdomain_id()))
{
#ifdef DEBUG
tot_size += this->variable(v).type().order;
#endif
std::vector<dof_id_type> di_new;
this->SCALAR_dof_indices(di_new,v);
di.insert( di.end(), di_new.begin(), di_new.end());
}
else
_dof_indices(elem, di, v, &elem_nodes[0], elem_nodes.size()
#ifdef DEBUG
, tot_size
#endif
);
}
}
STOP_LOG("dof_indices()", "DofMap");
return;
}
// Get the dof numbers
for (unsigned int v=0; v<n_vars; v++)
{
const Variable & var = this->variable(v);
if(var.type().family == SCALAR &&
(!elem ||
var.active_on_subdomain(elem->subdomain_id())))
{
#ifdef DEBUG
tot_size += var.type().order;
#endif
std::vector<dof_id_type> di_new;
this->SCALAR_dof_indices(di_new,v);
di.insert( di.end(), di_new.begin(), di_new.end());
}
else if (elem)
_dof_indices(elem, di, v, elem->get_nodes(), elem->n_nodes()
#ifdef DEBUG
, tot_size
#endif
);
}
#ifdef DEBUG
libmesh_assert_equal_to (tot_size, di.size());
#endif
STOP_LOG("dof_indices()", "DofMap");
}
| void libMesh::DofMap::dof_indices | ( | const Elem *const | elem, |
| std::vector< dof_id_type > & | di, | ||
| const unsigned int | vn | ||
| ) | const |
Fills the vector di with the global degree of freedom indices for the element. For one variable
Definition at line 1897 of file dof_map.C.
References _dof_indices(), libMesh::Variable::active_on_subdomain(), libMesh::FEType::family, libMesh::MeshTools::Subdivision::find_one_ring(), libMesh::Elem::get_nodes(), libMesh::Tri3Subdivision::is_ghost(), libMesh::Elem::n_nodes(), libMesh::FEType::order, libMesh::SCALAR, SCALAR_dof_indices(), libMesh::START_LOG(), libMesh::Elem::subdomain_id(), libMesh::TRI3SUBDIVISION, libMesh::Variable::type(), libMesh::Elem::type(), and variable().
{
// We now allow elem==NULL to request just SCALAR dofs
// libmesh_assert(elem);
START_LOG("dof_indices()", "DofMap");
// Clear the DOF indices vector
di.clear();
#ifdef DEBUG
// Check that sizes match in DEBUG mode
std::size_t tot_size = 0;
#endif
if (elem && elem->type() == TRI3SUBDIVISION)
{
// Subdivision surface FE require the 1-ring around elem
const Tri3Subdivision* sd_elem = static_cast<const Tri3Subdivision*>(elem);
// Ghost subdivision elements have no real dofs
if (!sd_elem->is_ghost())
{
// Determine the nodes contributing to element elem
std::vector<Node*> elem_nodes;
MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
_dof_indices(elem, di, vn, &elem_nodes[0], elem_nodes.size()
#ifdef DEBUG
, tot_size
#endif
);
}
STOP_LOG("dof_indices()", "DofMap");
return;
}
const Variable & var = this->variable(vn);
// Get the dof numbers
if(var.type().family == SCALAR &&
(!elem ||
var.active_on_subdomain(elem->subdomain_id())))
{
#ifdef DEBUG
tot_size += var.type().order;
#endif
std::vector<dof_id_type> di_new;
this->SCALAR_dof_indices(di_new,vn);
di.insert( di.end(), di_new.begin(), di_new.end());
}
else if (elem)
_dof_indices(elem, di, vn, elem->get_nodes(), elem->n_nodes()
#ifdef DEBUG
, tot_size
#endif
);
#ifdef DEBUG
libmesh_assert_equal_to (tot_size, di.size());
#endif
STOP_LOG("dof_indices()", "DofMap");
}
| 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 281 of file dof_map.C.
References libMesh::MeshBase::elem().
Referenced by distribute_dofs().
{
return mesh.elem(i);
}
| 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.
{
_enable_print_counter = true;
return;
}
| dof_id_type libMesh::DofMap::end_dof | ( | const processor_id_type | proc | ) | const [inline] |
Returns the first dof index that is after all indices local to processor proc. Analogous to the end() member function of STL containers.
Definition at line 489 of file dof_map.h.
References _end_df.
Referenced by DMCreateDomainDecomposition_libMesh(), DMCreateFieldDecomposition_libMesh(), libMesh::SystemSubsetBySubdomain::init(), libMesh::CondensedEigenSystem::initialize_condensed_dofs(), libMesh::System::local_dof_indices(), and libMesh::SparsityPattern::Build::operator()().
| dof_id_type libMesh::DofMap::end_dof | ( | ) | const [inline] |
Definition at line 492 of file dof_map.h.
References end_dof(), and libMesh::ParallelObject::processor_id().
Referenced by add_neighbors_to_send_list(), all_semilocal_indices(), distribute_dofs(), end_dof(), and local_variable_indices().
{ return this->end_dof(this->processor_id()); }
| dof_id_type libMesh::DofMap::end_old_dof | ( | const processor_id_type | proc | ) | const [inline] |
Returns the first old dof index that is after all indices local to processor proc. Analogous to the end() member function of STL containers.
Definition at line 501 of file dof_map.h.
References _end_old_df.
{ libmesh_assert_less (proc, _end_old_df.size()); return _end_old_df[proc]; }
| dof_id_type libMesh::DofMap::end_old_dof | ( | ) | const [inline] |
Definition at line 504 of file dof_map.h.
References end_old_dof(), and libMesh::ParallelObject::processor_id().
Referenced by end_old_dof().
{ return this->end_old_dof(this->processor_id()); }
| void libMesh::DofMap::enforce_adjoint_constraints_exactly | ( | NumericVector< Number > & | v, |
| unsigned int | q | ||
| ) | const [inline] |
Heterogenously constrains the numeric vector v, which represents an adjoint solution defined on the mesh for quantity fo interest q. For homogeneous constraints, use enforce_constraints_exactly instead
Definition at line 2005 of file dof_map_constraints.C.
References libMesh::NumericVector< T >::close(), libMesh::NumericVector< T >::closed(), libMesh::NumericVector< T >::get(), libMesh::GHOSTED, libMesh::libmesh_assert(), libMesh::NumericVector< T >::localize(), libMesh::PARALLEL, libMesh::SERIAL, libMesh::NumericVector< T >::set(), libMesh::NumericVector< T >::size(), libMesh::START_LOG(), and libMesh::NumericVector< T >::type().
Referenced by libMesh::ImplicitSystem::adjoint_solve(), and libMesh::System::project_vector().
{
parallel_object_only();
if (!this->n_constrained_dofs())
return;
START_LOG("enforce_adjoint_constraints_exactly()","DofMap");
NumericVector<Number> *v_local = NULL; // will be initialized below
NumericVector<Number> *v_global = NULL; // will be initialized below
UniquePtr<NumericVector<Number> > v_built;
if (v.type() == SERIAL)
{
v_built = NumericVector<Number>::build(this->comm());
v_built->init(this->n_dofs(), this->n_local_dofs(), true, PARALLEL);
v_built->close();
for (dof_id_type i=v_built->first_local_index();
i<v_built->last_local_index(); i++)
v_built->set(i, v(i));
v_built->close();
v_global = v_built.get();
v_local = &v;
libmesh_assert (v_local->closed());
}
else if (v.type() == PARALLEL)
{
v_built = NumericVector<Number>::build(this->comm());
v_built->init (v.size(), v.size(), true, SERIAL);
v.localize(*v_built);
v_built->close();
v_local = v_built.get();
v_global = &v;
}
else if (v.type() == GHOSTED)
{
v_local = &v;
v_global = &v;
}
else // unknown v.type()
libmesh_error_msg("ERROR: Unknown v.type() == " << v.type());
// We should never hit these asserts because we should error-out in
// else clause above. Just to be sure we don't try to use v_local
// and v_global uninitialized...
libmesh_assert(v_local);
libmesh_assert(v_global);
// Do we have any non_homogeneous constraints?
const AdjointDofConstraintValues::const_iterator
adjoint_constraint_map_it = _adjoint_constraint_values.find(q);
const DofConstraintValueMap *constraint_map =
(adjoint_constraint_map_it == _adjoint_constraint_values.end()) ?
NULL : &adjoint_constraint_map_it->second;
DofConstraints::const_iterator c_it = _dof_constraints.begin();
const DofConstraints::const_iterator c_end = _dof_constraints.end();
for ( ; c_it != c_end; ++c_it)
{
dof_id_type constrained_dof = c_it->first;
if (constrained_dof < this->first_dof() ||
constrained_dof >= this->end_dof())
continue;
const DofConstraintRow constraint_row = c_it->second;
Number exact_value = 0;
if (constraint_map)
{
const DofConstraintValueMap::const_iterator
adjoint_constraint_it =
constraint_map->find(constrained_dof);
if (adjoint_constraint_it != constraint_map->end())
exact_value = adjoint_constraint_it->second;
}
for (DofConstraintRow::const_iterator
j=constraint_row.begin(); j != constraint_row.end();
++j)
exact_value += j->second * (*v_local)(j->first);
v_global->set(constrained_dof, exact_value);
}
// If the old vector was serial, we probably need to send our values
// to other processors
if (v.type() == SERIAL)
{
#ifndef NDEBUG
v_global->close();
#endif
v_global->localize (v);
}
v.close();
STOP_LOG("enforce_adjoint_constraints_exactly()","DofMap");
}
| 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 1903 of file dof_map_constraints.C.
References libMesh::NumericVector< T >::close(), libMesh::NumericVector< T >::closed(), libMesh::NumericVector< T >::get(), libMesh::System::get_dof_map(), libMesh::GHOSTED, libMesh::libmesh_assert(), libMesh::NumericVector< T >::localize(), libMesh::PARALLEL, libMesh::SERIAL, libMesh::NumericVector< T >::set(), libMesh::NumericVector< T >::size(), libMesh::System::solution, libMesh::START_LOG(), and libMesh::NumericVector< T >::type().
Referenced by libMesh::__libmesh_petsc_diff_solver_residual(), libMesh::__libmesh_petsc_snes_residual(), libMesh::Problem_Interface::computeF(), libMesh::Problem_Interface::computeJacobian(), libMesh::Problem_Interface::computePreconditioner(), DMlibMeshFunction(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::System::project_vector(), libMesh::ImplicitSystem::sensitivity_solve(), libMesh::NewtonSolver::solve(), libMesh::ImplicitSystem::weighted_sensitivity_adjoint_solve(), and libMesh::ImplicitSystem::weighted_sensitivity_solve().
{
parallel_object_only();
if (!this->n_constrained_dofs())
return;
START_LOG("enforce_constraints_exactly()","DofMap");
if (!v)
v = system.solution.get();
NumericVector<Number> *v_local = NULL; // will be initialized below
NumericVector<Number> *v_global = NULL; // will be initialized below
UniquePtr<NumericVector<Number> > v_built;
if (v->type() == SERIAL)
{
v_built = NumericVector<Number>::build(this->comm());
v_built->init(this->n_dofs(), this->n_local_dofs(), true, PARALLEL);
v_built->close();
for (dof_id_type i=v_built->first_local_index();
i<v_built->last_local_index(); i++)
v_built->set(i, (*v)(i));
v_built->close();
v_global = v_built.get();
v_local = v;
libmesh_assert (v_local->closed());
}
else if (v->type() == PARALLEL)
{
v_built = NumericVector<Number>::build(this->comm());
v_built->init (v->size(), v->size(), true, SERIAL);
v->localize(*v_built);
v_built->close();
v_local = v_built.get();
v_global = v;
}
else if (v->type() == GHOSTED)
{
v_local = v;
v_global = v;
}
else // unknown v->type()
libmesh_error_msg("ERROR: Unknown v->type() == " << v->type());
// We should never hit these asserts because we should error-out in
// else clause above. Just to be sure we don't try to use v_local
// and v_global uninitialized...
libmesh_assert(v_local);
libmesh_assert(v_global);
libmesh_assert_equal_to (this, &(system.get_dof_map()));
DofConstraints::const_iterator c_it = _dof_constraints.begin();
const DofConstraints::const_iterator c_end = _dof_constraints.end();
for ( ; c_it != c_end; ++c_it)
{
dof_id_type constrained_dof = c_it->first;
if (constrained_dof < this->first_dof() ||
constrained_dof >= this->end_dof())
continue;
const DofConstraintRow constraint_row = c_it->second;
Number exact_value = 0;
if (!homogeneous)
{
DofConstraintValueMap::const_iterator rhsit =
_primal_constraint_values.find(constrained_dof);
if (rhsit != _primal_constraint_values.end())
exact_value = rhsit->second;
}
for (DofConstraintRow::const_iterator
j=constraint_row.begin(); j != constraint_row.end();
++j)
exact_value += j->second * (*v_local)(j->first);
v_global->set(constrained_dof, exact_value);
}
// If the old vector was serial, we probably need to send our values
// to other processors
if (v->type() == SERIAL)
{
#ifndef NDEBUG
v_global->close();
#endif
v_global->localize (*v);
}
v->close();
STOP_LOG("enforce_constraints_exactly()","DofMap");
}
| void libMesh::DofMap::extract_local_vector | ( | const NumericVector< Number > & | Ug, |
| const std::vector< dof_id_type > & | dof_indices, | ||
| DenseVectorBase< Number > & | Ue | ||
| ) | const |
Builds the local element vector Ue from the global vector Ug, accounting for any constrained degrees of freedom. For an element without constrained degrees of freedom this is the trivial mapping ![$ Ue[i] = Ug[dof_indices[i]] $](form_30.png)
Note that the user must ensure that the element vector Ue is properly sized when calling this method. This is because there is no resize() method in the DenseVectorBase<> class.
Definition at line 1719 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::libmesh_assert(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVectorBase< T >::size(), libMesh::NumericVector< T >::size(), and libMesh::DenseVectorBase< T >::zero().
{
#ifdef LIBMESH_ENABLE_AMR
// Trivial mapping
libmesh_assert_equal_to (dof_indices_in.size(), Ue.size());
bool has_constrained_dofs = false;
for (unsigned int il=0;
il != cast_int<unsigned int>(dof_indices_in.size()); il++)
{
const dof_id_type ig = dof_indices_in[il];
if (this->is_constrained_dof (ig)) has_constrained_dofs = true;
libmesh_assert_less (ig, Ug.size());
Ue.el(il) = Ug(ig);
}
// If the element has any constrained DOFs then we need
// to account for them in the mapping. This will handle
// the case that the input vector is not constrained.
if (has_constrained_dofs)
{
// Copy the input DOF indices.
std::vector<dof_id_type> constrained_dof_indices(dof_indices_in);
DenseMatrix<Number> C;
DenseVector<Number> H;
this->build_constraint_matrix_and_vector (C, H, constrained_dof_indices);
libmesh_assert_equal_to (dof_indices_in.size(), C.m());
libmesh_assert_equal_to (constrained_dof_indices.size(), C.n());
// zero-out Ue
Ue.zero();
// compute Ue = C Ug, with proper mapping.
const unsigned int n_original_dofs =
cast_int<unsigned int>(dof_indices_in.size());
for (unsigned int i=0; i != n_original_dofs; i++)
{
Ue.el(i) = H(i);
const unsigned int n_constrained =
cast_int<unsigned int>(constrained_dof_indices.size());
for (unsigned int j=0; j<n_constrained; j++)
{
const dof_id_type jg = constrained_dof_indices[j];
// If Ug is a serial or ghosted vector, then this assert is
// overzealous. If Ug is a parallel vector, then this assert
// is redundant.
// libmesh_assert ((jg >= Ug.first_local_index()) &&
// (jg < Ug.last_local_index()));
Ue.el(i) += C(i,j)*Ug(jg);
}
}
}
#else
// Trivial mapping
const unsigned int n_original_dofs =
cast_int<unsigned int>(dof_indices_in.size());
libmesh_assert_equal_to (n_original_dofs, Ue.size());
for (unsigned int il=0; il<n_original_dofs; il++)
{
const dof_id_type ig = dof_indices_in[il];
libmesh_assert ((ig >= Ug.first_local_index()) && (ig < Ug.last_local_index()));
Ue.el(il) = Ug(ig);
}
#endif
}
| 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 2380 of file dof_map.C.
References _dof_constraints, is_constrained_dof(), and libMesh::libmesh_assert().
Referenced by libMesh::SparsityPattern::Build::operator()().
{
typedef std::set<dof_id_type> RCSet;
// First insert the DOFS we already depend on into the set.
RCSet dof_set (elem_dofs.begin(), elem_dofs.end());
bool done = true;
// Next insert any dofs those might be constrained in terms
// of. Note that in this case we may not be done: Those may
// in turn depend on others. So, we need to repeat this process
// in that case until the system depends only on unconstrained
// degrees of freedom.
for (unsigned int i=0; i<elem_dofs.size(); i++)
if (this->is_constrained_dof(elem_dofs[i]))
{
// If the DOF is constrained
DofConstraints::const_iterator
pos = _dof_constraints.find(elem_dofs[i]);
libmesh_assert (pos != _dof_constraints.end());
const DofConstraintRow& constraint_row = pos->second;
// adaptive p refinement currently gives us lots of empty constraint
// rows - we should optimize those DoFs away in the future. [RHS]
//libmesh_assert (!constraint_row.empty());
DofConstraintRow::const_iterator it = constraint_row.begin();
DofConstraintRow::const_iterator it_end = constraint_row.end();
// Add the DOFs this dof is constrained in terms of.
// note that these dofs might also be constrained, so
// we will need to call this function recursively.
for ( ; it != it_end; ++it)
if (!dof_set.count (it->first))
{
dof_set.insert (it->first);
done = false;
}
}
// If not done then we need to do more work
// (obviously :-) )!
if (!done)
{
// Fill the vector with the contents of the set
elem_dofs.clear();
elem_dofs.insert (elem_dofs.end(),
dof_set.begin(), dof_set.end());
// May need to do this recursively. It is possible
// that we just replaced a constrained DOF with another
// constrained DOF.
this->find_connected_dofs (elem_dofs);
} // end if (!done)
}
| dof_id_type libMesh::DofMap::first_dof | ( | const processor_id_type | proc | ) | const [inline] |
Returns the first dof index that is local to partition proc.
Definition at line 452 of file dof_map.h.
References _first_df.
Referenced by DMCreateDomainDecomposition_libMesh(), DMCreateFieldDecomposition_libMesh(), libMesh::SystemSubsetBySubdomain::init(), libMesh::System::local_dof_indices(), and libMesh::SparsityPattern::Build::operator()().
| dof_id_type libMesh::DofMap::first_dof | ( | ) | const [inline] |
Definition at line 455 of file dof_map.h.
References first_dof(), and libMesh::ParallelObject::processor_id().
Referenced by add_neighbors_to_send_list(), all_semilocal_indices(), distribute_dofs(), first_dof(), and local_variable_indices().
{ return this->first_dof(this->processor_id()); }
| dof_id_type libMesh::DofMap::first_old_dof | ( | const processor_id_type | proc | ) | const [inline] |
Returns the first old dof index that is local to partition proc.
Definition at line 462 of file dof_map.h.
References _first_old_df.
{ libmesh_assert_less (proc, _first_old_df.size()); return _first_old_df[proc]; }
| dof_id_type libMesh::DofMap::first_old_dof | ( | ) | const [inline] |
Definition at line 465 of file dof_map.h.
References first_old_dof(), and libMesh::ParallelObject::processor_id().
Referenced by first_old_dof().
{ return this->first_old_dof(this->processor_id()); }
| const DirichletBoundaries * libMesh::DofMap::get_adjoint_dirichlet_boundaries | ( | unsigned int | q | ) | const |
Definition at line 3811 of file dof_map_constraints.C.
{
libmesh_assert_greater(_adjoint_dirichlet_boundaries.size(),q);
return _adjoint_dirichlet_boundaries[q];
}
| DirichletBoundaries * libMesh::DofMap::get_adjoint_dirichlet_boundaries | ( | unsigned int | q | ) |
Definition at line 3819 of file dof_map_constraints.C.
{
unsigned int old_size = cast_int<unsigned int>
(_adjoint_dirichlet_boundaries.size());
for (unsigned int i = old_size; i <= q; ++i)
_adjoint_dirichlet_boundaries.push_back(new DirichletBoundaries());
return _adjoint_dirichlet_boundaries[q];
}
| const DirichletBoundaries* libMesh::DofMap::get_dirichlet_boundaries | ( | ) | const [inline] |
Definition at line 991 of file dof_map.h.
References _dirichlet_boundaries.
{
return _dirichlet_boundaries;
}
| DirichletBoundaries* libMesh::DofMap::get_dirichlet_boundaries | ( | ) | [inline] |
Definition at line 996 of file dof_map.h.
References _dirichlet_boundaries.
{
return _dirichlet_boundaries;
}
| 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().
{
#if defined(LIBMESH_ENABLE_REFERENCE_COUNTING) && defined(DEBUG)
std::ostringstream oss;
oss << '\n'
<< " ---------------------------------------------------------------------------- \n"
<< "| Reference count information |\n"
<< " ---------------------------------------------------------------------------- \n";
for (Counts::iterator it = _counts.begin();
it != _counts.end(); ++it)
{
const std::string name(it->first);
const unsigned int creations = it->second.first;
const unsigned int destructions = it->second.second;
oss << "| " << name << " reference count information:\n"
<< "| Creations: " << creations << '\n'
<< "| Destructions: " << destructions << '\n';
}
oss << " ---------------------------------------------------------------------------- \n";
return oss.str();
#else
return "";
#endif
}
| std::string libMesh::DofMap::get_info | ( | ) | const |
Gets summary info about the sparsity bandwidth and constraints.
Definition at line 3084 of file dof_map.C.
References end, libMesh::libmesh_assert(), std::max(), libMesh::processor_id(), libMesh::DofObject::processor_id(), and libMesh::TypeVector< T >::size().
Referenced by libMesh::System::get_info().
{
std::ostringstream os;
// If we didn't calculate the exact sparsity pattern, the threaded
// sparsity pattern assembly may have just given us an upper bound
// on sparsity.
const char* may_equal = " <= ";
// If we calculated the exact sparsity pattern, then we can report
// exact bandwidth figures:
std::vector<SparseMatrix<Number>* >::const_iterator
pos = _matrices.begin(),
end = _matrices.end();
for (; pos != end; ++pos)
if ((*pos)->need_full_sparsity_pattern())
may_equal = " = ";
dof_id_type max_n_nz = 0, max_n_oz = 0;
long double avg_n_nz = 0, avg_n_oz = 0;
if (_n_nz)
{
for (std::size_t i = 0; i != _n_nz->size(); ++i)
{
max_n_nz = std::max(max_n_nz, (*_n_nz)[i]);
avg_n_nz += (*_n_nz)[i];
}
std::size_t n_nz_size = _n_nz->size();
this->comm().max(max_n_nz);
this->comm().sum(avg_n_nz);
this->comm().sum(n_nz_size);
avg_n_nz /= std::max(n_nz_size,std::size_t(1));
libmesh_assert(_n_oz);
for (std::size_t i = 0; i != (*_n_oz).size(); ++i)
{
max_n_oz = std::max(max_n_oz, (*_n_oz)[i]);
avg_n_oz += (*_n_oz)[i];
}
std::size_t n_oz_size = _n_oz->size();
this->comm().max(max_n_oz);
this->comm().sum(avg_n_oz);
this->comm().sum(n_oz_size);
avg_n_oz /= std::max(n_oz_size,std::size_t(1));
}
os << " DofMap Sparsity\n Average On-Processor Bandwidth"
<< may_equal << avg_n_nz << '\n';
os << " Average Off-Processor Bandwidth"
<< may_equal << avg_n_oz << '\n';
os << " Maximum On-Processor Bandwidth"
<< may_equal << max_n_nz << '\n';
os << " Maximum Off-Processor Bandwidth"
<< may_equal << max_n_oz << std::endl;
#ifdef LIBMESH_ENABLE_CONSTRAINTS
std::size_t n_constraints = 0, max_constraint_length = 0,
n_rhss = 0;
long double avg_constraint_length = 0.;
for (DofConstraints::const_iterator it=_dof_constraints.begin();
it != _dof_constraints.end(); ++it)
{
// Only count local constraints, then sum later
const dof_id_type constrained_dof = it->first;
if (constrained_dof < this->first_dof() ||
constrained_dof >= this->end_dof())
continue;
const DofConstraintRow& row = it->second;
std::size_t rowsize = row.size();
max_constraint_length = std::max(max_constraint_length,
rowsize);
avg_constraint_length += rowsize;
n_constraints++;
if (_primal_constraint_values.count(constrained_dof))
n_rhss++;
}
this->comm().sum(n_constraints);
this->comm().sum(n_rhss);
this->comm().sum(avg_constraint_length);
this->comm().max(max_constraint_length);
os << " DofMap Constraints\n Number of DoF Constraints = "
<< n_constraints;
if (n_rhss)
os << '\n'
<< " Number of Heterogenous Constraints= " << n_rhss;
if (n_constraints)
{
avg_constraint_length /= n_constraints;
os << '\n'
<< " Average DoF Constraint Length= " << avg_constraint_length;
}
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
std::size_t n_node_constraints = 0, max_node_constraint_length = 0,
n_node_rhss = 0;
long double avg_node_constraint_length = 0.;
for (NodeConstraints::const_iterator it=_node_constraints.begin();
it != _node_constraints.end(); ++it)
{
// Only count local constraints, then sum later
const Node *node = it->first;
if (node->processor_id() != this->processor_id())
continue;
const NodeConstraintRow& row = it->second.first;
std::size_t rowsize = row.size();
max_node_constraint_length = std::max(max_node_constraint_length,
rowsize);
avg_node_constraint_length += rowsize;
n_node_constraints++;
if (it->second.second != Point(0))
n_node_rhss++;
}
this->comm().sum(n_node_constraints);
this->comm().sum(n_node_rhss);
this->comm().sum(avg_node_constraint_length);
this->comm().max(max_node_constraint_length);
os << "\n Number of Node Constraints = " << n_node_constraints;
if (n_node_rhss)
os << '\n'
<< " Number of Heterogenous Node Constraints= " << n_node_rhss;
if (n_node_constraints)
{
avg_node_constraint_length /= n_node_constraints;
os << "\n Maximum Node Constraint Length= " << max_node_constraint_length
<< '\n'
<< " Average Node Constraint Length= " << avg_node_constraint_length;
}
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
os << std::endl;
#endif // LIBMESH_ENABLE_CONSTRAINTS
return os.str();
}
| 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 1258 of file dof_map_constraints.C.
References libMesh::DofObject::id(), libMesh::processor_id(), and libMesh::DofObject::processor_id().
{
std::ostringstream os;
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
if (print_nonlocal)
os << "All ";
else
os << "Local ";
os << "Node Constraints:"
<< std::endl;
for (NodeConstraints::const_iterator it=_node_constraints.begin();
it != _node_constraints.end(); ++it)
{
const Node *node = it->first;
// Skip non-local nodes if requested
if (!print_nonlocal &&
node->processor_id() != this->processor_id())
continue;
const NodeConstraintRow& row = it->second.first;
const Point& offset = it->second.second;
os << "Constraints for Node id " << node->id()
<< ": \t";
for (NodeConstraintRow::const_iterator pos=row.begin();
pos != row.end(); ++pos)
os << " (" << pos->first->id() << ","
<< pos->second << ")\t";
os << "rhs: " << offset;
os << std::endl;
}
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
if (print_nonlocal)
os << "All ";
else
os << "Local ";
os << "DoF Constraints:"
<< std::endl;
for (DofConstraints::const_iterator it=_dof_constraints.begin();
it != _dof_constraints.end(); ++it)
{
const dof_id_type i = it->first;
// Skip non-local dofs if requested
if (!print_nonlocal &&
((i < this->first_dof()) ||
(i >= this->end_dof())))
continue;
const DofConstraintRow& row = it->second;
DofConstraintValueMap::const_iterator rhsit =
_primal_constraint_values.find(i);
const Number rhs = (rhsit == _primal_constraint_values.end()) ?
0 : rhsit->second;
os << "Constraints for DoF " << i
<< ": \t";
for (DofConstraintRow::const_iterator pos=row.begin();
pos != row.end(); ++pos)
os << " (" << pos->first << ","
<< pos->second << ")\t";
os << "rhs: " << rhs;
os << std::endl;
}
for (unsigned int qoi_index = 0;
qoi_index != _adjoint_dirichlet_boundaries.size();
++qoi_index)
{
os << "Adjoint " << qoi_index << " DoF rhs values:"
<< std::endl;
AdjointDofConstraintValues::const_iterator adjoint_map_it =
_adjoint_constraint_values.find(qoi_index);
if (adjoint_map_it != _adjoint_constraint_values.end())
for (DofConstraintValueMap::const_iterator
it=adjoint_map_it->second.begin();
it != adjoint_map_it->second.end(); ++it)
{
const dof_id_type i = it->first;
// Skip non-local dofs if requested
if (!print_nonlocal &&
((i < this->first_dof()) ||
(i >= this->end_dof())))
continue;
const Number rhs = it->second;
os << "RHS for DoF " << i
<< ": " << rhs;
os << std::endl;
}
}
return os.str();
}
| 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 324 of file dof_map.h.
References _n_nz, and libMesh::libmesh_assert().
{
libmesh_assert(_n_nz);
return *_n_nz;
}
| 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 335 of file dof_map.h.
References _n_oz, and libMesh::libmesh_assert().
{
libmesh_assert(_n_oz);
return *_n_oz;
}
| PeriodicBoundaries* libMesh::DofMap::get_periodic_boundaries | ( | ) | [inline] |
Definition at line 953 of file dof_map.h.
References _periodic_boundaries.
{
return _periodic_boundaries;
}
Definition at line 1562 of file dof_map.h.
References _primal_constraint_values.
{
return _primal_constraint_values;
}
| 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 316 of file dof_map.h.
References _send_list.
Referenced by libMesh::UniformRefinementEstimator::_estimate_error(), 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().
{ return _send_list; }
| bool libMesh::DofMap::has_adjoint_dirichlet_boundaries | ( | unsigned int | q | ) | const |
Definition at line 3801 of file dof_map_constraints.C.
Referenced by libMesh::AdjointRefinementEstimator::estimate_error(), and libMesh::ImplicitSystem::weighted_sensitivity_adjoint_solve().
{
if (_adjoint_dirichlet_boundaries.size() > q)
return true;
return false;
}
| bool libMesh::DofMap::has_blocked_representation | ( | ) | const [inline] |
Definition at line 403 of file dof_map.h.
References n_variable_groups(), and n_variables().
Referenced by block_size().
{
#ifdef LIBMESH_ENABLE_BLOCKED_STORAGE
return ((this->n_variable_groups() == 1) && (this->n_variables() > 1));
#else
return false;
#endif
}
| Number libMesh::DofMap::has_heterogenous_adjoint_constraint | ( | const unsigned int | qoi_num, |
| const dof_id_type | dof | ||
| ) | const [inline] |
dof has a heterogenous constraint for adjoint solution qoi_num, zero otherwise. Definition at line 1541 of file dof_map.h.
References _adjoint_constraint_values.
{
AdjointDofConstraintValues::const_iterator it =
_adjoint_constraint_values.find(qoi_num);
if (it != _adjoint_constraint_values.end())
{
DofConstraintValueMap::const_iterator rhsit =
it->second.find(dof);
if (rhsit == it->second.end())
return 0;
else
return rhsit->second;
}
return 0;
}
| bool libMesh::DofMap::has_heterogenous_adjoint_constraints | ( | const unsigned int | qoi_num | ) | const [inline] |
qoi_num, false otherwise. Definition at line 1527 of file dof_map.h.
References _adjoint_constraint_values.
{
AdjointDofConstraintValues::const_iterator it =
_adjoint_constraint_values.find(qoi_num);
if (it == _adjoint_constraint_values.end())
return false;
if (it->second.empty())
return false;
return true;
}
| void libMesh::DofMap::heterogenously_constrain_element_matrix_and_vector | ( | DenseMatrix< Number > & | matrix, |
| DenseVector< Number > & | rhs, | ||
| std::vector< dof_id_type > & | elem_dofs, | ||
| bool | asymmetric_constraint_rows = true, |
||
| int | qoi_index = -1 |
||
| ) | const |
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.
By default, the constraints for the primal solution of this system are used. If a non-negative qoi_index is passed in, then the constraints for the corresponding adjoint solution are used instead.
Definition at line 1526 of file dof_map_constraints.C.
References dof_id, libMesh::DenseMatrix< T >::left_multiply_transpose(), libMesh::libmesh_assert(), libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseMatrix< T >::right_multiply(), libMesh::DenseVector< T >::size(), libMesh::START_LOG(), libMesh::DenseMatrix< T >::vector_mult(), and libMesh::DenseMatrix< T >::vector_mult_transpose().
{
libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
// check for easy return
if (this->_dof_constraints.empty())
return;
// The constrained matrix is built up as C^T K C.
// The constrained RHS is built up as C^T (F - K H)
DenseMatrix<Number> C;
DenseVector<Number> H;
this->build_constraint_matrix_and_vector (C, H, elem_dofs, qoi_index);
START_LOG("hetero_cnstrn_elem_mat_vec()", "DofMap");
// It is possible that the matrix is not constrained at all.
if ((C.m() == matrix.m()) &&
(C.n() == elem_dofs.size())) // It the matrix is constrained
{
// We may have rhs values to use later
const DofConstraintValueMap *rhs_values = NULL;
if (qoi_index < 0)
rhs_values = &_primal_constraint_values;
else
{
const AdjointDofConstraintValues::const_iterator
it = _adjoint_constraint_values.find(qoi_index);
if (it != _adjoint_constraint_values.end())
rhs_values = &it->second;
}
// Compute matrix/vector product K H
DenseVector<Number> KH;
matrix.vector_mult(KH, H);
// Compute the matrix-vector product C^T (F - KH)
DenseVector<Number> F_minus_KH(rhs);
F_minus_KH -= KH;
C.vector_mult_transpose(rhs, F_minus_KH);
// Compute the matrix-matrix-matrix product C^T K C
matrix.left_multiply_transpose (C);
matrix.right_multiply (C);
libmesh_assert_equal_to (matrix.m(), matrix.n());
libmesh_assert_equal_to (matrix.m(), elem_dofs.size());
libmesh_assert_equal_to (matrix.n(), elem_dofs.size());
for (unsigned int i=0; i<elem_dofs.size(); i++)
{
const dof_id_type dof_id = elem_dofs[i];
if (this->is_constrained_dof(dof_id))
{
for (unsigned int j=0; j<matrix.n(); j++)
matrix(i,j) = 0.;
// If the DOF is constrained
matrix(i,i) = 1.;
// This will put a nonsymmetric entry in the constraint
// row to ensure that the linear system produces the
// correct value for the constrained DOF.
if (asymmetric_constraint_rows)
{
DofConstraints::const_iterator
pos = _dof_constraints.find(dof_id);
libmesh_assert (pos != _dof_constraints.end());
const DofConstraintRow& constraint_row = pos->second;
for (DofConstraintRow::const_iterator
it=constraint_row.begin(); it != constraint_row.end();
++it)
for (unsigned int j=0; j<elem_dofs.size(); j++)
if (elem_dofs[j] == it->first)
matrix(i,j) = -it->second;
if (rhs_values)
{
const DofConstraintValueMap::const_iterator valpos =
rhs_values->find(dof_id);
rhs(i) = (valpos == rhs_values->end()) ?
0 : valpos->second;
}
}
else
rhs(i) = 0.;
}
}
} // end if is constrained...
STOP_LOG("hetero_cnstrn_elem_mat_vec()", "DofMap");
}
| void libMesh::DofMap::heterogenously_constrain_element_vector | ( | const DenseMatrix< Number > & | matrix, |
| DenseVector< Number > & | rhs, | ||
| std::vector< dof_id_type > & | elem_dofs, | ||
| bool | asymmetric_constraint_rows = true, |
||
| int | qoi_index = -1 |
||
| ) | const |
Constrains the element vector. This method requires the element matrix to be square and not-yet-constrained, in which case the elem_dofs correspond to the global DOF indices of both the rows and columns of the element matrix.
The 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.
By default, the constraints for the primal solution of this system are used. If a non-negative qoi_index is passed in, then the constraints for the corresponding adjoint solution are used instead.
Definition at line 1635 of file dof_map_constraints.C.
References dof_id, libMesh::DenseMatrixBase< T >::m(), libMesh::DenseMatrixBase< T >::n(), libMesh::DenseVector< T >::size(), libMesh::START_LOG(), libMesh::DenseMatrix< T >::vector_mult(), and libMesh::DenseMatrix< T >::vector_mult_transpose().
{
libmesh_assert_equal_to (elem_dofs.size(), matrix.m());
libmesh_assert_equal_to (elem_dofs.size(), matrix.n());
libmesh_assert_equal_to (elem_dofs.size(), rhs.size());
// check for easy return
if (this->_dof_constraints.empty())
return;
// The constrained matrix is built up as C^T K C.
// The constrained RHS is built up as C^T (F - K H)
DenseMatrix<Number> C;
DenseVector<Number> H;
this->build_constraint_matrix_and_vector (C, H, elem_dofs, qoi_index);
START_LOG("hetero_cnstrn_elem_vec()", "DofMap");
// It is possible that the matrix is not constrained at all.
if ((C.m() == matrix.m()) &&
(C.n() == elem_dofs.size())) // It the matrix is constrained
{
// We may have rhs values to use later
const DofConstraintValueMap *rhs_values = NULL;
if (qoi_index < 0)
rhs_values = &_primal_constraint_values;
else
{
const AdjointDofConstraintValues::const_iterator
it = _adjoint_constraint_values.find(qoi_index);
if (it != _adjoint_constraint_values.end())
rhs_values = &it->second;
}
// Compute matrix/vector product K H
DenseVector<Number> KH;
matrix.vector_mult(KH, H);
// Compute the matrix-vector product C^T (F - KH)
DenseVector<Number> F_minus_KH(rhs);
F_minus_KH -= KH;
C.vector_mult_transpose(rhs, F_minus_KH);
for (unsigned int i=0; i<elem_dofs.size(); i++)
{
const dof_id_type dof_id = elem_dofs[i];
if (this->is_constrained_dof(dof_id))
{
// This will put a nonsymmetric entry in the constraint
// row to ensure that the linear system produces the
// correct value for the constrained DOF.
if (asymmetric_constraint_rows && rhs_values)
{
const DofConstraintValueMap::const_iterator valpos =
rhs_values->find(dof_id);
rhs(i) = (valpos == rhs_values->end()) ?
0 : valpos->second;
}
else
rhs(i) = 0.;
}
}
} // end if is constrained...
STOP_LOG("hetero_cnstrn_elem_vec()", "DofMap");
}
| 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, libMesh::Quality::name(), and libMesh::Threads::spin_mtx.
Referenced by libMesh::ReferenceCountedObject< RBParametrized >::ReferenceCountedObject().
{
Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
std::pair<unsigned int, unsigned int>& p = _counts[name];
p.first++;
}
| 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, libMesh::Quality::name(), and libMesh::Threads::spin_mtx.
Referenced by libMesh::ReferenceCountedObject< RBParametrized >::~ReferenceCountedObject().
{
Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
std::pair<unsigned int, unsigned int>& p = _counts[name];
p.second++;
}
| void libMesh::DofMap::invalidate_dofs | ( | MeshBase & | mesh | ) | const [private] |
Invalidates all active DofObject dofs for this system
Definition at line 788 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().
{
const unsigned int sys_num = this->sys_number();
// All the nodes
MeshBase::node_iterator node_it = mesh.nodes_begin();
const MeshBase::node_iterator node_end = mesh.nodes_end();
for ( ; node_it != node_end; ++node_it)
(*node_it)->invalidate_dofs(sys_num);
// All the elements
MeshBase::element_iterator elem_it = mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = mesh.active_elements_end();
for ( ; elem_it != elem_end; ++elem_it)
(*elem_it)->invalidate_dofs(sys_num);
}
| 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 266 of file dof_map.C.
References _matrices.
Referenced by libMesh::ImplicitSystem::init_matrices().
| bool libMesh::DofMap::is_constrained_dof | ( | const dof_id_type | dof | ) | const [inline] |
Definition at line 1517 of file dof_map.h.
References _dof_constraints.
Referenced by libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), libMesh::FEGenericBase< OutputType >::compute_proj_constraints(), extract_local_vector(), and find_connected_dofs().
{
if (_dof_constraints.count(dof))
return true;
return false;
}
| bool libMesh::DofMap::is_constrained_node | ( | const Node * | node | ) | const [inline] |
Definition at line 1500 of file dof_map.h.
References _node_constraints.
{
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
if (_node_constraints.count(node))
return true;
#endif
return false;
}
| bool libMesh::DofMap::is_periodic_boundary | ( | const boundary_id_type | boundaryid | ) | const |
boundaryid is periodic, false otherwise Definition at line 198 of file dof_map.C.
References _periodic_boundaries.
{
if (_periodic_boundaries->count(boundaryid) != 0)
return true;
return false;
}
| dof_id_type libMesh::DofMap::last_dof | ( | const processor_id_type | proc | ) | const [inline] |
| dof_id_type libMesh::DofMap::last_dof | ( | ) | const [inline] |
Definition at line 481 of file dof_map.h.
References last_dof(), and libMesh::ParallelObject::processor_id().
Referenced by last_dof().
{ return this->last_dof(this->processor_id()); }
| void libMesh::DofMap::local_variable_indices | ( | std::vector< dof_id_type > & | idx, |
| const MeshBase & | mesh, | ||
| unsigned int | var_num | ||
| ) | const |
Fills an array of those dof indices which belong to the given variable number and live on the current processor.
Definition at line 1011 of file dof_map.C.
References libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::DofObject::dof_number(), end_dof(), first_dof(), libMesh::Elem::get_node(), libMesh::libmesh_assert(), libMesh::MeshBase::local_nodes_begin(), libMesh::MeshBase::local_nodes_end(), libMesh::DofObject::n_comp(), n_nodes, libMesh::Elem::n_nodes(), libMesh::ParallelObject::n_processors(), libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), libMesh::SCALAR, SCALAR_dof_indices(), sys_number(), and variable_type().
Referenced by libMesh::petsc_auto_fieldsplit().
{
const unsigned int sys_num = this->sys_number();
// If this isn't a SCALAR variable, we need to find all its field
// dofs on the mesh
if (this->variable_type(var_num).family != SCALAR)
{
MeshBase::const_element_iterator elem_it = mesh.active_local_elements_begin();
const MeshBase::const_element_iterator elem_end = mesh.active_local_elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
// Only count dofs connected to active
// elements on this processor.
Elem* elem = *elem_it;
const unsigned int n_nodes = elem->n_nodes();
// First get any new nodal DOFS
for (unsigned int n=0; n<n_nodes; n++)
{
Node* node = elem->get_node(n);
if (node->processor_id() < this->processor_id())
continue;
const unsigned int n_comp = node->n_comp(sys_num, var_num);
for(unsigned int i=0; i<n_comp; i++)
{
const dof_id_type index = node->dof_number(sys_num,var_num,i);
libmesh_assert_greater_equal (index, this->first_dof());
libmesh_assert_less (index, this->end_dof());
if (idx.empty() || index > idx.back())
idx.push_back(index);
}
}
// Next get any new element DOFS
const unsigned int n_comp = elem->n_comp(sys_num, var_num);
for(unsigned int i=0; i<n_comp; i++)
{
const dof_id_type index = elem->dof_number(sys_num,var_num,i);
if (idx.empty() || index > idx.back())
idx.push_back(index);
}
} // done looping over elements
// we may have missed assigning DOFs to nodes that we own
// but to which we have no connected elements matching our
// variable restriction criterion. this will happen, for example,
// if variable V is restricted to subdomain S. We may not own
// any elements which live in S, but we may own nodes which are
// *connected* to elements which do. in this scenario these nodes
// will presently have unnumbered DOFs. we need to take care of
// them here since we own them and no other processor will touch them.
{
MeshBase::const_node_iterator node_it = mesh.local_nodes_begin();
const MeshBase::const_node_iterator node_end = mesh.local_nodes_end();
for (; node_it != node_end; ++node_it)
{
Node *node = *node_it;
libmesh_assert(node);
const unsigned int n_comp = node->n_comp(sys_num, var_num);
for(unsigned int i=0; i<n_comp; i++)
{
const dof_id_type index = node->dof_number(sys_num,var_num,i);
if (idx.empty() || index > idx.back())
idx.push_back(index);
}
}
}
}
// Otherwise, count up the SCALAR dofs, if we're on the processor
// that holds this SCALAR variable
else if ( this->processor_id() == (this->n_processors()-1) )
{
std::vector<dof_id_type> di_scalar;
this->SCALAR_dof_indices(di_scalar,var_num);
idx.insert( idx.end(), di_scalar.begin(), di_scalar.end());
}
}
| 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 2111 of file dof_map_constraints.C.
References std::abs(), libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::NumericVector< T >::closed(), libMesh::NumericVector< T >::first_local_index(), libMesh::System::get_dof_map(), libMesh::System::get_mesh(), libMesh::NumericVector< T >::last_local_index(), libMesh::libmesh_assert(), libMesh::DenseMatrixBase< T >::m(), std::max(), mesh, libMesh::DenseMatrixBase< T >::n(), libMesh::Real, and libMesh::System::solution.
{
if (!v)
v = system.solution.get();
NumericVector<Number> &vec = *v;
// We'll assume the vector is closed
libmesh_assert (vec.closed());
Real max_absolute_error = 0., max_relative_error = 0.;
const MeshBase &mesh = system.get_mesh();
libmesh_assert_equal_to (this, &(system.get_dof_map()));
// indices on each element
std::vector<dof_id_type> local_dof_indices;
MeshBase::const_element_iterator elem_it =
mesh.active_local_elements_begin();
const MeshBase::const_element_iterator elem_end =
mesh.active_local_elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
const Elem* elem = *elem_it;
this->dof_indices(elem, local_dof_indices);
std::vector<dof_id_type> raw_dof_indices = local_dof_indices;
// Constraint matrix for each element
DenseMatrix<Number> C;
this->build_constraint_matrix (C, local_dof_indices);
// Continue if the element is unconstrained
if (!C.m())
continue;
libmesh_assert_equal_to (C.m(), raw_dof_indices.size());
libmesh_assert_equal_to (C.n(), local_dof_indices.size());
for (unsigned int i=0; i!=C.m(); ++i)
{
// Recalculate any constrained dof owned by this processor
dof_id_type global_dof = raw_dof_indices[i];
if (this->is_constrained_dof(global_dof) &&
global_dof >= vec.first_local_index() &&
global_dof < vec.last_local_index())
{
DofConstraints::const_iterator
pos = _dof_constraints.find(global_dof);
libmesh_assert (pos != _dof_constraints.end());
Number exact_value = 0;
DofConstraintValueMap::const_iterator rhsit =
_primal_constraint_values.find(global_dof);
if (rhsit != _primal_constraint_values.end())
exact_value = rhsit->second;
for (unsigned int j=0; j!=C.n(); ++j)
{
if (local_dof_indices[j] != global_dof)
exact_value += C(i,j) *
vec(local_dof_indices[j]);
}
max_absolute_error = std::max(max_absolute_error,
std::abs(vec(global_dof) - exact_value));
max_relative_error = std::max(max_relative_error,
std::abs(vec(global_dof) - exact_value)
/ std::abs(exact_value));
}
}
}
return std::pair<Real, Real>(max_absolute_error, max_relative_error);
}
Definition at line 1006 of file dof_map_constraints.C.
{
parallel_object_only();
dof_id_type nc_dofs = this->n_local_constrained_dofs();
this->comm().sum(nc_dofs);
return nc_dofs;
}
| dof_id_type libMesh::DofMap::n_constrained_nodes | ( | ) | const [inline] |
Definition at line 602 of file dof_map.h.
References _node_constraints.
{ return cast_int<dof_id_type>(_node_constraints.size()); }
| dof_id_type libMesh::DofMap::n_dofs | ( | ) | const [inline] |
Definition at line 428 of file dof_map.h.
References _n_dfs.
Referenced by _dof_indices(), distribute_dofs(), and libMesh::UnsteadySolver::old_nonlinear_solution().
{ return _n_dfs; }
| dof_id_type libMesh::DofMap::n_dofs_on_processor | ( | const processor_id_type | proc | ) | const [inline] |
Returns the number of degrees of freedom on partition proc.
Definition at line 444 of file dof_map.h.
References _end_df, and _first_df.
Referenced by n_local_dofs(), and libMesh::SparsityPattern::Build::operator()().
Definition at line 1016 of file dof_map_constraints.C.
{
const DofConstraints::const_iterator lower =
_dof_constraints.lower_bound(this->first_dof()),
upper =
_dof_constraints.upper_bound(this->end_dof()-1);
return cast_int<dof_id_type>(std::distance(lower, upper));
}
| dof_id_type libMesh::DofMap::n_local_dofs | ( | ) | const [inline] |
Definition at line 438 of file dof_map.h.
References n_dofs_on_processor(), and libMesh::ParallelObject::processor_id().
{ return this->n_dofs_on_processor (this->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.
Referenced by libMesh::LibMeshInit::~LibMeshInit().
{ return _n_objects; }
| dof_id_type libMesh::DofMap::n_old_dofs | ( | ) | const [inline] |
Definition at line 1040 of file dof_map.h.
References _n_old_dfs.
Referenced by SCALAR_dof_indices().
{ return _n_old_dfs; }
| processor_id_type libMesh::ParallelObject::n_processors | ( | ) | const [inline, inherited] |
Definition at line 92 of file parallel_object.h.
References libMesh::ParallelObject::_communicator, and libMesh::Parallel::Communicator::size().
Referenced by libMesh::ParmetisPartitioner::_do_repartition(), libMesh::ParallelMesh::add_elem(), libMesh::ParallelMesh::add_node(), libMesh::LaplaceMeshSmoother::allgather_graph(), libMesh::FEMSystem::assembly(), libMesh::ParmetisPartitioner::assign_partitioning(), libMesh::ParallelMesh::assign_unique_ids(), libMesh::AztecLinearSolver< T >::AztecLinearSolver(), libMesh::ParallelMesh::clear(), libMesh::Nemesis_IO_Helper::compute_border_node_ids(), libMesh::Nemesis_IO_Helper::construct_nemesis_filename(), libMesh::UnstructuredMesh::create_pid_mesh(), distribute_dofs(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), libMesh::EnsightIO::EnsightIO(), libMesh::MeshBase::get_info(), libMesh::EquationSystems::init(), libMesh::SystemSubsetBySubdomain::init(), libMesh::ParmetisPartitioner::initialize(), libMesh::Nemesis_IO_Helper::initialize(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), libMesh::MeshTools::libmesh_assert_valid_procids< Elem >(), libMesh::MeshTools::libmesh_assert_valid_procids< Node >(), libMesh::MeshTools::libmesh_assert_valid_refinement_flags(), local_variable_indices(), libMesh::MeshBase::n_active_elem_on_proc(), libMesh::MeshBase::n_elem_on_proc(), libMesh::MeshBase::n_nodes_on_proc(), libMesh::Partitioner::partition(), libMesh::MeshBase::partition(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::PetscLinearSolver< T >::PetscLinearSolver(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), libMesh::MeshTools::processor_bounding_box(), libMesh::System::project_vector(), libMesh::NameBasedIO::read(), libMesh::Nemesis_IO::read(), libMesh::CheckpointIO::read(), libMesh::XdrIO::read(), libMesh::System::read_parallel_data(), libMesh::System::read_SCALAR_dofs(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::System::read_serialized_vector(), libMesh::Partitioner::repartition(), libMesh::Partitioner::set_node_processor_ids(), set_nonlocal_dof_objects(), libMesh::BoundaryInfo::sync(), libMesh::ParallelMesh::update_parallel_id_counts(), libMesh::CheckpointIO::write(), libMesh::GMVIO::write_binary(), libMesh::GMVIO::write_discontinuous_gmv(), libMesh::System::write_parallel_data(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bcs(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), and libMesh::XdrIO::write_serialized_nodesets().
{ return cast_int<processor_id_type>(_communicator.size()); }
| dof_id_type libMesh::DofMap::n_SCALAR_dofs | ( | ) | const [inline] |
Definition at line 433 of file dof_map.h.
References _n_SCALAR_dofs.
Referenced by distribute_dofs(), and SCALAR_dof_indices().
{ return _n_SCALAR_dofs; }
| unsigned int libMesh::DofMap::n_variable_groups | ( | ) | const [inline] |
Definition at line 387 of file dof_map.h.
References _variable_groups.
Referenced by distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), has_blocked_representation(), reinit(), and set_nonlocal_dof_objects().
{ return cast_int<unsigned int>(_variable_groups.size()); }
| unsigned int libMesh::DofMap::n_variables | ( | ) | const [inline] |
Definition at line 395 of file dof_map.h.
References _variables.
Referenced by add_neighbors_to_send_list(), block_size(), distribute_dofs(), DMlibMeshSetSystem_libMesh(), dof_indices(), has_blocked_representation(), old_dof_indices(), libMesh::SparsityPattern::Build::operator()(), and use_coupled_neighbor_dofs().
{ return 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 695 of file dof_map.h.
References _node_constraints.
{ 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 701 of file dof_map.h.
References _node_constraints.
{ 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 274 of file dof_map.C.
References libMesh::MeshBase::node_ptr().
Referenced by distribute_dofs().
{
return mesh.node_ptr(i);
}
| 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 2146 of file dof_map.C.
References libMesh::Elem::active(), libMesh::Variable::active_on_subdomain(), libMesh::Elem::dim(), libMesh::DofObject::dof_number(), libMesh::FEInterface::extra_hanging_dofs(), libMesh::FEType::family, libMesh::MeshTools::Subdivision::find_one_ring(), libMesh::Elem::get_node(), libMesh::DofObject::has_dofs(), libMesh::DofObject::invalid_id, libMesh::invalid_uint, libMesh::Elem::is_vertex(), libMesh::Elem::JUST_COARSENED, libMesh::Elem::JUST_REFINED, libMesh::LAGRANGE, libMesh::libmesh_assert(), libMesh::DofObject::n_comp(), libMesh::FEInterface::n_dofs_at_node(), libMesh::FEInterface::n_dofs_per_elem(), libMesh::Elem::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(), libMesh::SCALAR, SCALAR_dof_indices(), libMesh::START_LOG(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::TRI3SUBDIVISION, libMesh::Elem::type(), variable(), and variable_type().
Referenced by libMesh::FEGenericBase< OutputType >::coarsened_dof_values().
{
START_LOG("old_dof_indices()", "DofMap");
libmesh_assert(elem);
const ElemType type = elem->type();
const unsigned int sys_num = this->sys_number();
const unsigned int n_vars = this->n_variables();
const unsigned int dim = elem->dim();
// If we have dof indices stored on the elem, and there's no chance
// that we only have those indices because we were just p refined,
// then we should have old dof indices too.
libmesh_assert(!elem->has_dofs(sys_num) ||
elem->p_refinement_flag() == Elem::JUST_REFINED ||
elem->old_dof_object);
// Clear the DOF indices vector.
di.clear();
// Create a vector to indicate which
// SCALAR variables have been requested
std::vector<unsigned int> SCALAR_var_numbers;
SCALAR_var_numbers.clear();
// Determine the nodes contributing to element elem
std::vector<Node*> elem_nodes;
if (elem->type() == TRI3SUBDIVISION)
{
// Subdivision surface FE require the 1-ring around elem
const Tri3Subdivision* sd_elem = static_cast<const Tri3Subdivision*>(elem);
MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
}
else
{
// All other FE use only the nodes of elem itself
elem_nodes.resize(elem->n_nodes(), NULL);
for (unsigned int i=0; i<elem->n_nodes(); i++)
elem_nodes[i] = elem->get_node(i);
}
// Get the dof numbers
for (unsigned int v=0; v<n_vars; v++)
if ((v == vn) || (vn == libMesh::invalid_uint))
{
if(this->variable(v).type().family == SCALAR &&
(!elem ||
this->variable(v).active_on_subdomain(elem->subdomain_id())))
{
// We asked for this variable, so add it to the vector.
std::vector<dof_id_type> di_new;
this->SCALAR_dof_indices(di_new,v,true);
di.insert( di.end(), di_new.begin(), di_new.end());
}
else
if (this->variable(v).active_on_subdomain(elem->subdomain_id()))
{ // Do this for all the variables if one was not specified
// or just for the specified variable
// Increase the polynomial order on p refined elements,
// but make sure you get the right polynomial order for
// the OLD degrees of freedom
int p_adjustment = 0;
if (elem->p_refinement_flag() == Elem::JUST_REFINED)
{
libmesh_assert_greater (elem->p_level(), 0);
p_adjustment = -1;
}
else if (elem->p_refinement_flag() == Elem::JUST_COARSENED)
{
p_adjustment = 1;
}
FEType fe_type = this->variable_type(v);
fe_type.order = static_cast<Order>(fe_type.order +
elem->p_level() +
p_adjustment);
const bool extra_hanging_dofs =
FEInterface::extra_hanging_dofs(fe_type);
// Get the node-based DOF numbers
for (unsigned int n=0; n<elem_nodes.size(); n++)
{
const Node* node = elem_nodes[n];
// There is a potential problem with h refinement. Imagine a
// quad9 that has a linear FE on it. Then, on the hanging side,
// it can falsely identify a DOF at the mid-edge node. This is why
// we call FEInterface instead of node->n_comp() directly.
const unsigned int nc = FEInterface::n_dofs_at_node (dim,
fe_type,
type,
n);
libmesh_assert(node->old_dof_object);
// If this is a non-vertex on a hanging node with extra
// degrees of freedom, we use the non-vertex dofs (which
// come in reverse order starting from the end, to
// simplify p refinement)
if (extra_hanging_dofs && !elem->is_vertex(n))
{
const int dof_offset =
node->old_dof_object->n_comp(sys_num,v) - nc;
// We should never have fewer dofs than necessary on a
// node unless we're getting indices on a parent element
// or a just-coarsened element
if (dof_offset < 0)
{
libmesh_assert(!elem->active() || elem->refinement_flag() ==
Elem::JUST_COARSENED);
di.resize(di.size() + nc, DofObject::invalid_id);
}
else
for (int i=node->old_dof_object->n_comp(sys_num,v)-1;
i>=dof_offset; i--)
{
libmesh_assert_not_equal_to (node->old_dof_object->dof_number(sys_num,v,i),
DofObject::invalid_id);
di.push_back(node->old_dof_object->dof_number(sys_num,v,i));
}
}
// If this is a vertex or an element without extra hanging
// dofs, our dofs come in forward order coming from the
// beginning
else
for (unsigned int i=0; i<nc; i++)
{
libmesh_assert_not_equal_to (node->old_dof_object->dof_number(sys_num,v,i),
DofObject::invalid_id);
di.push_back(node->old_dof_object->dof_number(sys_num,v,i));
}
}
// If there are any element-based DOF numbers, get them
const unsigned int nc = FEInterface::n_dofs_per_elem(dim,
fe_type,
type);
// We should never have fewer dofs than necessary on an
// element unless we're getting indices on a parent element
// or a just-coarsened element
if (nc != 0)
{
if (elem->old_dof_object->n_systems() > sys_num &&
nc <= elem->old_dof_object->n_comp(sys_num,v))
{
libmesh_assert(elem->old_dof_object);
for (unsigned int i=0; i<nc; i++)
{
libmesh_assert_not_equal_to (elem->old_dof_object->dof_number(sys_num,v,i),
DofObject::invalid_id);
di.push_back(elem->old_dof_object->dof_number(sys_num,v,i));
}
}
else
{
libmesh_assert(!elem->active() || fe_type.family == LAGRANGE ||
elem->refinement_flag() == Elem::JUST_COARSENED);
di.resize(di.size() + nc, DofObject::invalid_id);
}
}
}
} // end loop over variables
STOP_LOG("old_dof_indices()", "DofMap");
}
| 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 1559 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, libMesh::START_LOG(), and libMesh::swap().
Referenced by libMesh::EquationSystems::allgather(), libMesh::EquationSystems::reinit(), and libMesh::System::reinit_constraints().
{
START_LOG("prepare_send_list()", "DofMap");
// Check to see if we have any extra stuff to add to the send_list
if (_extra_send_list_function)
{
if (_augment_send_list)
{
libmesh_here();
libMesh::out << "WARNING: You have specified both an extra send list function and object.\n"
<< " Are you sure this is what you meant to do??"
<< std::endl;
}
_extra_send_list_function(_send_list, _extra_send_list_context);
}
if (_augment_send_list)
_augment_send_list->augment_send_list (_send_list);
// First sort the send list. After this
// duplicated elements will be adjacent in the
// vector
std::sort(_send_list.begin(), _send_list.end());
// Now use std::unique to remove duplicate entries
std::vector<dof_id_type>::iterator new_end =
std::unique (_send_list.begin(), _send_list.end());
// Remove the end of the send_list. Use the "swap trick"
// from Effective STL
std::vector<dof_id_type> (_send_list.begin(), new_end).swap (_send_list);
STOP_LOG("prepare_send_list()", "DofMap");
}
| 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 1232 of file dof_map_constraints.C.
References libMesh::n_processors(), and libMesh::processor_id().
{
parallel_object_only();
std::string local_constraints =
this->get_local_constraints(print_nonlocal);
if (this->processor_id())
{
this->comm().send(0, local_constraints);
}
else
{
os << "Processor 0:\n";
os << local_constraints;
for (processor_id_type i=1; i<this->n_processors(); ++i)
{
this->comm().receive(i, local_constraints);
os << "Processor " << i << ":\n";
os << local_constraints;
}
}
}
| 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().
Referenced by libMesh::LibMeshInit::~LibMeshInit().
{
if( _enable_print_counter ) out_stream << ReferenceCounter::get_info();
}
| void libMesh::DofMap::print_info | ( | std::ostream & | os = libMesh::out | ) | const |
| 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 3151 of file dof_map_constraints.C.
References libMesh::libmesh_assert(), and libMesh::Real.
Referenced by libMesh::EquationSystems::allgather(), libMesh::EquationSystems::reinit(), and libMesh::System::reinit_constraints().
{
// We've computed our local constraints, but they may depend on
// non-local constraints that we'll need to take into account.
this->allgather_recursive_constraints(mesh);
// Create a set containing the DOFs we already depend on
typedef std::set<dof_id_type> RCSet;
RCSet unexpanded_set;
for (DofConstraints::iterator i = _dof_constraints.begin();
i != _dof_constraints.end(); ++i)
unexpanded_set.insert(i->first);
while (!unexpanded_set.empty())
for (RCSet::iterator i = unexpanded_set.begin();
i != unexpanded_set.end(); /* nothing */)
{
// If the DOF is constrained
DofConstraints::iterator
pos = _dof_constraints.find(*i);
libmesh_assert (pos != _dof_constraints.end());
DofConstraintRow& constraint_row = pos->second;
DofConstraintValueMap::iterator rhsit =
_primal_constraint_values.find(*i);
Number constraint_rhs = (rhsit == _primal_constraint_values.end()) ?
0 : rhsit->second;
std::vector<dof_id_type> constraints_to_expand;
for (DofConstraintRow::const_iterator
it=constraint_row.begin(); it != constraint_row.end();
++it)
if (it->first != *i && this->is_constrained_dof(it->first))
{
unexpanded_set.insert(it->first);
constraints_to_expand.push_back(it->first);
}
for (std::size_t j = 0; j != constraints_to_expand.size();
++j)
{
dof_id_type expandable = constraints_to_expand[j];
const Real this_coef = constraint_row[expandable];
DofConstraints::const_iterator
subpos = _dof_constraints.find(expandable);
libmesh_assert (subpos != _dof_constraints.end());
const DofConstraintRow& subconstraint_row = subpos->second;
for (DofConstraintRow::const_iterator
it=subconstraint_row.begin();
it != subconstraint_row.end(); ++it)
{
constraint_row[it->first] += it->second * this_coef;
}
DofConstraintValueMap::const_iterator subrhsit =
_primal_constraint_values.find(expandable);
if (subrhsit != _primal_constraint_values.end())
constraint_rhs += subrhsit->second * this_coef;
constraint_row.erase(expandable);
}
if (rhsit == _primal_constraint_values.end())
{
if (constraint_rhs != Number(0))
_primal_constraint_values[*i] = constraint_rhs;
else
_primal_constraint_values.erase(*i);
}
else
{
if (constraint_rhs != Number(0))
rhsit->second = constraint_rhs;
else
_primal_constraint_values.erase(rhsit);
}
if (constraints_to_expand.empty())
unexpanded_set.erase(i++);
else
++i;
}
// In parallel we can't guarantee that nodes/dofs which constrain
// others are on processors which are aware of that constraint, yet
// we need such awareness for sparsity pattern generation. So send
// other processors any constraints they might need to know about.
this->scatter_constraints(mesh);
// Now that we have our root constraint dependencies sorted out, add
// them to the send_list
this->add_constraints_to_send_list();
}
| processor_id_type libMesh::ParallelObject::processor_id | ( | ) | const [inline, inherited] |
Definition at line 98 of file parallel_object.h.
References libMesh::ParallelObject::_communicator, and libMesh::Parallel::Communicator::rank().
Referenced by libMesh::MetisPartitioner::_do_partition(), libMesh::EquationSystems::_read_impl(), libMesh::SerialMesh::active_local_elements_begin(), libMesh::ParallelMesh::active_local_elements_begin(), libMesh::SerialMesh::active_local_elements_end(), libMesh::ParallelMesh::active_local_elements_end(), libMesh::SerialMesh::active_local_subdomain_elements_begin(), libMesh::ParallelMesh::active_local_subdomain_elements_begin(), libMesh::SerialMesh::active_local_subdomain_elements_end(), libMesh::ParallelMesh::active_local_subdomain_elements_end(), libMesh::SerialMesh::active_not_local_elements_begin(), libMesh::ParallelMesh::active_not_local_elements_begin(), libMesh::SerialMesh::active_not_local_elements_end(), libMesh::ParallelMesh::active_not_local_elements_end(), libMesh::ParallelMesh::add_elem(), add_neighbors_to_send_list(), libMesh::ParallelMesh::add_node(), libMesh::UnstructuredMesh::all_second_order(), libMesh::FEMSystem::assembly(), libMesh::ParmetisPartitioner::assign_partitioning(), libMesh::ParallelMesh::assign_unique_ids(), libMesh::EquationSystems::build_discontinuous_solution_vector(), libMesh::Nemesis_IO_Helper::build_element_and_node_maps(), libMesh::ParmetisPartitioner::build_graph(), libMesh::InfElemBuilder::build_inf_elem(), build_sparsity(), libMesh::ParallelMesh::clear(), libMesh::ExodusII_IO_Helper::close(), libMesh::Nemesis_IO_Helper::compute_border_node_ids(), libMesh::Nemesis_IO_Helper::compute_communication_map_parameters(), libMesh::Nemesis_IO_Helper::compute_internal_and_border_elems_and_internal_nodes(), libMesh::Nemesis_IO_Helper::compute_node_communication_maps(), libMesh::Nemesis_IO_Helper::compute_num_global_elem_blocks(), libMesh::Nemesis_IO_Helper::compute_num_global_nodesets(), libMesh::Nemesis_IO_Helper::compute_num_global_sidesets(), libMesh::Nemesis_IO_Helper::construct_nemesis_filename(), libMesh::ExodusII_IO_Helper::create(), libMesh::ParallelMesh::delete_elem(), libMesh::ParallelMesh::delete_node(), distribute_dofs(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), end_dof(), end_old_dof(), libMesh::EnsightIO::EnsightIO(), libMesh::SerialMesh::facelocal_elements_begin(), libMesh::ParallelMesh::facelocal_elements_begin(), libMesh::SerialMesh::facelocal_elements_end(), libMesh::ParallelMesh::facelocal_elements_end(), libMesh::MeshFunction::find_element(), libMesh::UnstructuredMesh::find_neighbors(), first_dof(), first_old_dof(), libMesh::Nemesis_IO_Helper::get_cmap_params(), libMesh::Nemesis_IO_Helper::get_eb_info_global(), libMesh::Nemesis_IO_Helper::get_elem_cmap(), libMesh::Nemesis_IO_Helper::get_elem_map(), libMesh::MeshBase::get_info(), libMesh::Nemesis_IO_Helper::get_init_global(), libMesh::Nemesis_IO_Helper::get_init_info(), libMesh::Nemesis_IO_Helper::get_loadbal_param(), libMesh::Nemesis_IO_Helper::get_node_cmap(), libMesh::Nemesis_IO_Helper::get_node_map(), libMesh::Nemesis_IO_Helper::get_ns_param_global(), libMesh::Nemesis_IO_Helper::get_ss_param_global(), libMesh::SystemSubsetBySubdomain::init(), libMesh::ParmetisPartitioner::initialize(), libMesh::ExodusII_IO_Helper::initialize(), libMesh::ExodusII_IO_Helper::initialize_element_variables(), libMesh::ExodusII_IO_Helper::initialize_global_variables(), libMesh::ExodusII_IO_Helper::initialize_nodal_variables(), libMesh::ParallelMesh::insert_elem(), libMesh::SparsityPattern::Build::join(), last_dof(), libMesh::MeshTools::libmesh_assert_valid_procids< Elem >(), libMesh::MeshTools::libmesh_assert_valid_procids< Node >(), libMesh::SerialMesh::local_elements_begin(), libMesh::ParallelMesh::local_elements_begin(), libMesh::SerialMesh::local_elements_end(), libMesh::ParallelMesh::local_elements_end(), libMesh::SerialMesh::local_level_elements_begin(), libMesh::ParallelMesh::local_level_elements_begin(), libMesh::SerialMesh::local_level_elements_end(), libMesh::ParallelMesh::local_level_elements_end(), libMesh::SerialMesh::local_nodes_begin(), libMesh::ParallelMesh::local_nodes_begin(), libMesh::SerialMesh::local_nodes_end(), libMesh::ParallelMesh::local_nodes_end(), libMesh::SerialMesh::local_not_level_elements_begin(), libMesh::ParallelMesh::local_not_level_elements_begin(), libMesh::SerialMesh::local_not_level_elements_end(), libMesh::ParallelMesh::local_not_level_elements_end(), local_variable_indices(), libMesh::MeshRefinement::make_coarsening_compatible(), libMesh::MeshBase::n_active_local_elem(), libMesh::BoundaryInfo::n_boundary_conds(), libMesh::BoundaryInfo::n_edge_conds(), n_local_dofs(), libMesh::System::n_local_dofs(), libMesh::MeshBase::n_local_elem(), libMesh::MeshBase::n_local_nodes(), libMesh::BoundaryInfo::n_nodeset_conds(), libMesh::SerialMesh::not_local_elements_begin(), libMesh::ParallelMesh::not_local_elements_begin(), libMesh::SerialMesh::not_local_elements_end(), libMesh::ParallelMesh::not_local_elements_end(), libMesh::WeightedPatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::SparsityPattern::Build::operator()(), libMesh::PatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::ParallelMesh::ParallelMesh(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), libMesh::System::project_vector(), libMesh::Nemesis_IO_Helper::put_cmap_params(), libMesh::Nemesis_IO_Helper::put_elem_cmap(), libMesh::Nemesis_IO_Helper::put_elem_map(), libMesh::Nemesis_IO_Helper::put_loadbal_param(), libMesh::Nemesis_IO_Helper::put_node_cmap(), libMesh::Nemesis_IO_Helper::put_node_map(), libMesh::NameBasedIO::read(), libMesh::Nemesis_IO::read(), libMesh::CheckpointIO::read(), libMesh::XdrIO::read(), libMesh::ExodusII_IO_Helper::read_elem_num_map(), libMesh::System::read_header(), libMesh::System::read_legacy_data(), libMesh::ExodusII_IO_Helper::read_node_num_map(), libMesh::System::read_parallel_data(), libMesh::System::read_SCALAR_dofs(), libMesh::XdrIO::read_serialized_bc_names(), libMesh::XdrIO::read_serialized_bcs(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::System::read_serialized_data(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::System::read_serialized_vector(), libMesh::System::read_serialized_vectors(), libMesh::MeshData::read_xdr(), libMesh::SerialMesh::semilocal_elements_begin(), libMesh::ParallelMesh::semilocal_elements_begin(), libMesh::SerialMesh::semilocal_elements_end(), libMesh::ParallelMesh::semilocal_elements_end(), libMesh::Partitioner::set_node_processor_ids(), set_nonlocal_dof_objects(), libMesh::LaplaceMeshSmoother::smooth(), libMesh::BoundaryInfo::sync(), libMesh::MeshTools::total_weight(), libMesh::ParallelMesh::update_parallel_id_counts(), libMesh::MeshTools::weight(), libMesh::NameBasedIO::write(), libMesh::ExodusII_IO::write(), libMesh::CheckpointIO::write(), libMesh::XdrIO::write(), libMesh::EquationSystems::write(), libMesh::GMVIO::write_discontinuous_gmv(), libMesh::ExodusII_IO::write_element_data(), libMesh::ExodusII_IO_Helper::write_element_values(), libMesh::ExodusII_IO_Helper::write_elements(), libMesh::ExodusII_IO::write_global_data(), libMesh::ExodusII_IO_Helper::write_global_values(), libMesh::System::write_header(), libMesh::ExodusII_IO::write_information_records(), libMesh::ExodusII_IO_Helper::write_information_records(), libMesh::ExodusII_IO_Helper::write_nodal_coordinates(), libMesh::UCDIO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data_discontinuous(), libMesh::ExodusII_IO_Helper::write_nodal_values(), libMesh::ExodusII_IO_Helper::write_nodesets(), libMesh::Nemesis_IO_Helper::write_nodesets(), libMesh::System::write_parallel_data(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bc_names(), libMesh::XdrIO::write_serialized_bcs(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::System::write_serialized_data(), libMesh::XdrIO::write_serialized_nodes(), libMesh::XdrIO::write_serialized_nodesets(), libMesh::XdrIO::write_serialized_subdomain_names(), libMesh::System::write_serialized_vector(), libMesh::System::write_serialized_vectors(), libMesh::ExodusII_IO_Helper::write_sidesets(), libMesh::Nemesis_IO_Helper::write_sidesets(), libMesh::ExodusII_IO::write_timestep(), and libMesh::ExodusII_IO_Helper::write_timestep().
{ return cast_int<processor_id_type>(_communicator.rank()); }
| void libMesh::DofMap::reinit | ( | MeshBase & | mesh | ) |
Reinitialize the underlying data strucures conformal to the current mesh.
Definition at line 439 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, libMesh::libmesh_assert(), 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(), libMesh::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::START_LOG(), libMesh::Elem::subdomain_id(), sys_number(), libMesh::Variable::type(), libMesh::Elem::type(), variable_group(), and libMesh::DofObject::vg_dof_base().
Referenced by distribute_dofs().
{
libmesh_assert (mesh.is_prepared());
START_LOG("reinit()", "DofMap");
const unsigned int
sys_num = this->sys_number(),
n_var_groups = this->n_variable_groups();
// The DofObjects need to know how many variable groups we have, and
// how many variables there are in each group.
std::vector<unsigned int> n_vars_per_group; n_vars_per_group.reserve (n_var_groups);
for (unsigned int vg=0; vg<n_var_groups; vg++)
n_vars_per_group.push_back (this->variable_group(vg).n_variables());
#ifdef LIBMESH_ENABLE_AMR
//------------------------------------------------------------
// Clear the old_dof_objects for all the nodes
// and elements so that we can overwrite them
{
MeshBase::node_iterator node_it = mesh.nodes_begin();
const MeshBase::node_iterator node_end = mesh.nodes_end();
for ( ; node_it != node_end; ++node_it)
{
(*node_it)->clear_old_dof_object();
libmesh_assert (!(*node_it)->old_dof_object);
}
MeshBase::element_iterator elem_it = mesh.elements_begin();
const MeshBase::element_iterator elem_end = mesh.elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
(*elem_it)->clear_old_dof_object();
libmesh_assert (!(*elem_it)->old_dof_object);
}
}
//------------------------------------------------------------
// Set the old_dof_objects for the elements that
// weren't just created, if these old dof objects
// had variables
{
MeshBase::element_iterator elem_it = mesh.elements_begin();
const MeshBase::element_iterator elem_end = mesh.elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
Elem* elem = *elem_it;
// Skip the elements that were just refined
if (elem->refinement_flag() == Elem::JUST_REFINED) continue;
for (unsigned int n=0; n<elem->n_nodes(); n++)
{
Node* node = elem->get_node(n);
if (node->old_dof_object == NULL)
if (node->has_dofs(sys_num))
node->set_old_dof_object();
}
libmesh_assert (!elem->old_dof_object);
if (elem->has_dofs(sys_num))
elem->set_old_dof_object();
}
}
#endif // #ifdef LIBMESH_ENABLE_AMR
//------------------------------------------------------------
// Then set the number of variables for each \p DofObject
// equal to n_variables() for this system. This will
// handle new \p DofObjects that may have just been created
{
// All the nodes
MeshBase::node_iterator node_it = mesh.nodes_begin();
const MeshBase::node_iterator node_end = mesh.nodes_end();
for ( ; node_it != node_end; ++node_it)
(*node_it)->set_n_vars_per_group(sys_num, n_vars_per_group);
// All the elements
MeshBase::element_iterator elem_it = mesh.elements_begin();
const MeshBase::element_iterator elem_end = mesh.elements_end();
for ( ; elem_it != elem_end; ++elem_it)
(*elem_it)->set_n_vars_per_group(sys_num, n_vars_per_group);
}
// Zero _n_SCALAR_dofs, it will be updated below.
this->_n_SCALAR_dofs = 0;
//------------------------------------------------------------
// Next allocate space for the DOF indices
for (unsigned int vg=0; vg<n_var_groups; vg++)
{
const VariableGroup &vg_description = this->variable_group(vg);
const unsigned int n_var_in_group = vg_description.n_variables();
const FEType& base_fe_type = vg_description.type();
// Don't need to loop over elements for a SCALAR variable
// Just increment _n_SCALAR_dofs
if(base_fe_type.family == SCALAR)
{
this->_n_SCALAR_dofs += base_fe_type.order*n_var_in_group;
continue;
}
// This should be constant even on p-refined elements
const bool extra_hanging_dofs =
FEInterface::extra_hanging_dofs(base_fe_type);
// For all the active elements
MeshBase::element_iterator elem_it = mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = mesh.active_elements_end();
// Count vertex degrees of freedom first
for ( ; elem_it != elem_end; ++elem_it)
{
Elem* elem = *elem_it;
libmesh_assert(elem);
// Skip the numbering if this variable is
// not active on this element's subdomain
if (!vg_description.active_on_subdomain(elem->subdomain_id()))
continue;
const ElemType type = elem->type();
const unsigned int dim = elem->dim();
FEType fe_type = base_fe_type;
#ifdef LIBMESH_ENABLE_AMR
// Make sure we haven't done more p refinement than we can
// handle
if (elem->p_level() + base_fe_type.order >
FEInterface::max_order(base_fe_type, type))
{
# ifdef DEBUG
if (FEInterface::max_order(base_fe_type,type) < static_cast<unsigned int>(base_fe_type.order))
libmesh_error_msg("ERROR: Finite element " \
<< Utility::enum_to_string(base_fe_type.family) \
<< " on geometric element " \
<< Utility::enum_to_string(type) \
<< "\nonly supports FEInterface::max_order = " \
<< FEInterface::max_order(base_fe_type,type) \
<< ", not fe_type.order = " \
<< base_fe_type.order);
libMesh::err
<< "WARNING: Finite element "
<< Utility::enum_to_string(base_fe_type.family)
<< " on geometric element "
<< Utility::enum_to_string(type) << std::endl
<< "could not be p refined past FEInterface::max_order = "
<< FEInterface::max_order(base_fe_type,type)
<< std::endl;
# endif
elem->set_p_level(FEInterface::max_order(base_fe_type,type)
- base_fe_type.order);
}
#endif
fe_type.order = static_cast<Order>(fe_type.order +
elem->p_level());
// Allocate the vertex DOFs
for (unsigned int n=0; n<elem->n_nodes(); n++)
{
Node* node = elem->get_node(n);
if (elem->is_vertex(n))
{
const unsigned int old_node_dofs =
node->n_comp_group(sys_num, vg);
const unsigned int vertex_dofs =
std::max(FEInterface::n_dofs_at_node(dim, fe_type,
type, n),
old_node_dofs);
// Some discontinuous FEs have no vertex dofs
if (vertex_dofs > old_node_dofs)
{
node->set_n_comp_group(sys_num, vg,
vertex_dofs);
// Abusing dof_number to set a "this is a
// vertex" flag
node->set_vg_dof_base(sys_num, vg,
vertex_dofs);
// libMesh::out << "sys_num,vg,old_node_dofs,vertex_dofs="
// << sys_num << ","
// << vg << ","
// << old_node_dofs << ","
// << vertex_dofs << '\n',
// node->debug_buffer();
// libmesh_assert_equal_to (vertex_dofs, node->n_comp(sys_num, vg));
// libmesh_assert_equal_to (vertex_dofs, node->vg_dof_base(sys_num, vg));
}
}
}
} // done counting vertex dofs
// count edge & face dofs next
elem_it = mesh.active_elements_begin();
for ( ; elem_it != elem_end; ++elem_it)
{
Elem* elem = *elem_it;
libmesh_assert(elem);
// Skip the numbering if this variable is
// not active on this element's subdomain
if (!vg_description.active_on_subdomain(elem->subdomain_id()))
continue;
const ElemType type = elem->type();
const unsigned int dim = elem->dim();
FEType fe_type = base_fe_type;
fe_type.order = static_cast<Order>(fe_type.order +
elem->p_level());
// Allocate the edge and face DOFs
for (unsigned int n=0; n<elem->n_nodes(); n++)
{
Node* node = elem->get_node(n);
const unsigned int old_node_dofs =
node->n_comp_group(sys_num, vg);
const unsigned int vertex_dofs = old_node_dofs?
cast_int<unsigned int>(node->vg_dof_base (sys_num,vg)):0;
const unsigned int new_node_dofs =
FEInterface::n_dofs_at_node(dim, fe_type, type, n);
// We've already allocated vertex DOFs
if (elem->is_vertex(n))
{
libmesh_assert_greater_equal (old_node_dofs, vertex_dofs);
// //if (vertex_dofs < new_node_dofs)
// libMesh::out << "sys_num,vg,old_node_dofs,vertex_dofs,new_node_dofs="
// << sys_num << ","
// << vg << ","
// << old_node_dofs << ","
// << vertex_dofs << ","
// << new_node_dofs << '\n',
// node->debug_buffer();
libmesh_assert_greater_equal (vertex_dofs, new_node_dofs);
}
// We need to allocate the rest
else
{
// If this has no dofs yet, it needs no vertex
// dofs, so we just give it edge or face dofs
if (!old_node_dofs)
{
node->set_n_comp_group(sys_num, vg,
new_node_dofs);
// Abusing dof_number to set a "this has no
// vertex dofs" flag
if (new_node_dofs)
node->set_vg_dof_base(sys_num, vg,
0);
}
// If this has dofs, but has no vertex dofs,
// it may still need more edge or face dofs if
// we're p-refined.
else if (vertex_dofs == 0)
{
if (new_node_dofs > old_node_dofs)
{
node->set_n_comp_group(sys_num, vg,
new_node_dofs);
node->set_vg_dof_base(sys_num, vg,
vertex_dofs);
}
}
// If this is another element's vertex,
// add more (non-overlapping) edge/face dofs if
// necessary
else if (extra_hanging_dofs)
{
if (new_node_dofs > old_node_dofs - vertex_dofs)
{
node->set_n_comp_group(sys_num, vg,
vertex_dofs + new_node_dofs);
node->set_vg_dof_base(sys_num, vg,
vertex_dofs);
}
}
// If this is another element's vertex, add any
// (overlapping) edge/face dofs if necessary
else
{
libmesh_assert_greater_equal (old_node_dofs, vertex_dofs);
if (new_node_dofs > old_node_dofs)
{
node->set_n_comp_group(sys_num, vg,
new_node_dofs);
node->set_vg_dof_base (sys_num, vg,
vertex_dofs);
}
}
}
}
// Allocate the element DOFs
const unsigned int dofs_per_elem =
FEInterface::n_dofs_per_elem(dim, fe_type,
type);
elem->set_n_comp_group(sys_num, vg, dofs_per_elem);
}
} // end loop over variable groups
// Calling DofMap::reinit() by itself makes little sense,
// so we won't bother with nonlocal DofObjects.
// Those will be fixed by distribute_dofs
//------------------------------------------------------------
// Finally, clear all the current DOF indices
// (distribute_dofs expects them cleared!)
this->invalidate_dofs(mesh);
STOP_LOG("reinit()", "DofMap");
}
| void libMesh::DofMap::remove_adjoint_dirichlet_boundary | ( | const DirichletBoundary & | dirichlet_boundary, |
| unsigned int | q | ||
| ) |
Removes from the system the specified Dirichlet boundary for the adjoint equation defined by Quantity of interest index q
Definition at line 3851 of file dof_map_constraints.C.
References libMesh::DirichletBoundary::b, end, libMesh::libmesh_assert(), and libMesh::DirichletBoundary::variables.
{
libmesh_assert_greater(_adjoint_dirichlet_boundaries.size(),
qoi_index);
// Find a boundary condition matching the one to be removed
std::vector<DirichletBoundary *>::iterator it =
_adjoint_dirichlet_boundaries[qoi_index]->begin();
std::vector<DirichletBoundary *>::iterator end =
_adjoint_dirichlet_boundaries[qoi_index]->end();
for (; it != end; ++it)
{
DirichletBoundary *bdy = *it;
if ((bdy->b == boundary_to_remove.b) &&
bdy->variables == boundary_to_remove.variables)
break;
}
// Delete it and remove it
libmesh_assert (it != end);
delete *it;
_adjoint_dirichlet_boundaries[qoi_index]->erase(it);
}
| void libMesh::DofMap::remove_dirichlet_boundary | ( | const DirichletBoundary & | dirichlet_boundary | ) |
Removes the specified Dirichlet boundary from the system.
Definition at line 3830 of file dof_map_constraints.C.
References libMesh::DirichletBoundary::b, end, libMesh::libmesh_assert(), and libMesh::DirichletBoundary::variables.
{
// Find a boundary condition matching the one to be removed
std::vector<DirichletBoundary *>::iterator it = _dirichlet_boundaries->begin();
std::vector<DirichletBoundary *>::iterator end = _dirichlet_boundaries->end();
for (; it != end; ++it)
{
DirichletBoundary *bdy = *it;
if ((bdy->b == boundary_to_remove.b) &&
bdy->variables == boundary_to_remove.variables)
break;
}
// Delete it and remove it
libmesh_assert (it != end);
delete *it;
_dirichlet_boundaries->erase(it);
}
| 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.
Definition at line 2085 of file dof_map.C.
References _first_old_scalar_df, _first_scalar_df, libMesh::DofObject::invalid_id, libMesh::libmesh_assert(), n_old_dofs(), n_SCALAR_dofs(), libMesh::FEType::order, libMesh::SCALAR, libMesh::START_LOG(), libMesh::Variable::type(), and variable().
Referenced by add_neighbors_to_send_list(), dof_indices(), local_variable_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().
{
START_LOG("SCALAR_dof_indices()", "DofMap");
libmesh_assert(this->variable(vn).type().family == SCALAR);
#ifdef LIBMESH_ENABLE_AMR
// If we're asking for old dofs then we'd better have some
if (old_dofs)
libmesh_assert_greater_equal(n_old_dofs(), n_SCALAR_dofs());
dof_id_type my_idx = old_dofs ?
this->_first_old_scalar_df[vn] : this->_first_scalar_df[vn];
#else
dof_id_type my_idx = this->_first_scalar_df[vn];
#endif
libmesh_assert_not_equal_to(my_idx, DofObject::invalid_id);
// The number of SCALAR dofs comes from the variable order
const int n_dofs_vn = this->variable(vn).type().order;
di.resize(n_dofs_vn);
for(int i = 0; i != n_dofs_vn; ++i)
di[i] = my_idx++;
STOP_LOG("SCALAR_dof_indices()", "DofMap");
}
| void libMesh::DofMap::scatter_constraints | ( | MeshBase & | mesh | ) |
Sends constraint equations to constraining processors
Definition at line 3254 of file dof_map_constraints.C.
References libMesh::MeshBase::active_not_local_elements_begin(), libMesh::MeshBase::active_not_local_elements_end(), end, libMesh::DofObject::id(), libMesh::MeshBase::is_serial(), libMesh::libmesh_assert(), mesh, libMesh::n_processors(), libMesh::MeshBase::node_ptr(), libMesh::processor_id(), libMesh::DofObject::processor_id(), and libMesh::TypeVector< T >::size().
{
// At this point each processor with a constrained node knows
// the corresponding constraint row, but we also need each processor
// with a constrainer node to know the corresponding row(s).
// This function must be run on all processors at once
parallel_object_only();
// Return immediately if there's nothing to gather
if (this->n_processors() == 1)
return;
// We might get to return immediately if none of the processors
// found any constraints
unsigned int has_constraints = !_dof_constraints.empty()
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
|| !_node_constraints.empty()
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
;
this->comm().max(has_constraints);
if (!has_constraints)
return;
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
std::vector<std::set<dof_id_type> > pushed_node_ids(this->n_processors());
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
std::vector<std::set<dof_id_type> > pushed_ids(this->n_processors());
// Collect the dof constraints I need to push to each processor
dof_id_type constrained_proc_id = 0;
for (DofConstraints::iterator i = _dof_constraints.begin();
i != _dof_constraints.end(); ++i)
{
const dof_id_type constrained = i->first;
while (constrained >= _end_df[constrained_proc_id])
constrained_proc_id++;
if (constrained_proc_id != this->processor_id())
continue;
DofConstraintRow &row = i->second;
for (DofConstraintRow::iterator j = row.begin();
j != row.end(); ++j)
{
const dof_id_type constraining = j->first;
processor_id_type constraining_proc_id = 0;
while (constraining >= _end_df[constraining_proc_id])
constraining_proc_id++;
if (constraining_proc_id != this->processor_id() &&
constraining_proc_id != constrained_proc_id)
pushed_ids[constraining_proc_id].insert(constrained);
}
}
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
// Collect the node constraints to push to each processor
for (NodeConstraints::iterator i = _node_constraints.begin();
i != _node_constraints.end(); ++i)
{
const Node *constrained = i->first;
if (constrained->processor_id() != this->processor_id())
continue;
NodeConstraintRow &row = i->second.first;
for (NodeConstraintRow::iterator j = row.begin();
j != row.end(); ++j)
{
const Node *constraining = j->first;
if (constraining->processor_id() != this->processor_id() &&
constraining->processor_id() != constrained->processor_id())
pushed_node_ids[constraining->processor_id()].insert(constrained->id());
}
}
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
// Now trade constraint rows
for (processor_id_type p = 0; p != this->n_processors(); ++p)
{
// Push to processor procup while receiving from procdown
processor_id_type procup =
cast_int<processor_id_type>((this->processor_id() + p) %
this->n_processors());
processor_id_type procdown =
cast_int<processor_id_type>((this->n_processors() +
this->processor_id() - p) %
this->n_processors());
// Pack the dof constraint rows and rhs's to push to procup
const std::size_t pushed_ids_size = pushed_ids[procup].size();
std::vector<std::vector<dof_id_type> > pushed_keys(pushed_ids_size);
std::vector<std::vector<Real> > pushed_vals(pushed_ids_size);
std::vector<Number> pushed_rhss(pushed_ids_size);
std::set<dof_id_type>::const_iterator it;
std::size_t push_i;
for (push_i = 0, it = pushed_ids[procup].begin();
it != pushed_ids[procup].end(); ++push_i, ++it)
{
const dof_id_type constrained = *it;
DofConstraintRow &row = _dof_constraints[constrained];
std::size_t row_size = row.size();
pushed_keys[push_i].reserve(row_size);
pushed_vals[push_i].reserve(row_size);
for (DofConstraintRow::iterator j = row.begin();
j != row.end(); ++j)
{
pushed_keys[push_i].push_back(j->first);
pushed_vals[push_i].push_back(j->second);
}
DofConstraintValueMap::const_iterator rhsit =
_primal_constraint_values.find(constrained);
pushed_rhss[push_i] = (rhsit == _primal_constraint_values.end()) ?
0 : rhsit->second;
}
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
// Pack the node constraint rows to push to procup
const std::size_t pushed_node_ids_size = pushed_node_ids[procup].size();
std::vector<std::vector<dof_id_type> > pushed_node_keys(pushed_node_ids_size);
std::vector<std::vector<Real> > pushed_node_vals(pushed_node_ids_size);
std::vector<Point> pushed_node_offsets(pushed_node_ids_size);
std::set<const Node*> pushed_nodes;
for (push_i = 0, it = pushed_node_ids[procup].begin();
it != pushed_node_ids[procup].end(); ++push_i, ++it)
{
const Node *constrained = mesh.node_ptr(*it);
if (constrained->processor_id() != procdown)
pushed_nodes.insert(constrained);
NodeConstraintRow &row = _node_constraints[constrained].first;
std::size_t row_size = row.size();
pushed_node_keys[push_i].reserve(row_size);
pushed_node_vals[push_i].reserve(row_size);
for (NodeConstraintRow::iterator j = row.begin();
j != row.end(); ++j)
{
const Node* constraining = j->first;
pushed_node_keys[push_i].push_back(constraining->id());
pushed_node_vals[push_i].push_back(j->second);
if (constraining->processor_id() != procup)
pushed_nodes.insert(constraining);
}
pushed_node_offsets[push_i] = _node_constraints[constrained].second;
}
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
// Trade pushed dof constraint rows
std::vector<dof_id_type> pushed_ids_from_me
(pushed_ids[procup].begin(), pushed_ids[procup].end());
std::vector<dof_id_type> pushed_ids_to_me;
std::vector<std::vector<dof_id_type> > pushed_keys_to_me;
std::vector<std::vector<Real> > pushed_vals_to_me;
std::vector<Number> pushed_rhss_to_me;
this->comm().send_receive(procup, pushed_ids_from_me,
procdown, pushed_ids_to_me);
this->comm().send_receive(procup, pushed_keys,
procdown, pushed_keys_to_me);
this->comm().send_receive(procup, pushed_vals,
procdown, pushed_vals_to_me);
this->comm().send_receive(procup, pushed_rhss,
procdown, pushed_rhss_to_me);
libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_keys_to_me.size());
libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_vals_to_me.size());
libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_rhss_to_me.size());
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
// Trade pushed node constraint rows
std::vector<dof_id_type> pushed_node_ids_from_me
(pushed_node_ids[procup].begin(), pushed_node_ids[procup].end());
std::vector<dof_id_type> pushed_node_ids_to_me;
std::vector<std::vector<dof_id_type> > pushed_node_keys_to_me;
std::vector<std::vector<Real> > pushed_node_vals_to_me;
std::vector<Point> pushed_node_offsets_to_me;
this->comm().send_receive(procup, pushed_node_ids_from_me,
procdown, pushed_node_ids_to_me);
this->comm().send_receive(procup, pushed_node_keys,
procdown, pushed_node_keys_to_me);
this->comm().send_receive(procup, pushed_node_vals,
procdown, pushed_node_vals_to_me);
this->comm().send_receive(procup, pushed_node_offsets,
procdown, pushed_node_offsets_to_me);
// Constraining nodes might not even exist on our subset of
// a distributed mesh, so let's make them exist.
if (!mesh.is_serial())
this->comm().send_receive_packed_range
(procup, &mesh, pushed_nodes.begin(), pushed_nodes.end(),
procdown, &mesh, mesh_inserter_iterator<Node>(mesh));
libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_keys_to_me.size());
libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_vals_to_me.size());
libmesh_assert_equal_to (pushed_node_ids_to_me.size(), pushed_node_offsets_to_me.size());
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
// Add the dof constraints that I've been sent
for (std::size_t i = 0; i != pushed_ids_to_me.size(); ++i)
{
libmesh_assert_equal_to (pushed_keys_to_me[i].size(), pushed_vals_to_me[i].size());
dof_id_type constrained = pushed_ids_to_me[i];
// If we don't already have a constraint for this dof,
// add the one we were sent
if (!this->is_constrained_dof(constrained))
{
DofConstraintRow &row = _dof_constraints[constrained];
for (std::size_t j = 0; j != pushed_keys_to_me[i].size(); ++j)
{
row[pushed_keys_to_me[i][j]] = pushed_vals_to_me[i][j];
}
if (pushed_rhss_to_me[i] != Number(0))
_primal_constraint_values[constrained] = pushed_rhss_to_me[i];
else
_primal_constraint_values.erase(constrained);
}
}
#ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
// Add the node constraints that I've been sent
for (std::size_t i = 0; i != pushed_node_ids_to_me.size(); ++i)
{
libmesh_assert_equal_to (pushed_node_keys_to_me[i].size(), pushed_node_vals_to_me[i].size());
dof_id_type constrained_id = pushed_node_ids_to_me[i];
// If we don't already have a constraint for this node,
// add the one we were sent
const Node *constrained = mesh.node_ptr(constrained_id);
if (!this->is_constrained_node(constrained))
{
NodeConstraintRow &row = _node_constraints[constrained].first;
for (std::size_t j = 0; j != pushed_node_keys_to_me[i].size(); ++j)
{
const Node *key_node = mesh.node_ptr(pushed_node_keys_to_me[i][j]);
libmesh_assert(key_node);
row[key_node] = pushed_node_vals_to_me[i][j];
}
_node_constraints[constrained].second = pushed_node_offsets_to_me[i];
}
}
#endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
}
// Next we need to push constraints to processors which don't own
// the constrained dof, don't own the constraining dof, but own an
// element supporting the constraining dof.
//
// We need to be able to quickly look up constrained dof ids by what
// constrains them, so that we can handle the case where we see a
// foreign element containing one of our constraining DoF ids and we
// need to push that constraint.
//
// Getting distributed adaptive sparsity patterns right is hard.
typedef std::map<dof_id_type, std::set<dof_id_type> > DofConstrainsMap;
DofConstrainsMap dof_id_constrains;
for (DofConstraints::iterator i = _dof_constraints.begin();
i != _dof_constraints.end(); ++i)
{
const dof_id_type constrained = i->first;
DofConstraintRow &row = i->second;
for (DofConstraintRow::iterator j = row.begin();
j != row.end(); ++j)
{
const dof_id_type constraining = j->first;
dof_id_type constraining_proc_id = 0;
while (constraining >= _end_df[constraining_proc_id])
constraining_proc_id++;
if (constraining_proc_id == this->processor_id())
dof_id_constrains[constraining].insert(constrained);
}
}
// Loop over all foreign elements, find any supporting our
// constrained dof indices.
pushed_ids.clear();
pushed_ids.resize(this->n_processors());
MeshBase::const_element_iterator it = mesh.active_not_local_elements_begin(),
end = mesh.active_not_local_elements_end();
for (; it != end; ++it)
{
const Elem *elem = *it;
std::vector<dof_id_type> my_dof_indices;
this->dof_indices (elem, my_dof_indices);
for (std::size_t i=0; i != my_dof_indices.size(); ++i)
{
DofConstrainsMap::const_iterator dcmi =
dof_id_constrains.find(my_dof_indices[i]);
if (dcmi != dof_id_constrains.end())
{
for (DofConstrainsMap::mapped_type::const_iterator mti =
dcmi->second.begin();
mti != dcmi->second.end(); ++mti)
{
const dof_id_type constrained = *mti;
dof_id_type the_constrained_proc_id = 0;
while (constrained >= _end_df[the_constrained_proc_id])
the_constrained_proc_id++;
const dof_id_type elemproc = elem->processor_id();
if (elemproc != the_constrained_proc_id)
pushed_ids[elemproc].insert(constrained);
}
}
}
}
// One last trade of constraint rows
for (processor_id_type p = 0; p != this->n_processors(); ++p)
{
// Push to processor procup while receiving from procdown
processor_id_type procup =
cast_int<processor_id_type>((this->processor_id() + p) %
this->n_processors());
processor_id_type procdown =
cast_int<processor_id_type>((this->n_processors() +
this->processor_id() - p) %
this->n_processors());
// Pack the dof constraint rows and rhs's to push to procup
const std::size_t pushed_ids_size = pushed_ids[procup].size();
std::vector<std::vector<dof_id_type> > pushed_keys(pushed_ids_size);
std::vector<std::vector<Real> > pushed_vals(pushed_ids_size);
std::vector<Number> pushed_rhss(pushed_ids_size);
// As long as we're declaring them outside the loop, let's initialize them too!
std::set<dof_id_type>::const_iterator pushed_ids_iter = pushed_ids[procup].begin();
std::size_t push_i = 0;
for ( ; pushed_ids_iter != pushed_ids[procup].end(); ++push_i, ++pushed_ids_iter)
{
const dof_id_type constrained = *pushed_ids_iter;
DofConstraintRow &row = _dof_constraints[constrained];
std::size_t row_size = row.size();
pushed_keys[push_i].reserve(row_size);
pushed_vals[push_i].reserve(row_size);
for (DofConstraintRow::iterator j = row.begin();
j != row.end(); ++j)
{
pushed_keys[push_i].push_back(j->first);
pushed_vals[push_i].push_back(j->second);
}
DofConstraintValueMap::const_iterator rhsit =
_primal_constraint_values.find(constrained);
pushed_rhss[push_i] = (rhsit == _primal_constraint_values.end()) ?
0 : rhsit->second;
}
// Trade pushed dof constraint rows
std::vector<dof_id_type> pushed_ids_from_me
(pushed_ids[procup].begin(), pushed_ids[procup].end());
std::vector<dof_id_type> pushed_ids_to_me;
std::vector<std::vector<dof_id_type> > pushed_keys_to_me;
std::vector<std::vector<Real> > pushed_vals_to_me;
std::vector<Number> pushed_rhss_to_me;
this->comm().send_receive(procup, pushed_ids_from_me,
procdown, pushed_ids_to_me);
this->comm().send_receive(procup, pushed_keys,
procdown, pushed_keys_to_me);
this->comm().send_receive(procup, pushed_vals,
procdown, pushed_vals_to_me);
this->comm().send_receive(procup, pushed_rhss,
procdown, pushed_rhss_to_me);
libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_keys_to_me.size());
libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_vals_to_me.size());
libmesh_assert_equal_to (pushed_ids_to_me.size(), pushed_rhss_to_me.size());
// Add the dof constraints that I've been sent
for (std::size_t i = 0; i != pushed_ids_to_me.size(); ++i)
{
libmesh_assert_equal_to (pushed_keys_to_me[i].size(), pushed_vals_to_me[i].size());
dof_id_type constrained = pushed_ids_to_me[i];
// If we don't already have a constraint for this dof,
// add the one we were sent
if (!this->is_constrained_dof(constrained))
{
DofConstraintRow &row = _dof_constraints[constrained];
for (std::size_t j = 0; j != pushed_keys_to_me[i].size(); ++j)
{
row[pushed_keys_to_me[i][j]] = pushed_vals_to_me[i][j];
}
if (pushed_rhss_to_me[i] != Number(0))
_primal_constraint_values[constrained] = pushed_rhss_to_me[i];
else
_primal_constraint_values.erase(constrained);
}
}
}
}
| void libMesh::DofMap::set_implicit_neighbor_dofs | ( | bool | implicit_neighbor_dofs | ) |
Allow the implicit_neighbor_dofs flag to be set programmatically. This overrides the --implicit_neighbor_dofs commandline option. We can use this to set the implicit neighbor dofs option differently for different systems, whereas the commandline option is the same for all systems.
Definition at line 1597 of file dof_map.C.
References _implicit_neighbor_dofs, and _implicit_neighbor_dofs_initialized.
{
_implicit_neighbor_dofs_initialized = true;
_implicit_neighbor_dofs = implicit_neighbor_dofs;
}
| void libMesh::DofMap::set_nonlocal_dof_objects | ( | iterator_type | objects_begin, |
| iterator_type | objects_end, | ||
| MeshBase & | mesh, | ||
| dofobject_accessor | objects | ||
| ) | [private] |
Helper function for distributing dofs in parallel
Definition at line 289 of file dof_map.C.
References libMesh::Parallel::Communicator::allgather(), libMesh::ParallelObject::comm(), libMesh::DofObject::dof_number(), libMesh::DofObject::id(), libMesh::DofObject::invalid_id, libMesh::DofObject::invalid_processor_id, libMesh::libmesh_assert(), libMesh::DofObject::n_comp(), libMesh::DofObject::n_comp_group(), libMesh::ParallelObject::n_processors(), libMesh::DofObject::n_var_groups(), n_variable_groups(), libMesh::DofObject::n_vars(), libMesh::ParallelObject::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().
{
// This function must be run on all processors at once
parallel_object_only();
// First, iterate over local objects to find out how many
// are on each processor
std::vector<dof_id_type>
ghost_objects_from_proc(this->n_processors(), 0);
iterator_type it = objects_begin;
for (; it != objects_end; ++it)
{
DofObject *obj = *it;
if (obj)
{
processor_id_type obj_procid = obj->processor_id();
// We'd better be completely partitioned by now
libmesh_assert_not_equal_to (obj_procid, DofObject::invalid_processor_id);
ghost_objects_from_proc[obj_procid]++;
}
}
std::vector<dof_id_type> objects_on_proc(this->n_processors(), 0);
this->comm().allgather(ghost_objects_from_proc[this->processor_id()],
objects_on_proc);
#ifdef DEBUG
for (processor_id_type p=0; p != this->n_processors(); ++p)
libmesh_assert_less_equal (ghost_objects_from_proc[p], objects_on_proc[p]);
#endif
// Request sets to send to each processor
std::vector<std::vector<dof_id_type> >
requested_ids(this->n_processors());
// We know how many of our objects live on each processor, so
// reserve() space for requests from each.
for (processor_id_type p=0; p != this->n_processors(); ++p)
if (p != this->processor_id())
requested_ids[p].reserve(ghost_objects_from_proc[p]);
for (it = objects_begin; it != objects_end; ++it)
{
DofObject *obj = *it;
if (obj->processor_id() != DofObject::invalid_processor_id)
requested_ids[obj->processor_id()].push_back(obj->id());
}
#ifdef DEBUG
for (processor_id_type p=0; p != this->n_processors(); ++p)
libmesh_assert_equal_to (requested_ids[p].size(), ghost_objects_from_proc[p]);
#endif
// Next set ghost object n_comps from other processors
for (processor_id_type p=1; p != this->n_processors(); ++p)
{
// Trade my requests with processor procup and procdown
processor_id_type procup =
cast_int<processor_id_type>((this->processor_id() + p) %
this->n_processors());
processor_id_type procdown =
cast_int<processor_id_type>((this->n_processors() +
this->processor_id() - p) %
this->n_processors());
std::vector<dof_id_type> request_to_fill;
this->comm().send_receive(procup, requested_ids[procup],
procdown, request_to_fill);
// Fill those requests
const unsigned int
sys_num = this->sys_number(),
n_var_groups = this->n_variable_groups();
std::vector<dof_id_type> ghost_data
(request_to_fill.size() * 2 * n_var_groups);
for (std::size_t i=0; i != request_to_fill.size(); ++i)
{
DofObject *requested = (this->*objects)(mesh, request_to_fill[i]);
libmesh_assert(requested);
libmesh_assert_equal_to (requested->processor_id(), this->processor_id());
libmesh_assert_equal_to (requested->n_var_groups(sys_num), n_var_groups);
for (unsigned int vg=0; vg != n_var_groups; ++vg)
{
unsigned int n_comp_g =
requested->n_comp_group(sys_num, vg);
ghost_data[i*2*n_var_groups+vg] = n_comp_g;
dof_id_type my_first_dof = n_comp_g ?
requested->vg_dof_base(sys_num, vg) : 0;
libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
ghost_data[i*2*n_var_groups+n_var_groups+vg] = my_first_dof;
}
}
// Trade back the results
std::vector<dof_id_type> filled_request;
this->comm().send_receive(procdown, ghost_data,
procup, filled_request);
// And copy the id changes we've now been informed of
libmesh_assert_equal_to (filled_request.size(),
requested_ids[procup].size() * 2 * n_var_groups);
for (std::size_t i=0; i != requested_ids[procup].size(); ++i)
{
DofObject *requested = (this->*objects)(mesh, requested_ids[procup][i]);
libmesh_assert(requested);
libmesh_assert_equal_to (requested->processor_id(), procup);
for (unsigned int vg=0; vg != n_var_groups; ++vg)
{
unsigned int n_comp_g =
cast_int<unsigned int>(filled_request[i*2*n_var_groups+vg]);
requested->set_n_comp_group(sys_num, vg, n_comp_g);
if (n_comp_g)
{
dof_id_type my_first_dof =
filled_request[i*2*n_var_groups+n_var_groups+vg];
libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
requested->set_vg_dof_base
(sys_num, vg, my_first_dof);
}
}
}
}
#ifdef DEBUG
// Double check for invalid dofs
for (it = objects_begin; it != objects_end; ++it)
{
DofObject *obj = *it;
libmesh_assert (obj);
unsigned int num_variables = obj->n_vars(this->sys_number());
for (unsigned int v=0; v != num_variables; ++v)
{
unsigned int n_comp =
obj->n_comp(this->sys_number(), v);
dof_id_type my_first_dof = n_comp ?
obj->dof_number(this->sys_number(), v, 0) : 0;
libmesh_assert_not_equal_to (my_first_dof, DofObject::invalid_id);
}
}
#endif
}
| void libMesh::DofMap::stash_dof_constraints | ( | ) | [inline] |
Definition at line 679 of file dof_map.h.
References _dof_constraints, _stashed_dof_constraints, and libMesh::libmesh_assert().
{
libmesh_assert(_stashed_dof_constraints.empty());
_dof_constraints.swap(_stashed_dof_constraints);
}
| unsigned int libMesh::DofMap::sys_number | ( | ) | const [inline] |
Definition at line 1432 of file dof_map.h.
References _sys_number.
Referenced by _dof_indices(), add_neighbors_to_send_list(), libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), distribute_dofs(), distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), invalidate_dofs(), local_variable_indices(), old_dof_indices(), reinit(), and set_nonlocal_dof_objects().
{
return _sys_number;
}
| void libMesh::DofMap::unstash_dof_constraints | ( | ) | [inline] |
Definition at line 685 of file dof_map.h.
References _dof_constraints, _stashed_dof_constraints, and libMesh::libmesh_assert().
{
libmesh_assert(_dof_constraints.empty());
_dof_constraints.swap(_stashed_dof_constraints);
}
| 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 1604 of file dof_map.C.
References _implicit_neighbor_dofs, _implicit_neighbor_dofs_initialized, libMesh::FEAbstract::build(), libMesh::command_line_next(), libMesh::DISCONTINUOUS, libMesh::MeshBase::mesh_dimension(), n_variables(), libMesh::on_command_line(), and variable_type().
{
// If we were asked on the command line, then we need to
// include sensitivities between neighbor degrees of freedom
bool implicit_neighbor_dofs =
libMesh::on_command_line ("--implicit_neighbor_dofs");
// If the user specifies --implicit_neighbor_dofs 0, then
// presumably he knows what he is doing and we won't try to
// automatically turn it on even when all the variables are
// discontinuous.
if (implicit_neighbor_dofs)
{
// No flag provided defaults to 'true'
int flag = 1;
flag = libMesh::command_line_next ("--implicit_neighbor_dofs", flag);
if (!flag)
{
// The user said --implicit_neighbor_dofs 0, so he knows
// what he is doing and really doesn't want it.
return false;
}
}
// Possibly override the commandline option, if set_implicit_neighbor_dofs
// has been called.
if(_implicit_neighbor_dofs_initialized)
{
implicit_neighbor_dofs = _implicit_neighbor_dofs;
// Again, if the user explicitly says implicit_neighbor_dofs = false,
// then we return here.
if (!implicit_neighbor_dofs)
return false;
}
// Look at all the variables in this system. If every one is
// discontinuous then the user must be doing DG/FVM, so be nice
// and force implicit_neighbor_dofs=true.
{
bool all_discontinuous_dofs = true;
for (unsigned int var=0; var<this->n_variables(); var++)
if (FEAbstract::build (mesh.mesh_dimension(),
this->variable_type(var))->get_continuity() != DISCONTINUOUS)
all_discontinuous_dofs = false;
if (all_discontinuous_dofs)
implicit_neighbor_dofs = true;
}
return implicit_neighbor_dofs;
}
| const Variable & libMesh::DofMap::variable | ( | const unsigned int | c | ) | const [inline] |
c. Definition at line 1450 of file dof_map.h.
References _variables.
Referenced by _dof_indices(), add_neighbors_to_send_list(), distribute_dofs(), DMlibMeshSetSystem_libMesh(), dof_indices(), old_dof_indices(), libMesh::ProjectSolution::operator()(), libMesh::ProjectFEMSolution::operator()(), libMesh::BoundaryProjectSolution::operator()(), and SCALAR_dof_indices().
{
libmesh_assert_less (c, _variables.size());
return _variables[c];
}
| const VariableGroup & libMesh::DofMap::variable_group | ( | const unsigned int | c | ) | const [inline] |
VariableGroup description object for group g. Definition at line 1440 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().
{
libmesh_assert_less (g, _variable_groups.size());
return _variable_groups[g];
}
| Order libMesh::DofMap::variable_group_order | ( | const unsigned int | vg | ) | const [inline] |
VariableGroup vg. Definition at line 1470 of file dof_map.h.
References _variable_groups.
{
libmesh_assert_less (vg, _variable_groups.size());
return _variable_groups[vg].type().order;
}
| const FEType & libMesh::DofMap::variable_group_type | ( | const unsigned int | vg | ) | const [inline] |
VariableGroup vg. Definition at line 1490 of file dof_map.h.
References _variable_groups.
{
libmesh_assert_less (vg, _variable_groups.size());
return _variable_groups[vg].type();
}
| Order libMesh::DofMap::variable_order | ( | const unsigned int | c | ) | const [inline] |
c. Definition at line 1460 of file dof_map.h.
References _variables.
{
libmesh_assert_less (c, _variables.size());
return _variables[c].type().order;
}
| const FEType & libMesh::DofMap::variable_type | ( | const unsigned int | c | ) | const [inline] |
c. Definition at line 1480 of file dof_map.h.
References _variables.
Referenced by libMesh::ExactSolution::_compute_error(), libMesh::UniformRefinementEstimator::_estimate_error(), libMesh::HPCoarsenTest::add_projection(), libMesh::System::calculate_norm(), libMesh::FEGenericBase< OutputType >::coarsened_dof_values(), libMesh::FEInterface::compute_constraints(), libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), libMesh::FEGenericBase< OutputType >::compute_proj_constraints(), libMesh::JumpErrorEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::MeshFunction::gradient(), libMesh::MeshFunction::hessian(), local_variable_indices(), old_dof_indices(), libMesh::WeightedPatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::PatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::MeshFunction::operator()(), libMesh::HPCoarsenTest::select_refinement(), and use_coupled_neighbor_dofs().
{
libmesh_assert_less (c, _variables.size());
return _variables[c].type();
}
friend class SparsityPattern::Build [friend] |
Definition at line 1385 of file dof_map.h.
Referenced by clear(), has_heterogenous_adjoint_constraint(), and has_heterogenous_adjoint_constraints().
std::vector<DirichletBoundaries *> libMesh::DofMap::_adjoint_dirichlet_boundaries [private] |
Function object to call to add extra entries to the send list
Definition at line 1302 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 1285 of file dof_map.h.
Referenced by attach_extra_sparsity_object().
const Parallel::Communicator& libMesh::ParallelObject::_communicator [protected, inherited] |
Definition at line 104 of file parallel_object.h.
Referenced by libMesh::EquationSystems::build_solution_vector(), libMesh::ParallelObject::comm(), libMesh::EquationSystems::get_solution(), libMesh::ParallelObject::n_processors(), libMesh::ParallelObject::operator=(), and libMesh::ParallelObject::processor_id().
ReferenceCounter::Counts libMesh::ReferenceCounter::_counts [static, protected, inherited] |
Actually holds the data.
Definition at line 118 of file reference_counter.h.
Referenced by libMesh::ReferenceCounter::get_info(), libMesh::ReferenceCounter::increment_constructor_count(), and libMesh::ReferenceCounter::increment_destructor_count().
Data structure containing Dirichlet functions. The ith entry is the constraint matrix row for boundaryid i.
Definition at line 1409 of file dof_map.h.
Referenced by get_dirichlet_boundaries(), and ~DofMap().
Data structure containing DOF constraints. The ith entry is the constraint matrix row for DOF i.
Definition at line 1381 of file dof_map.h.
Referenced by clear(), constraint_rows_begin(), constraint_rows_end(), find_connected_dofs(), is_constrained_dof(), stash_dof_constraints(), and unstash_dof_constraints().
Degree of freedom coupling. If left empty each DOF couples to all others. Can be used to reduce memory requirements for sparse matrices. DOF 0 might only couple to itself, in which case dof_coupling(0,0) should be 1 and dof_coupling(0,j) = 0 for j not equal to 0.
This variable is named as though it were class private, but it is in the public interface. Also there are no public methods for accessing it... This typically means you should only use it if you know what you are doing.
bool libMesh::ReferenceCounter::_enable_print_counter = true [static, protected, inherited] |
Flag to control whether reference count information is printed when print_info is called.
Definition at line 137 of file reference_counter.h.
Referenced by libMesh::ReferenceCounter::disable_print_counter_info(), libMesh::ReferenceCounter::enable_print_counter_info(), and libMesh::ReferenceCounter::print_info().
std::vector<dof_id_type> libMesh::DofMap::_end_df [private] |
Last DOF index (plus 1) on processor p.
Definition at line 1268 of file dof_map.h.
Referenced by clear(), distribute_dofs(), end_dof(), last_dof(), and n_dofs_on_processor().
std::vector<dof_id_type> libMesh::DofMap::_end_old_df [private] |
Last old DOF index (plus 1) on processor p.
Definition at line 1366 of file dof_map.h.
Referenced by clear(), distribute_dofs(), and end_old_dof().
void* libMesh::DofMap::_extra_send_list_context [private] |
A pointer associcated with the extra send list that can optionally be passed in
Definition at line 1312 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
Definition at line 1307 of file dof_map.h.
Referenced by attach_extra_send_list_function(), and prepare_send_list().
void* libMesh::DofMap::_extra_sparsity_context [private] |
A pointer associcated with the extra sparsity that can optionally be passed in
Definition at line 1297 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
Definition at line 1290 of file dof_map.h.
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 1263 of file dof_map.h.
Referenced by clear(), distribute_dofs(), first_dof(), and n_dofs_on_processor().
std::vector<dof_id_type> libMesh::DofMap::_first_old_df [private] |
First old DOF index on processor p.
Definition at line 1361 of file dof_map.h.
Referenced by clear(), distribute_dofs(), and first_old_dof().
std::vector<dof_id_type> libMesh::DofMap::_first_old_scalar_df [private] |
First old DOF index for SCALAR variable v, or garbage for non-SCALAR variable v
Definition at line 1372 of file dof_map.h.
Referenced by clear(), distribute_dofs(), and SCALAR_dof_indices().
std::vector<dof_id_type> libMesh::DofMap::_first_scalar_df [private] |
First DOF index for SCALAR variable v, or garbage for non-SCALAR variable v
Definition at line 1274 of file dof_map.h.
Referenced by clear(), distribute_dofs(), and SCALAR_dof_indices().
bool libMesh::DofMap::_implicit_neighbor_dofs [private] |
Definition at line 1425 of file dof_map.h.
Referenced by set_implicit_neighbor_dofs(), and use_coupled_neighbor_dofs().
bool libMesh::DofMap::_implicit_neighbor_dofs_initialized [private] |
Bools to indicate if we override the --implicit_neighbor_dofs commandline options.
Definition at line 1424 of file dof_map.h.
Referenced by set_implicit_neighbor_dofs(), and use_coupled_neighbor_dofs().
std::vector<SparseMatrix<Number>* > libMesh::DofMap::_matrices [private] |
Additional matrices handled by this object. These pointers do not handle the memory, instead, System, who told DofMap about them, owns them.
Definition at line 1258 of file dof_map.h.
Referenced by attach_matrix(), clear(), compute_sparsity(), DofMap(), and is_attached().
Threads::spin_mutex libMesh::ReferenceCounter::_mutex [static, protected, inherited] |
Mutual exclusion object to enable thread-safe reference counting.
Definition at line 131 of file reference_counter.h.
dof_id_type libMesh::DofMap::_n_dfs [private] |
Total number of degrees of freedom.
Definition at line 1343 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 1332 of file dof_map.h.
Referenced by attach_matrix(), clear_sparsity(), compute_sparsity(), and get_n_nz().
Threads::atomic< unsigned int > libMesh::ReferenceCounter::_n_objects [static, protected, inherited] |
The number of objects. Print the reference count information when the number returns to 0.
Definition at line 126 of file reference_counter.h.
Referenced by libMesh::ReferenceCounter::n_objects(), libMesh::ReferenceCounter::ReferenceCounter(), and libMesh::ReferenceCounter::~ReferenceCounter().
dof_id_type libMesh::DofMap::_n_old_dfs [private] |
Total number of degrees of freedom on old dof objects
Definition at line 1356 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 1338 of file dof_map.h.
Referenced by attach_matrix(), clear_sparsity(), compute_sparsity(), and get_n_oz().
dof_id_type libMesh::DofMap::_n_SCALAR_dofs [private] |
The total number of SCALAR dofs associated to all SCALAR variables.
Definition at line 1349 of file dof_map.h.
Referenced by distribute_local_dofs_node_major(), distribute_local_dofs_var_major(), n_SCALAR_dofs(), and reinit().
Data structure containing DofObject constraints.
Definition at line 1392 of file dof_map.h.
Referenced by is_constrained_node(), n_constrained_nodes(), node_constraint_rows_begin(), and node_constraint_rows_end().
Data structure containing periodic boundaries. The ith entry is the constraint matrix row for boundaryid i.
Definition at line 1401 of file dof_map.h.
Referenced by get_periodic_boundaries(), is_periodic_boundary(), and ~DofMap().
Definition at line 1383 of file dof_map.h.
Referenced by clear(), and get_primal_constraint_values().
std::vector<dof_id_type> libMesh::DofMap::_send_list [private] |
A list containing all the global DOF indices that affect the solution on my processor.
Definition at line 1280 of file dof_map.h.
Referenced by add_neighbors_to_send_list(), all_semilocal_indices(), clear(), distribute_dofs(), get_send_list(), and prepare_send_list().
UniquePtr<SparsityPattern::Build> libMesh::DofMap::_sp [private] |
The sparsity pattern of the global matrix, kept around if it might be needed by future additions of the same type of matrix.
Definition at line 1324 of file dof_map.h.
Referenced by attach_matrix(), clear_sparsity(), and compute_sparsity().
Definition at line 1381 of file dof_map.h.
Referenced by clear(), stash_dof_constraints(), and unstash_dof_constraints().
const unsigned int libMesh::DofMap::_sys_number [private] |
The number of the system we manage DOFs for.
Definition at line 1251 of file dof_map.h.
Referenced by sys_number().
std::vector<VariableGroup> libMesh::DofMap::_variable_groups [private] |
The finite element type for each variable.
Definition at line 1246 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 1241 of file dof_map.h.
Referenced by add_variable_group(), clear(), n_variables(), variable(), variable_order(), and variable_type().
bool libMesh::DofMap::need_full_sparsity_pattern [private] |
Default false; set to true if any attached matrix requires a full sparsity pattern.
Definition at line 1318 of file dof_map.h.
Referenced by attach_matrix(), clear(), clear_sparsity(), and compute_sparsity().