* sums them into the vector @p dst. The function also applies constraints
* during the write operation. The functionality is hence similar to the
* function AffineConstraints::distribute_local_to_global. If vectorization
- * is enabled, the DoF values for several cells are used.
+ * is enabled, the DoF values for several cells are used. The mask can be
+ * used to suppress the write access for some of the vectorized cells, e.g.
+ * in case of local time stepping, where some cells are excluded from a
+ * call. A value of `true` in the bitset means that the respective lane
+ * index will be processed, whereas a value of `false` skips this index.
*
* If this class was constructed without a MatrixFree object and the
* information is acquired on the fly through a
*/
template <typename VectorType>
void
- distribute_local_to_global(VectorType & dst,
- const unsigned int first_index = 0) const;
+ distribute_local_to_global(
+ VectorType & dst,
+ const unsigned int first_index = 0,
+ const std::bitset<VectorizedArray<Number>::n_array_elements> mask =
+ std::bitset<VectorizedArray<Number>::n_array_elements>().flip()) const;
/**
* Takes the values stored internally on dof values of the current cell and
* by the current cell are overwritten. Thus, if a degree of freedom is
* associated to more than one cell (as usual in continuous finite
* elements), the values will be overwritten and only the value written last
- * is retained.
+ * is retained. The mask can be used to suppress the write access for some
+ * of the vectorized cells, e.g. in case of local time stepping, where some
+ * cells are excluded from a call. A value of `true` in the bitset means
+ * that the respective lane index will be processed, whereas a value of
+ * `false` skips this index.
*
* If this class was constructed without a MatrixFree object and the
* information is acquired on the fly through a
*/
template <typename VectorType>
void
- set_dof_values(VectorType &dst, const unsigned int first_index = 0) const;
+ set_dof_values(
+ VectorType & dst,
+ const unsigned int first_index = 0,
+ const std::bitset<VectorizedArray<Number>::n_array_elements> mask =
+ std::bitset<VectorizedArray<Number>::n_array_elements>().flip()) const;
//@}
*/
template <typename VectorType, typename VectorOperation>
void
- read_write_operation(const VectorOperation &operation,
- VectorType * vectors[],
- const bool apply_constraints = true) const;
+ read_write_operation(
+ const VectorOperation & operation,
+ VectorType * vectors[],
+ const std::bitset<VectorizedArray<Number>::n_array_elements> mask,
+ const bool apply_constraints = true) const;
/**
* A unified function to read from and write into vectors based on the given
*/
template <typename VectorType, typename VectorOperation>
void
- read_write_operation_contiguous(const VectorOperation &operation,
- VectorType * vectors[]) const;
+ read_write_operation_contiguous(
+ const VectorOperation & operation,
+ VectorType * vectors[],
+ const std::bitset<VectorizedArray<Number>::n_array_elements> mask) const;
/**
* A unified function to read from and write into vectors based on the given
template <typename VectorType, typename VectorOperation>
inline void
FEEvaluationBase<dim, n_components_, Number, is_face>::read_write_operation(
- const VectorOperation &operation,
- VectorType * src[],
- const bool apply_constraints) const
+ const VectorOperation & operation,
+ VectorType * src[],
+ const std::bitset<VectorizedArray<Number>::n_array_elements> mask,
+ const bool apply_constraints) const
{
// Case 1: No MatrixFree object given, simple case because we do not need to
// process constraints and need not care about vectorization -> go to
[cell] >=
internal::MatrixFreeFunctions::DoFInfo::IndexStorageVariants::contiguous)
{
- read_write_operation_contiguous(operation, src);
+ read_write_operation_contiguous(operation, src, mask);
return;
}
constexpr unsigned int n_vectorization =
VectorizedArray<Number>::n_array_elements;
+ Assert(mask.count() == n_vectorization,
+ ExcNotImplemented("Masking currently not implemented for "
+ "non-contiguous DoF storage"));
const unsigned int dofs_per_component =
this->data->dofs_per_component_on_cell;
if (dof_info->index_storage_variants
template <typename VectorType, typename VectorOperation>
inline void
FEEvaluationBase<dim, n_components_, Number, is_face>::
- read_write_operation_contiguous(const VectorOperation &operation,
- VectorType * src[]) const
+ read_write_operation_contiguous(
+ const VectorOperation & operation,
+ VectorType * src[],
+ const std::bitset<VectorizedArray<Number>::n_array_elements> mask) const
{
// This functions processes the functions read_dof_values,
// distribute_local_to_global, and set_dof_values with the same code for
const internal::MatrixFreeFunctions::DoFInfo::DoFAccessIndex ind =
is_face ? dof_access_index :
internal::MatrixFreeFunctions::DoFInfo::dof_access_cell;
+ const unsigned int n_lanes = mask.count();
const std::vector<unsigned int> &dof_indices_cont =
dof_info->dof_indices_contiguous[ind];
// Simple case: We have contiguous storage, so we can simply copy out the
// data
if (dof_info->index_storage_variants[ind][cell] ==
- internal::MatrixFreeFunctions::DoFInfo::IndexStorageVariants::
- interleaved_contiguous)
+ internal::MatrixFreeFunctions::DoFInfo::IndexStorageVariants::
+ interleaved_contiguous &&
+ n_lanes == VectorizedArray<Number>::n_array_elements)
{
const unsigned int dof_index =
dof_indices_cont[cell * VectorizedArray<Number>::n_array_elements] +
// some transformations
const unsigned int vectorization_populated =
dof_info->n_vectorization_lanes_filled[ind][this->cell];
+
unsigned int dof_indices[VectorizedArray<Number>::n_array_elements];
for (unsigned int v = 0; v < vectorization_populated; ++v)
dof_indices[v] =
[first_selected_component] *
dof_info->dof_indices_interleave_strides
[ind][cell * VectorizedArray<Number>::n_array_elements + v];
+
for (unsigned int v = vectorization_populated;
v < VectorizedArray<Number>::n_array_elements;
++v)
// In the case with contiguous cell indices, we know that there are no
// constraints and that the indices within each element are contiguous
- if (vectorization_populated == VectorizedArray<Number>::n_array_elements)
+ if (vectorization_populated == VectorizedArray<Number>::n_array_elements &&
+ n_lanes == VectorizedArray<Number>::n_array_elements)
{
if (dof_info->index_storage_variants[ind][cell] ==
internal::MatrixFreeFunctions::DoFInfo::IndexStorageVariants::
{
if (n_components == 1 || n_fe_components == 1)
for (unsigned int v = 0; v < vectorization_populated; ++v)
- for (unsigned int i = 0; i < data->dofs_per_component_on_cell;
- ++i)
- operation.process_dof(dof_indices[v] + i,
- *src[comp],
- values_dofs[comp][i][v]);
- else
- for (unsigned int v = 0; v < vectorization_populated; ++v)
- for (unsigned int i = 0; i < data->dofs_per_component_on_cell;
- ++i)
- operation.process_dof(dof_indices[v] + i +
- comp *
- data->dofs_per_component_on_cell,
- *src[0],
- values_dofs[comp][i][v]);
+ if (mask[v] == true)
+ for (unsigned int i = 0; i < data->dofs_per_component_on_cell;
+ ++i)
+ operation.process_dof(dof_indices[v] + i,
+ *src[comp],
+ values_dofs[comp][i][v]);
+ else
+ for (unsigned int v = 0; v < vectorization_populated; ++v)
+ if (mask[v] == true)
+ for (unsigned int i = 0;
+ i < data->dofs_per_component_on_cell;
+ ++i)
+ operation.process_dof(
+ dof_indices[v] + i +
+ comp * data->dofs_per_component_on_cell,
+ *src[0],
+ values_dofs[comp][i][v]);
}
else
{
VectorizedArray<Number>::n_array_elements + 1);
if (n_components == 1 || n_fe_components == 1)
for (unsigned int v = 0; v < vectorization_populated; ++v)
- for (unsigned int i = 0; i < data->dofs_per_component_on_cell;
- ++i)
- operation.process_dof(dof_indices[v] + i * offsets[v],
- *src[comp],
- values_dofs[comp][i][v]);
- else
- for (unsigned int v = 0; v < vectorization_populated; ++v)
- for (unsigned int i = 0; i < data->dofs_per_component_on_cell;
- ++i)
- operation.process_dof(
- dof_indices[v] +
- (i + comp * data->dofs_per_component_on_cell) *
- offsets[v],
- *src[0],
- values_dofs[comp][i][v]);
+ if (mask[v] == true)
+ for (unsigned int i = 0; i < data->dofs_per_component_on_cell;
+ ++i)
+ operation.process_dof(dof_indices[v] + i * offsets[v],
+ *src[comp],
+ values_dofs[comp][i][v]);
+ else
+ for (unsigned int v = 0; v < vectorization_populated; ++v)
+ if (mask[v] == true)
+ for (unsigned int i = 0;
+ i < data->dofs_per_component_on_cell;
+ ++i)
+ operation.process_dof(
+ dof_indices[v] +
+ (i + comp * data->dofs_per_component_on_cell) *
+ offsets[v],
+ *src[0],
+ values_dofs[comp][i][v]);
}
}
}
get_vector_component(const_cast<VectorType &>(src), d + first_index);
internal::VectorReader<Number> reader;
- read_write_operation(reader, src_data, true);
+ read_write_operation(
+ reader,
+ src_data,
+ std::bitset<VectorizedArray<Number>::n_array_elements>().flip(),
+ true);
# ifdef DEBUG
dof_values_initialized = true;
get_vector_component(const_cast<VectorType &>(src), d + first_index);
internal::VectorReader<Number> reader;
- read_write_operation(reader, src_data, false);
+ read_write_operation(
+ reader,
+ src_data,
+ std::bitset<VectorizedArray<Number>::n_array_elements>().flip(),
+ false);
# ifdef DEBUG
dof_values_initialized = true;
template <typename VectorType>
inline void
FEEvaluationBase<dim, n_components_, Number, is_face>::
- distribute_local_to_global(VectorType & dst,
- const unsigned int first_index) const
+ distribute_local_to_global(
+ VectorType & dst,
+ const unsigned int first_index,
+ const std::bitset<VectorizedArray<Number>::n_array_elements> mask) const
{
Assert(dof_values_initialized == true,
internal::ExcAccessToUninitializedField());
d + first_index);
internal::VectorDistributorLocalToGlobal<Number> distributor;
- read_write_operation(distributor, dst_data);
+ read_write_operation(distributor, dst_data, mask);
}
template <typename VectorType>
inline void
FEEvaluationBase<dim, n_components_, Number, is_face>::set_dof_values(
- VectorType & dst,
- const unsigned int first_index) const
+ VectorType & dst,
+ const unsigned int first_index,
+ const std::bitset<VectorizedArray<Number>::n_array_elements> mask) const
{
Assert(dof_values_initialized == true,
internal::ExcAccessToUninitializedField());
d + first_index);
internal::VectorSetter<Number> setter;
- read_write_operation(setter, dst_data);
+ read_write_operation(setter, dst_data, mask);
}