17 #ifndef dealii_matrix_free_operators_h
18 #define dealii_matrix_free_operators_h
46 template <
typename VectorType>
51 return vector.n_blocks();
54 template <
typename VectorType>
62 template <
typename VectorType>
64 typename VectorType::BlockType &>::type
67 return vector.block(block_no);
70 template <
typename VectorType>
72 const typename VectorType::BlockType &>::type
76 return vector.block(block_no);
79 template <
typename VectorType>
87 template <
typename VectorType>
95 template <
typename VectorType>
99 vector.collect_sizes();
102 template <
typename VectorType>
189 typename VectorizedArrayType =
212 virtual ~Base()
override =
default;
240 const std::vector<unsigned int> &selected_row_blocks =
241 std::vector<unsigned int>(),
242 const std::vector<unsigned int> &selected_column_blocks =
243 std::vector<unsigned int>());
262 const unsigned int level,
263 const std::vector<unsigned int> &selected_row_blocks =
264 std::vector<unsigned int>());
283 const std::vector<MGConstrainedDoFs> &mg_constrained_dofs,
284 const unsigned int level,
285 const std::vector<unsigned int> & selected_row_blocks =
286 std::vector<unsigned int>());
341 el(
const unsigned int row,
const unsigned int col)
const;
369 std::shared_ptr<const MatrixFree<dim, value_type, VectorizedArrayType>>
375 const std::shared_ptr<DiagonalMatrix<VectorType>> &
381 const std::shared_ptr<DiagonalMatrix<VectorType>> &
434 std::shared_ptr<const MatrixFree<dim, value_type, VectorizedArrayType>>
470 mutable std::vector<std::vector<std::pair<value_type, value_type>>>
497 const bool is_row)
const;
538 template <
typename OperatorType>
572 template <
typename VectorType>
579 template <
typename VectorType>
586 template <
typename VectorType>
628 "Type of Number and of VectorizedArrayType do not match.");
640 VectorizedArrayType> &
fe_eval);
652 const unsigned int n_actual_components,
653 const VectorizedArrayType * in_array,
654 VectorizedArrayType * out_array)
const;
668 apply(
const VectorizedArrayType *in_array,
669 VectorizedArrayType * out_array)
const;
706 const VectorizedArrayType *in_array,
707 VectorizedArrayType *out_array)
const;
742 int n_q_points_1d = fe_degree + 1,
745 typename VectorizedArrayType =
791 const std::pair<unsigned int, unsigned int> & cell_range)
const;
810 int n_q_points_1d = fe_degree + 1,
813 typename VectorizedArrayType =
911 std::shared_ptr<Table<2, VectorizedArrayType>>
931 const std::pair<unsigned int, unsigned int> & cell_range)
const;
941 const std::pair<unsigned int, unsigned int> &cell_range)
const;
950 const unsigned int cell)
const;
966 typename VectorizedArrayType>
971 VectorizedArrayType>::
972 CellwiseInverseMassMatrix(
977 VectorizedArrayType> &fe_eval)
987 typename VectorizedArrayType>
993 VectorizedArrayType>::
994 fill_inverse_JxW_values(
997 constexpr
unsigned int dofs_per_component_on_cell =
1000 inverse_jxw.
size() % dofs_per_component_on_cell == 0,
1002 "Expected diagonal to be a multiple of scalar dof per cells"));
1006 for (
unsigned int q = 0; q < dofs_per_component_on_cell; ++q)
1007 inverse_jxw[q] = 1. / fe_eval.JxW(q);
1009 for (
unsigned int q = dofs_per_component_on_cell; q < inverse_jxw.
size();)
1010 for (
unsigned int i = 0; i < dofs_per_component_on_cell; ++i, ++q)
1011 inverse_jxw[q] = inverse_jxw[i];
1020 typename VectorizedArrayType>
1027 VectorizedArrayType>
::apply(
const VectorizedArrayType *in_array,
1028 VectorizedArrayType * out_array)
const
1034 VectorizedArrayType>
::apply(fe_eval, in_array, out_array);
1043 typename VectorizedArrayType>
1049 VectorizedArrayType>
::
1051 const unsigned int n_actual_components,
1052 const VectorizedArrayType * in_array,
1053 VectorizedArrayType * out_array)
const
1058 VectorizedArrayType>
::
1059 apply(fe_eval.get_shape_info().data.front().inverse_shape_values_eo,
1060 inverse_coefficients,
1061 n_actual_components,
1072 typename VectorizedArrayType>
1078 VectorizedArrayType>::
1079 transform_from_q_points_to_basis(
const unsigned int n_actual_components,
1080 const VectorizedArrayType *in_array,
1081 VectorizedArrayType * out_array)
const
1086 VectorizedArrayType>::
1087 transform_from_q_points_to_basis(
1088 fe_eval.get_shape_info().data.front().inverse_shape_values_eo,
1089 n_actual_components,
1097 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1100 , have_interface_matrices(false)
1105 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1112 for (
const unsigned int selected_row : selected_rows)
1113 total_size += data->get_vector_partitioner(selected_row)->size();
1119 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1126 for (
const unsigned int selected_column : selected_columns)
1127 total_size += data->get_vector_partitioner(selected_column)->size();
1133 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1138 inverse_diagonal_entries.reset();
1143 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1146 const unsigned int col)
const
1150 Assert(inverse_diagonal_entries.get() !=
nullptr &&
1151 inverse_diagonal_entries->m() > 0,
1153 return 1.0 / (*inverse_diagonal_entries)(row, row);
1158 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1167 const unsigned int index = selected_rows[i];
1169 .partitioners_are_compatible(
1170 *data->get_dof_info(index).vector_partitioner))
1174 .partitioners_are_globally_compatible(
1175 *data->get_dof_info(index).vector_partitioner),
1183 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1188 const std::vector<unsigned int> &given_row_selection,
1189 const std::vector<unsigned int> &given_column_selection)
1193 selected_rows.
clear();
1194 selected_columns.clear();
1195 if (given_row_selection.empty())
1196 for (
unsigned int i = 0; i < data_->n_components(); ++i)
1197 selected_rows.push_back(i);
1200 for (
unsigned int i = 0; i < given_row_selection.size(); ++i)
1203 for (
unsigned int j = 0; j < given_row_selection.size(); ++j)
1205 Assert(given_row_selection[j] != given_row_selection[i],
1206 ExcMessage(
"Given row indices must be unique"));
1208 selected_rows.push_back(given_row_selection[i]);
1211 if (given_column_selection.size() == 0)
1212 selected_columns = selected_rows;
1215 for (
unsigned int i = 0; i < given_column_selection.size(); ++i)
1218 for (
unsigned int j = 0; j < given_column_selection.size(); ++j)
1220 Assert(given_column_selection[j] != given_column_selection[i],
1221 ExcMessage(
"Given column indices must be unique"));
1223 selected_columns.push_back(given_column_selection[i]);
1227 edge_constrained_indices.clear();
1228 edge_constrained_indices.resize(selected_rows.size());
1229 edge_constrained_values.clear();
1230 edge_constrained_values.resize(selected_rows.size());
1231 have_interface_matrices =
false;
1236 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1242 const unsigned int level,
1243 const std::vector<unsigned int> &given_row_selection)
1245 std::vector<MGConstrainedDoFs> mg_constrained_dofs_vector(
1246 1, mg_constrained_dofs);
1247 initialize(data_, mg_constrained_dofs_vector,
level, given_row_selection);
1252 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1257 const std::vector<MGConstrainedDoFs> &mg_constrained_dofs,
1258 const unsigned int level,
1259 const std::vector<unsigned int> & given_row_selection)
1264 selected_rows.clear();
1265 selected_columns.clear();
1266 if (given_row_selection.empty())
1267 for (
unsigned int i = 0; i < data_->n_components(); ++i)
1268 selected_rows.push_back(i);
1271 for (
unsigned int i = 0; i < given_row_selection.size(); ++i)
1274 for (
unsigned int j = 0; j < given_row_selection.size(); ++j)
1276 Assert(given_row_selection[j] != given_row_selection[i],
1277 ExcMessage(
"Given row indices must be unique"));
1279 selected_rows.push_back(given_row_selection[i]);
1282 selected_columns = selected_rows;
1285 edge_constrained_indices.clear();
1286 edge_constrained_indices.resize(selected_rows.size());
1287 edge_constrained_values.clear();
1288 edge_constrained_values.resize(selected_rows.size());
1292 for (
unsigned int j = 0; j < selected_rows.size(); ++j)
1294 if (data_->n_macro_cells() > 0)
1300 std::vector<types::global_dof_index> interface_indices;
1301 mg_constrained_dofs[j]
1302 .get_refinement_edge_indices(
level)
1303 .fill_index_vector(interface_indices);
1304 edge_constrained_indices[j].clear();
1305 edge_constrained_indices[j].reserve(interface_indices.size());
1306 edge_constrained_values[j].resize(interface_indices.size());
1308 data->get_dof_handler(selected_rows[j]).locally_owned_mg_dofs(
level);
1309 for (
const auto interface_index : interface_indices)
1310 if (locally_owned.
is_element(interface_index))
1311 edge_constrained_indices[j].push_back(
1313 have_interface_matrices |=
1315 static_cast<unsigned int>(edge_constrained_indices[j].size()),
1316 data->get_vector_partitioner()->get_mpi_communicator()) > 0;
1322 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1329 const std::vector<unsigned int> &constrained_dofs =
1330 data->get_constrained_dofs(selected_rows[j]);
1331 for (
const auto constrained_dof : constrained_dofs)
1333 for (
unsigned int i = 0; i < edge_constrained_indices[j].size(); ++i)
1335 edge_constrained_indices[j][i]) = 1.;
1341 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1349 vmult_add(dst, src);
1354 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1360 mult_add(dst, src,
false);
1365 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1371 mult_add(dst, src,
true);
1376 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1380 const bool is_row)
const
1386 const unsigned int mf_component =
1387 is_row ? selected_rows[i] : selected_columns[i];
1390 data->get_dof_info(mf_component).vector_partitioner.get())
1397 data->get_dof_info(mf_component).vector_partitioner->local_size(),
1398 ExcMessage(
"The vector passed to the vmult() function does not have "
1399 "the correct size for compatibility with MatrixFree."));
1406 .reinit(data->get_dof_info(mf_component).vector_partitioner);
1408 .copy_locally_owned_data_from(copy_vec);
1414 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1422 adjust_ghost_range_if_necessary(src,
false);
1423 adjust_ghost_range_if_necessary(dst,
true);
1429 for (
unsigned int i = 0; i < edge_constrained_indices[j].size(); ++i)
1431 edge_constrained_values[j][i] = std::pair<Number, Number>(
1433 edge_constrained_indices[j][i]),
1435 edge_constrained_indices[j][i]));
1437 .local_element(edge_constrained_indices[j][i]) = 0.;
1444 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1454 preprocess_constraints(dst, src);
1456 Tapply_add(dst, src);
1458 apply_add(dst, src);
1459 postprocess_constraints(dst, src);
1464 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1472 const std::vector<unsigned int> &constrained_dofs =
1473 data->get_constrained_dofs(selected_rows[j]);
1474 for (
const auto constrained_dof : constrained_dofs)
1483 for (
unsigned int i = 0; i < edge_constrained_indices[j].size(); ++i)
1486 .local_element(edge_constrained_indices[j][i]) =
1487 edge_constrained_values[j][i].first;
1489 edge_constrained_indices[j][i]) =
1490 edge_constrained_values[j][i].second +
1491 edge_constrained_values[j][i].first;
1498 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1507 adjust_ghost_range_if_necessary(src,
false);
1508 adjust_ghost_range_if_necessary(dst,
true);
1512 if (!have_interface_matrices)
1518 for (
unsigned int i = 0; i < edge_constrained_indices[j].size(); ++i)
1520 edge_constrained_values[j][i] = std::pair<Number, Number>(
1522 edge_constrained_indices[j][i]),
1524 edge_constrained_indices[j][i]));
1526 .local_element(edge_constrained_indices[j][i]) = 0.;
1529 apply_add(dst, src);
1534 for (
unsigned int i = 0; i < edge_constrained_indices[j].size(); ++i)
1536 for (; c < edge_constrained_indices[j][i]; ++c)
1542 .local_element(edge_constrained_indices[j][i]) =
1543 edge_constrained_values[j][i].first;
1552 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1561 adjust_ghost_range_if_necessary(src,
false);
1562 adjust_ghost_range_if_necessary(dst,
true);
1566 if (!have_interface_matrices)
1573 for (
unsigned int i = 0; i < edge_constrained_indices[j].size(); ++i)
1575 for (; c < edge_constrained_indices[j][i]; ++c)
1583 apply_add(dst, src_cpy);
1586 for (
unsigned int i = 0; i < edge_constrained_indices[j].size(); ++i)
1588 edge_constrained_indices[j][i]) = 0.;
1593 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1602 Tvmult_add(dst, src);
1607 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1611 return inverse_diagonal_entries.get() !=
nullptr ?
1612 inverse_diagonal_entries->memory_consumption() :
1618 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1622 VectorizedArrayType>>
1630 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1631 const std::shared_ptr<DiagonalMatrix<VectorType>> &
1635 Assert(inverse_diagonal_entries.get() !=
nullptr &&
1636 inverse_diagonal_entries->m() > 0,
1638 return inverse_diagonal_entries;
1643 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1644 const std::shared_ptr<DiagonalMatrix<VectorType>> &
1647 Assert(diagonal_entries.get() !=
nullptr && diagonal_entries->m() > 0,
1649 return diagonal_entries;
1654 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1660 apply_add(dst, src);
1665 template <
int dim,
typename VectorType,
typename VectorizedArrayType>
1673 Assert(inverse_diagonal_entries.get() && inverse_diagonal_entries->m() > 0,
1675 inverse_diagonal_entries->vmult(dst, src);
1683 template <
typename OperatorType>
1686 , mf_base_operator(nullptr)
1691 template <
typename OperatorType>
1695 mf_base_operator =
nullptr;
1700 template <
typename OperatorType>
1704 mf_base_operator = &operator_in;
1709 template <
typename OperatorType>
1710 template <
typename VectorType>
1715 #ifndef DEAL_II_MSVC
1718 "The vector type must be based on the same value type as this "
1724 mf_base_operator->vmult_interface_down(dst, src);
1729 template <
typename OperatorType>
1730 template <
typename VectorType>
1735 #ifndef DEAL_II_MSVC
1738 "The vector type must be based on the same value type as this "
1744 mf_base_operator->vmult_interface_up(dst, src);
1749 template <
typename OperatorType>
1750 template <
typename VectorType>
1757 mf_base_operator->initialize_dof_vector(vec);
1769 typename VectorizedArrayType>
1786 typename VectorizedArrayType>
1793 VectorizedArrayType>::compute_diagonal()
1800 this->inverse_diagonal_entries =
1801 std::make_shared<DiagonalMatrix<VectorType>>();
1802 this->diagonal_entries = std::make_shared<DiagonalMatrix<VectorType>>();
1804 this->inverse_diagonal_entries->get_vector();
1805 VectorType &diagonal_vector = this->diagonal_entries->get_vector();
1806 this->initialize_dof_vector(inverse_diagonal_vector);
1807 this->initialize_dof_vector(diagonal_vector);
1808 inverse_diagonal_vector = Number(1.);
1809 apply_add(diagonal_vector, inverse_diagonal_vector);
1811 this->set_constrained_entries_to_one(diagonal_vector);
1812 inverse_diagonal_vector = diagonal_vector;
1814 const unsigned int local_size = inverse_diagonal_vector.local_size();
1815 for (
unsigned int i = 0; i < local_size; ++i)
1816 inverse_diagonal_vector.local_element(i) =
1817 Number(1.) / inverse_diagonal_vector.local_element(i);
1819 inverse_diagonal_vector.update_ghost_values();
1820 diagonal_vector.update_ghost_values();
1830 typename VectorizedArrayType>
1851 typename VectorizedArrayType>
1858 VectorizedArrayType>::
1863 VectorizedArrayType> & data,
1866 const std::pair<unsigned int, unsigned int> &cell_range)
const
1875 VectorizedArrayType>
1876 phi(data, this->selected_rows[0]);
1877 for (
unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
1880 phi.read_dof_values(src);
1881 phi.evaluate(
true,
false,
false);
1882 for (
unsigned int q = 0; q < phi.n_q_points; ++q)
1883 phi.submit_value(phi.get_value(q), q);
1884 phi.integrate(
true,
false);
1885 phi.distribute_local_to_global(dst);
1897 typename VectorizedArrayType>
1914 typename VectorizedArrayType>
1921 VectorizedArrayType>::clear()
1924 scalar_coefficient.reset();
1934 typename VectorizedArrayType>
1941 VectorizedArrayType>::
1945 scalar_coefficient = scalar_coefficient_;
1955 typename VectorizedArrayType>
1956 std::shared_ptr<Table<2, VectorizedArrayType>>
1962 VectorizedArrayType>::get_coefficient()
1965 return scalar_coefficient;
1975 typename VectorizedArrayType>
1982 VectorizedArrayType>::compute_diagonal()
1989 this->inverse_diagonal_entries =
1990 std::make_shared<DiagonalMatrix<VectorType>>();
1991 this->diagonal_entries = std::make_shared<DiagonalMatrix<VectorType>>();
1993 this->inverse_diagonal_entries->get_vector();
1994 VectorType &diagonal_vector = this->diagonal_entries->get_vector();
1995 this->initialize_dof_vector(inverse_diagonal_vector);
1996 this->initialize_dof_vector(diagonal_vector);
2002 this->set_constrained_entries_to_one(diagonal_vector);
2004 inverse_diagonal_vector = diagonal_vector;
2006 for (
unsigned int i = 0; i < inverse_diagonal_vector.local_size(); ++i)
2007 if (std::abs(inverse_diagonal_vector.local_element(i)) >
2009 inverse_diagonal_vector.local_element(i) =
2010 1. / inverse_diagonal_vector.local_element(i);
2012 inverse_diagonal_vector.local_element(i) = 1.;
2014 inverse_diagonal_vector.update_ghost_values();
2015 diagonal_vector.update_ghost_values();
2025 typename VectorizedArrayType>
2039 namespace Implementation
2041 template <
typename VectorizedArrayType>
2045 for (
unsigned int v = 0; v < VectorizedArrayType::size(); ++v)
2060 typename VectorizedArrayType>
2062 LaplaceOperator<dim,
2067 VectorizedArrayType>::
2068 do_operation_on_cell(
2075 const unsigned int cell)
const
2077 phi.evaluate(
false,
true,
false);
2078 if (scalar_coefficient.get())
2080 Assert(scalar_coefficient->size(1) == 1 ||
2081 scalar_coefficient->size(1) == phi.n_q_points,
2082 ExcMessage(
"The number of columns in the coefficient table must "
2083 "be either 1 or the number of quadrature points " +
2085 ", but the given value was " +
2087 if (scalar_coefficient->size(1) == phi.n_q_points)
2088 for (
unsigned int q = 0; q < phi.n_q_points; ++q)
2091 (*scalar_coefficient)(cell, q)),
2092 ExcMessage(
"Coefficient must be non-negative"));
2093 phi.submit_gradient((*scalar_coefficient)(cell, q) *
2094 phi.get_gradient(q),
2100 ExcMessage(
"Coefficient must be non-negative"));
2101 const VectorizedArrayType coefficient =
2102 (*scalar_coefficient)(cell, 0);
2103 for (
unsigned int q = 0; q < phi.n_q_points; ++q)
2104 phi.submit_gradient(coefficient * phi.get_gradient(q), q);
2109 for (
unsigned int q = 0; q < phi.n_q_points; ++q)
2111 phi.submit_gradient(phi.get_gradient(q), q);
2114 phi.integrate(
false,
true);
2124 typename VectorizedArrayType>
2131 VectorizedArrayType>::
2136 VectorizedArrayType> & data,
2139 const std::pair<unsigned int, unsigned int> &cell_range)
const
2144 data, this->selected_rows[0]);
2145 for (
unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
2148 phi.read_dof_values(src);
2149 do_operation_on_cell(phi, cell);
2150 phi.distribute_local_to_global(dst);
2160 typename VectorizedArrayType>
2167 VectorizedArrayType>::
2168 local_diagonal_cell(
2172 VectorizedArrayType> &data,
2175 const std::pair<unsigned int, unsigned int> &cell_range)
const
2181 data, this->selected_rows[0]);
2182 for (
unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
2189 phi.begin_dof_values()[j] = VectorizedArrayType();
2190 phi.begin_dof_values()[i] = 1.;
2191 do_operation_on_cell(phi, cell);
2192 local_diagonal_vector[i] = phi.begin_dof_values()[i];
2197 local_diagonal_vector[i];
2198 phi.distribute_local_to_global(dst);