#include <base/config.h>
#include <vector>
+#include <map>
#include <utility>
#include <base/exceptions.h>
#include <base/subscriptor.h>
* In contrast to the similar function in
* the DoFAccessor class, this function
* also takes care of constraints,
- * i.e. of one of the elements of @p
+ * i.e. if one of the elements of @p
* local_dof_indices belongs to a
* constrained node, then rather than
* writing the corresponding element of
* the condense function after the
* vectors and matrices are fully
* assembled.
+ *
+ * In order to do its work
+ * properly, this function has to
+ * know which degrees of freedom
+ * are fixed, for example
+ * boundary values. For this, the
+ * third argument is a map
+ * between the numbers of the
+ * DoFs that are fixed and the
+ * values they are fixed to. One
+ * can pass an empty map in for
+ * this argument, but note that
+ * you will then have to fix
+ * these nodes later on again,
+ * for example by using
+ * MatrixTools::apply_boundary_values
+ * to the resulting
+ * matrix. However, since the
+ * present function was written
+ * for the express purpose of not
+ * having to use tools that later
+ * modify the matrix, it is
+ * advisable to have the list of
+ * fixed nodes available when
+ * calling the present function.
*/
template <typename VectorType>
void
distribute_local_to_global (const Vector<double> &local_vector,
const std::vector<unsigned int> &local_dof_indices,
+ const std::map<unsigned int, double> &fixed_dofs,
VectorType &global_vector) const;
/**
* In contrast to the similar function in
* the DoFAccessor class, this function
* also takes care of constraints,
- * i.e. of one of the elements of @p
+ * i.e. if one of the elements of @p
* local_dof_indices belongs to a
* constrained node, then rather than
* writing the corresponding element of
* the condense function after the
* vectors and matrices are fully
* assembled.
+ *
+ * In order to do its work
+ * properly, this function has to
+ * know which degrees of freedom
+ * are fixed, for example
+ * boundary values. For this, the
+ * third argument is a map
+ * between the numbers of the
+ * DoFs that are fixed and the
+ * values they are fixed to. One
+ * can pass an empty map in for
+ * this argument, but note that
+ * you will then have to fix
+ * these nodes later on again,
+ * for example by using
+ * MatrixTools::apply_boundary_values
+ * to the resulting
+ * matrix. However, since the
+ * present function was written
+ * for the express purpose of not
+ * having to use tools that later
+ * modify the matrix, it is
+ * advisable to have the list of
+ * fixed nodes available when
+ * calling the present function.
*/
template <typename MatrixType>
void
distribute_local_to_global (const FullMatrix<double> &local_matrix,
const std::vector<unsigned int> &local_dof_indices,
+ const std::map<unsigned int, double> &fixed_dofs,
MatrixType &global_matrix) const;
/**
+#define is_fixed(i) (fixed_dofs.find(i) != fixed_dofs.end())
+//#define is_fixed(i) false
+
template <typename VectorType>
void
ConstraintMatrix::
distribute_local_to_global (const Vector<double> &local_vector,
const std::vector<unsigned int> &local_dof_indices,
+ const std::map<unsigned int, double> &fixed_dofs,
VectorType &global_vector) const
{
Assert (local_vector.size() == local_dof_indices.size(),
lines.end(),
index_comparison);
- // if the line is not constrained,
- // then simply copy the
- // data. otherwise distribute it
+ // if the line is not
+ // constrained, then simply
+ // copy the data. otherwise
+ // distribute it, but make
+ // sure we don't touch the
+ // entries of fixed dofs
if (position->line != local_dof_indices[i])
global_vector(local_dof_indices[i]) += local_vector(i);
else
for (unsigned int j=0; j<position->entries.size(); ++j)
- global_vector(position->entries[j].first)
- += local_vector(i) * position->entries[j].second;
+ if (!is_fixed(position->entries[j].first))
+ global_vector(position->entries[j].first)
+ += local_vector(i) * position->entries[j].second;
}
}
}
ConstraintMatrix::
distribute_local_to_global (const FullMatrix<double> &local_matrix,
const std::vector<unsigned int> &local_dof_indices,
+ const std::map<unsigned int, double> &fixed_dofs,
MatrixType &global_matrix) const
{
Assert (local_matrix.n() == local_dof_indices.size(),
// ok, row is constrained,
// but column is not
for (unsigned int q=0; q<position_i->entries.size(); ++q)
- global_matrix.add (position_i->entries[q].first,
- local_dof_indices[j],
- local_matrix(i,j) *
- position_i->entries[q].second);
+ if (!is_fixed(position_i->entries[q].first))
+ global_matrix.add (position_i->entries[q].first,
+ local_dof_indices[j],
+ local_matrix(i,j) *
+ position_i->entries[q].second);
}
else if ((is_constrained_i == false) &&
(is_constrained_j == true))
// round: row ok, column is
// constrained
for (unsigned int q=0; q<position_j->entries.size(); ++q)
- global_matrix.add (local_dof_indices[i],
- position_j->entries[q].first,
- local_matrix(i,j) *
- position_j->entries[q].second);
+ if (!is_fixed(position_j->entries[q].first))
+ global_matrix.add (local_dof_indices[i],
+ position_j->entries[q].first,
+ local_matrix(i,j) *
+ position_j->entries[q].second);
}
else if ((is_constrained_i == true) &&
(is_constrained_j == true))
// last case: both row and
// column are constrained
for (unsigned int p=0; p<position_i->entries.size(); ++p)
- for (unsigned int q=0; q<position_j->entries.size(); ++q)
- global_matrix.add (position_i->entries[p].first,
- position_j->entries[q].first,
- local_matrix(i,j) *
- position_i->entries[p].second *
- position_j->entries[q].second);
+ if (!is_fixed(position_i->entries[p].first))
+ for (unsigned int q=0; q<position_j->entries.size(); ++q)
+ if (!is_fixed(position_j->entries[q].first))
+ global_matrix.add (position_i->entries[p].first,
+ position_j->entries[q].first,
+ local_matrix(i,j) *
+ position_i->entries[p].second *
+ position_j->entries[q].second);
// to make sure that the
// global matrix remains
template void ConstraintMatrix:: \
distribute_local_to_global<VectorType > (const Vector<double> &, \
const std::vector<unsigned int> &, \
+ const std::map<unsigned int, double> &, \
VectorType &) const; \
template void ConstraintMatrix::distribute<VectorType >(const VectorType &condensed,\
VectorType &uncondensed) const;\
template void ConstraintMatrix:: \
distribute_local_to_global<MatrixType > (const FullMatrix<double> &, \
const std::vector<unsigned int> &, \
+ const std::map<unsigned int, double> &, \
MatrixType &) const
MATRIX_FUNCTIONS(SparseMatrix<double>);
A.add (local_dofs[i], local_dofs[j], local_matrix(i,j));
// or let other functions do that
- constraints.distribute_local_to_global (local_matrix, local_dofs, B);
+ constraints.distribute_local_to_global (local_matrix, local_dofs,
+ std::map<unsigned int,double>(), B);
}
// now condense away constraints from A
A(local_dofs[i]) += local_vector(i);
// or let other functions do that
- constraints.distribute_local_to_global (local_vector, local_dofs, B);
+ constraints.distribute_local_to_global (local_vector, local_dofs,
+ std::map<unsigned int,double>(), B);
}
// now condense away constraints from A