const Vector<Number, MemorySpace> &V,
const Vector<Number, MemorySpace> &W);
+ /**
+ * Assert that there are no spurious non-zero entries in the ghost
+ * region of the vector caused by some forgotten compress() or
+ * zero_out_ghost_values() calls, which is an invariant of the vector
+ * space operations such as the addition of vectors, scaling a vector,
+ * and similar.
+ */
+ void
+ assert_no_residual_content_in_ghost_region() const;
+
/**
* Shared pointer to store the parallel partitioning information. This
* information can be shared between several vectors that have the same
if (vector_is_ghosted)
update_ghost_values();
+ else
+ assert_no_residual_content_in_ghost_region();
return *this;
}
if (vector_is_ghosted)
update_ghost_values();
+ else
+ assert_no_residual_content_in_ghost_region();
return *this;
}
if (vector_is_ghosted)
update_ghost_values();
+ else
+ assert_no_residual_content_in_ghost_region();
}
if (vector_is_ghosted)
update_ghost_values();
+ else
+ assert_no_residual_content_in_ghost_region();
}
if (vector_is_ghosted)
update_ghost_values();
+ else
+ assert_no_residual_content_in_ghost_region();
}
if (vector_is_ghosted)
update_ghost_values();
+ else
+ assert_no_residual_content_in_ghost_region();
}
if (vector_is_ghosted)
update_ghost_values();
+ else
+ assert_no_residual_content_in_ghost_region();
}
if (vector_is_ghosted)
update_ghost_values();
+ else
+ assert_no_residual_content_in_ghost_region();
return *this;
}
if (vector_is_ghosted)
update_ghost_values();
+ else
+ assert_no_residual_content_in_ghost_region();
}
if (vector_is_ghosted)
update_ghost_values();
+ else
+ assert_no_residual_content_in_ghost_region();
+ }
+
+
+
+ template <typename Number, typename MemorySpaceType>
+ void
+ Vector<Number,
+ MemorySpaceType>::assert_no_residual_content_in_ghost_region() const
+ {
+#ifdef DEBUG
+ // This should only be called for non-ghosted vectors
+ Assert(!vector_is_ghosted, ExcInternalError());
+
+ // Run a reduction over the ghost range only to find out whether some
+ // entries are non-zero
+ real_type sum = real_type();
+ dealii::internal::VectorOperations::
+ functions<Number, Number, MemorySpaceType>::norm_1(
+ thread_loop_partitioner,
+ partitioner->n_ghost_indices(),
+ sum,
+ data,
+ partitioner->locally_owned_size());
+
+ Assert(sum == real_type(),
+ ExcMessage("You called a vector space operation like add(), "
+ "scale(), operator* for a non-ghosted vector, which "
+ "will not update the content in the memory locations "
+ "reserved for ghost values. However, a non-zero "
+ "content was detected for some of those entries, which "
+ "can lead to an invalid state of the vector. Please "
+ "call Vector::compress(VectorOperation::add) or "
+ "Vector::zero_out_ghost_values() before calling a "
+ "vector space operation to avoid this problem."));
+#endif
}
real_type &sum,
::dealii::MemorySpace::MemorySpaceData<Number,
::dealii::MemorySpace::Host>
- &data)
+ &data,
+ const size_type optional_offset = 0)
{
Norm1<Number, real_type> norm1(data.values.data());
- parallel_reduce(norm1, 0, size, sum, thread_loop_partitioner);
+ parallel_reduce(norm1,
+ optional_offset,
+ optional_offset + size,
+ sum,
+ thread_loop_partitioner);
}
template <typename real_type>
real_type &sum,
::dealii::MemorySpace::MemorySpaceData<Number,
::dealii::MemorySpace::Default>
- &data)
+ &data,
+ const size_type optional_offset = 0)
{
auto exec = typename ::dealii::MemorySpace::Default::kokkos_space::
execution_space{};
"dealii::norm_1",
Kokkos::RangePolicy<
::dealii::MemorySpace::Default::kokkos_space::execution_space>(
- exec, 0, size),
+ exec, optional_offset, optional_offset + size),
KOKKOS_LAMBDA(size_type i, Number & update) {
#if KOKKOS_VERSION < 30400
update += std::abs(data.values(i));