(Martin Kronbichler, 2013/05/14)
</li>
- <li> Fixed: setting values in TrilinosWrappers::SparseMatrix
- in parallel was adding the values instead.
- <br>
- (Bruno Turcksin, Timo Heister, 2013/05/03)
- </li>
-
<li> New: The step-49 tutorial program now also has a discussion on
what to do once you have a coarse mesh and want to refine it.
<br>
<h3>Specific improvements</h3>
<ol>
+<li> New: All vector classes now have a static member variable
+<code>supports_distributed_data</code> that indicates whether the
+vector class supports data that is distributed across multiple
+processors. This variable is provided as a <i>traits variable</i>
+to allow generic algorithms working on general vector types to
+query the capabilities of the vector class at compile time.
+<br>
+(Wolfgang Bangerth, 2013/05/23)
+</li>
<li> Fixed: FETools::back_interpolate has been revised to work correctly
also with parallel::distributed::Vector.
(Wolfgang Bangerth, 2013/05/06)
</li>
+<li> Fixed: setting values in TrilinosWrappers::SparseMatrix
+in parallel was adding the values instead.
+<br>
+(Bruno Turcksin, Timo Heister, 2013/05/03)
+</li>
+
<li> Fixed: Generate an error if the user tries to refine a cell
that is already on the maximum level in a distributed triangulation.
<br>
*/
typedef typename BlockType::real_type real_type;
+ /**
+ * A variable that indicates whether this vector
+ * supports distributed data storage. If true, then
+ * this vector also needs an appropriate compress()
+ * function that allows communicating recent set or
+ * add operations to individual elements to be communicated
+ * to other processors.
+ *
+ * For the current class, the variable equals the
+ * value declared for the type of the individual blocks.
+ */
+ static const bool supports_distributed_data = BlockType::supports_distributed_data;
+
/**
* Default constructor.
*/
typedef size_t size_type;
typedef typename numbers::NumberTraits<Number>::real_type real_type;
+ /**
+ * A variable that indicates whether this vector
+ * supports distributed data storage. If true, then
+ * this vector also needs an appropriate compress()
+ * function that allows communicating recent set or
+ * add operations to individual elements to be communicated
+ * to other processors.
+ *
+ * For the current class, the variable equals
+ * true, since it does support parallel data storage.
+ */
+ static const bool supports_distributed_data = true;
+
/**
* @name 1: Basic Object-handling
*/
{
public:
/**
+ * A variable that indicates whether this vector
+ * supports distributed data storage. If true, then
+ * this vector also needs an appropriate compress()
+ * function that allows communicating recent set or
+ * add operations to individual elements to be communicated
+ * to other processors.
+ *
+ * For the current class, the variable equals
+ * true, since it does support parallel data storage.
+ */
+ static const bool supports_distributed_data = true;
+
+ /**
* Default constructor. Initialize the
* vector as empty.
*/
class Vector : public VectorBase
{
public:
+ /**
+ * A variable that indicates whether this vector
+ * supports distributed data storage. If true, then
+ * this vector also needs an appropriate compress()
+ * function that allows communicating recent set or
+ * add operations to individual elements to be communicated
+ * to other processors.
+ *
+ * For the current class, the variable equals
+ * false, since it does not support parallel data storage.
+ * If you do need parallel data storage, use
+ * PETScWrappers::MPI::Vector.
+ */
+ static const bool supports_distributed_data = false;
+
/**
* Default constructor. Initialize the
* vector as empty.
class Vector : public VectorBase
{
public:
+ /**
+ * A variable that indicates whether this vector
+ * supports distributed data storage. If true, then
+ * this vector also needs an appropriate compress()
+ * function that allows communicating recent set or
+ * add operations to individual elements to be communicated
+ * to other processors.
+ *
+ * For the current class, the variable equals
+ * true, since it does support parallel data storage.
+ */
+ static const bool supports_distributed_data = true;
+
/**
* @name Basic constructors and initalization.
*/
-//@{
+ //@{
/**
* Default constructor that
* generates an empty (zero size)
class Vector : public VectorBase
{
public:
+ /**
+ * A variable that indicates whether this vector
+ * supports distributed data storage. If true, then
+ * this vector also needs an appropriate compress()
+ * function that allows communicating recent set or
+ * add operations to individual elements to be communicated
+ * to other processors.
+ *
+ * For the current class, the variable equals
+ * false, since it does not support parallel data storage.
+ * If you do need parallel data storage, use
+ * TrilinosWrappers::MPI::Vector.
+ */
+ static const bool supports_distributed_data = false;
+
/**
* Default constructor that
* generates an empty (zero size)
*/
typedef typename numbers::NumberTraits<Number>::real_type real_type;
+ /**
+ * A variable that indicates whether this vector
+ * supports distributed data storage. If true, then
+ * this vector also needs an appropriate compress()
+ * function that allows communicating recent set or
+ * add operations to individual elements to be communicated
+ * to other processors.
+ *
+ * For the current class, the variable equals
+ * false, since it does not support parallel data storage.
+ */
+ static const bool supports_distributed_data = false;
+
public:
/**
typedef std::vector<ConstraintLine>::const_iterator constraint_iterator;
#ifdef DEBUG
- // the algorithm below pushes contributions c_ij x_j to a constrained
- // DoF x_j *from the side of the owner of x_j*, as opposed to pulling
- // it from the owner of the target side x_i. this relies on the
- // assumption that both target and source know about the constraint
- // on x_i.
- //
- // the disadvantage is that it is incredibly difficult to find out what
- // is happening if the assumption is not satisfied. to help debug
- // problems of this kind, we do the following in a first step if
- // debugging is enabled:
- // - every processor who owns an x_j where c_ij!=0 sends a one
- // to the owner of x_i to add up
- // - the owner of x_i knows how many nonzero entries exist, so can
- // verify that the correct number of ones has been added
- // - if the sum is not correct, then apparently one of the owners
- // of the x_j's did not know to send its one and, consequently,
- // will also not know to send the correct c_ij*x_j later on,
- // leading to a bug
- set_zero (vec);
- for (constraint_iterator it = lines.begin();
- it != lines.end(); ++it)
- for (unsigned int i=0; i<it->entries.size(); ++i)
- if (vec_owned_elements.is_element (it->entries[i].first))
- vec(it->line) += 1;
- vec.compress (VectorOperation::add);
-
- for (constraint_iterator it = lines.begin();
- it != lines.end(); ++it)
- if (vec_owned_elements.is_element(it->line))
- Assert (vec(it->line) == it->entries.size(),
+ if (vec.supports_distributed_data == true)
+ {
+ // the algorithm below pushes contributions c_ij x_j to a constrained
+ // DoF x_j *from the side of the owner of x_j*, as opposed to pulling
+ // it from the owner of the target side x_i. this relies on the
+ // assumption that both target and source know about the constraint
+ // on x_i.
+ //
+ // the disadvantage is that it is incredibly difficult to find out what
+ // is happening if the assumption is not satisfied. to help debug
+ // problems of this kind, we do the following in a first step if
+ // debugging is enabled:
+ // - every processor who owns an x_j where c_ij!=0 sends a one
+ // to the owner of x_i to add up
+ // - the owner of x_i knows how many nonzero entries exist, so can
+ // verify that the correct number of ones has been added
+ // - if the sum is not correct, then apparently one of the owners
+ // of the x_j's did not know to send its one and, consequently,
+ // will also not know to send the correct c_ij*x_j later on,
+ // leading to a bug
+ set_zero (vec);
+ for (constraint_iterator it = lines.begin();
+ it != lines.end(); ++it)
+ for (unsigned int i=0; i<it->entries.size(); ++i)
+ if (vec_owned_elements.is_element (it->entries[i].first))
+ vec(it->line) += 1;
+ vec.compress (VectorOperation::add);
+
+ for (constraint_iterator it = lines.begin();
+ it != lines.end(); ++it)
+ if (vec_owned_elements.is_element(it->line))
+ Assert (vec(it->line) == it->entries.size(),
ExcIncorrectConstraint(it->line, it->entries.size()));
+ }
#endif
// set the values of all constrained DoFs to zero, then add the