38 const unsigned num_components,
41 std::vector<GlobalVector*>
const& x,
42 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& dof_table)
44 auto const num_nodal_dof_result =
47 std::vector<GlobalIndexType> ghost_indices;
51 auto const& single_component_ghost_indices =
53 auto const single_component_ghost_indices_size =
54 single_component_ghost_indices.size();
55 ghost_indices.reserve(single_component_ghost_indices_size *
57 for (
unsigned i = 0; i < single_component_ghost_indices_size; ++i)
59 for (
unsigned c = 0; c < num_components; ++c)
61 ghost_indices.push_back(
62 single_component_ghost_indices[i] * num_components + c);
76 {num_nodal_dof_result, num_nodal_dof_result, &ghost_indices,
87 auto const size = extrapolatables.
size();
88 for (std::size_t i = 0; i < size; ++i)
101 const unsigned num_components,
104 std::vector<GlobalVector*>
const& x,
105 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& dof_table)
119 if (
static_cast<std::size_t
>(num_element_dof_result) !=
120 extrapolatables.
size() * num_components)
122 OGS_FATAL(
"mismatch in number of D.o.F.");
125 auto const size = extrapolatables.
size();
126 for (std::size_t i = 0; i < size; ++i)
135 std::size_t
const element_index,
136 const unsigned num_components,
139 std::vector<GlobalVector*>
const& x,
140 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& dof_table,
143 auto const& integration_point_values =
148 if (integration_point_values.empty())
153 auto const& N_0 = extrapolatables.
getShapeMatrix(element_index, 0);
154 auto const num_nodes =
static_cast<unsigned>(N_0.cols());
155 auto const num_values =
156 static_cast<unsigned>(integration_point_values.size());
158 if (num_values % num_components != 0)
161 "The number of computed integration point values is not divisible "
162 "by the number of num_components. Maybe the computed property is "
163 "not a {:d}-component vector for each integration point.",
168 const auto num_int_pts = num_values / num_components;
170 if (num_int_pts < num_nodes)
173 "Least squares is not possible if there are more nodes than "
174 "integration points.");
178 std::make_pair(num_nodes, num_int_pts),
CachedData{});
180 auto& cached_data = pair_it_inserted.first->second;
181 if (pair_it_inserted.second)
183 DBUG(
"Computing new singular value decomposition");
188 auto& interpolation_matrix = cached_data.A;
189 interpolation_matrix.resize(num_int_pts, num_nodes);
191 interpolation_matrix.row(0) = N_0;
192 for (
unsigned int_pt = 1; int_pt < num_int_pts; ++int_pt)
194 auto const& shp_mat =
196 assert(shp_mat.cols() == num_nodes);
199 interpolation_matrix.row(int_pt) = shp_mat;
208 Eigen::JacobiSVD<Eigen::MatrixXd> svd(
209 interpolation_matrix, Eigen::ComputeThinU | Eigen::ComputeThinV);
211 auto const& S = svd.singularValues();
212 auto const& U = svd.matrixU();
213 auto const& V = svd.matrixV();
216 auto const rank = svd.rank();
217 assert(rank == num_nodes);
220 cached_data.A_pinv.noalias() = V.leftCols(rank) *
221 S.head(rank).asDiagonal().inverse() *
222 U.leftCols(rank).transpose();
224 else if (cached_data.A.row(0) != N_0)
226 OGS_FATAL(
"The cached and the passed shapematrices differ.");
229 auto const& global_indices =
232 if (num_components == 1)
234 auto const integration_point_values_vec =
238 Eigen::VectorXd
const nodal_values =
239 cached_data.A_pinv * integration_point_values_vec;
244 counts.
add(global_indices,
245 std::vector<double>(global_indices.size(), 1.0));
250 integration_point_values, num_components, num_int_pts);
253 Eigen::MatrixXd
const nodal_values =
254 cached_data.A_pinv * integration_point_values_mat.transpose();
256 std::vector<GlobalIndexType> indices;
257 indices.reserve(num_components * global_indices.size());
260 for (
unsigned comp = 0; comp < num_components; ++comp)
262 transform(cbegin(global_indices), cend(global_indices),
263 back_inserter(indices),
264 [&](
auto const i) {
return num_components * i + comp; });
270 counts.
add(indices, std::vector<double>(indices.size(), 1.0));
275 std::size_t
const element_index,
276 const unsigned num_components,
279 std::vector<GlobalVector*>
const& x,
280 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& dof_table)
285 auto const num_values =
static_cast<unsigned>(int_pt_vals.size());
286 if (num_values % num_components != 0)
289 "The number of computed integration point values is not divisible "
290 "by the number of num_components. Maybe the computed property is "
291 "not a {:d}-component vector for each integration point.",
296 const auto num_int_pts = num_values / num_components;
298 const auto& global_indices =
300 const auto num_nodes =
static_cast<unsigned>(global_indices.size());
302 auto const& interpolation_matrix =
305 Eigen::VectorXd nodal_vals_element(num_nodes);
306 auto const int_pt_vals_mat =
311 for (
unsigned comp = 0; comp < num_components; ++comp)
314 for (
unsigned i = 0; i < num_nodes; ++i)
317 auto const idx = num_components * global_indices[i] + comp;
321 double const residual = (interpolation_matrix * nodal_vals_element -
322 int_pt_vals_mat.row(comp).transpose())
328 auto const root_mean_square = std::sqrt(residual / num_int_pts);