Skip to content
Snippets Groups Projects
Commit 82ee912b authored by Christoph Lehmann's avatar Christoph Lehmann
Browse files

[NL] reuse extrapolation matrix for residual computation

parent 4d7a046a
No related branches found
No related tags found
No related merge requests found
...@@ -96,7 +96,7 @@ void LocalLinearLeastSquaresExtrapolator::extrapolateElement( ...@@ -96,7 +96,7 @@ void LocalLinearLeastSquaresExtrapolator::extrapolateElement(
"integration points."); "integration points.");
auto const pair_it_inserted = _qr_decomposition_cache.emplace( auto const pair_it_inserted = _qr_decomposition_cache.emplace(
std::make_pair(num_nodes, num_int_pts), CachedData{N_0}); std::make_pair(num_nodes, num_int_pts), CachedData{});
auto& cached_data = pair_it_inserted.first->second; auto& cached_data = pair_it_inserted.first->second;
if (pair_it_inserted.second) if (pair_it_inserted.second)
...@@ -106,9 +106,11 @@ void LocalLinearLeastSquaresExtrapolator::extrapolateElement( ...@@ -106,9 +106,11 @@ void LocalLinearLeastSquaresExtrapolator::extrapolateElement(
// interpolation_matrix * nodal_values = integration_point_values // interpolation_matrix * nodal_values = integration_point_values
// We are going to pseudo-invert this relation now using singular value // We are going to pseudo-invert this relation now using singular value
// decomposition. // decomposition.
Eigen::MatrixXd interpolation_matrix(num_int_pts, num_nodes); auto& interpolation_matrix = cached_data.A;
interpolation_matrix.resize(num_int_pts, num_nodes);
for (unsigned int_pt = 0; int_pt < num_int_pts; ++int_pt) { interpolation_matrix.row(0) = N_0;
for (unsigned int_pt = 1; int_pt < num_int_pts; ++int_pt) {
auto const& shp_mat = auto const& shp_mat =
extrapolatables.getShapeMatrix(element_index, int_pt); extrapolatables.getShapeMatrix(element_index, int_pt);
assert(shp_mat.cols() == num_nodes); assert(shp_mat.cols() == num_nodes);
...@@ -134,12 +136,12 @@ void LocalLinearLeastSquaresExtrapolator::extrapolateElement( ...@@ -134,12 +136,12 @@ void LocalLinearLeastSquaresExtrapolator::extrapolateElement(
assert(rank == num_nodes); assert(rank == num_nodes);
// cf. http://eigen.tuxfamily.org/dox/JacobiSVD_8h_source.html // cf. http://eigen.tuxfamily.org/dox/JacobiSVD_8h_source.html
cached_data.p_inv.noalias() = cached_data.A_pinv.noalias() =
V.leftCols(rank) * V.leftCols(rank) *
S.head(rank).asDiagonal().inverse() * S.head(rank).asDiagonal().inverse() *
U.leftCols(rank).transpose(); U.leftCols(rank).transpose();
} }
else if (cached_data.N_0 != N_0) { else if (cached_data.A.row(0) != N_0) {
OGS_FATAL("The cached and the passed shapematrices differ."); OGS_FATAL("The cached and the passed shapematrices differ.");
} }
...@@ -149,7 +151,7 @@ void LocalLinearLeastSquaresExtrapolator::extrapolateElement( ...@@ -149,7 +151,7 @@ void LocalLinearLeastSquaresExtrapolator::extrapolateElement(
// Apply the pre-computed pseudo-inverse. // Apply the pre-computed pseudo-inverse.
Eigen::VectorXd const nodal_values = Eigen::VectorXd const nodal_values =
cached_data.p_inv * integration_point_values_vec; cached_data.A_pinv * integration_point_values_vec;
// TODO: for now always zeroth component is used. This has to be extended if // TODO: for now always zeroth component is used. This has to be extended if
// multi-component properties shall be extrapolated // multi-component properties shall be extrapolated
...@@ -174,23 +176,18 @@ void LocalLinearLeastSquaresExtrapolator::calculateResidualElement( ...@@ -174,23 +176,18 @@ void LocalLinearLeastSquaresExtrapolator::calculateResidualElement(
const unsigned num_nodes = global_indices.size(); const unsigned num_nodes = global_indices.size();
// filter nodal values of the current element // filter nodal values of the current element
std::vector<double> nodal_vals_element(num_nodes); Eigen::VectorXd nodal_vals_element(num_nodes);
for (unsigned i = 0; i < num_nodes; ++i) { for (unsigned i = 0; i < num_nodes; ++i) {
// TODO PETSc negative indices? // TODO PETSc negative indices?
nodal_vals_element[i] = _nodal_values[global_indices[i]]; nodal_vals_element[i] = _nodal_values[global_indices[i]];
} }
double residual = 0.0; auto const& interpolation_matrix =
double int_pt_val_extrapolated = 0.0; _qr_decomposition_cache.find({num_nodes, num_int_pts})->second.A;
for (unsigned int_pt = 0; int_pt < num_int_pts; ++int_pt) { double const residual = (interpolation_matrix * nodal_vals_element -
NumLib::shapeFunctionInterpolate( MathLib::toVector(int_pt_vals))
nodal_vals_element, .squaredNorm();
extrapolatables.getShapeMatrix(element_index, int_pt),
int_pt_val_extrapolated);
auto const& ax_m_b = int_pt_val_extrapolated - int_pt_vals[int_pt];
residual += ax_m_b * ax_m_b;
}
_residuals.set(element_index, std::sqrt(residual / num_int_pts)); _residuals.set(element_index, std::sqrt(residual / num_int_pts));
} }
......
...@@ -99,19 +99,14 @@ private: ...@@ -99,19 +99,14 @@ private:
//! Avoids frequent reallocations. //! Avoids frequent reallocations.
std::vector<double> _integration_point_values_cache; std::vector<double> _integration_point_values_cache;
//! Stores a QR decomposition of some matrix. //! Stores a matrix and its Moore-Penrose pseudo-inverse.
struct CachedData { struct CachedData
explicit CachedData(Eigen::Ref<const Eigen::RowVectorXd> N_0_) {
: N_0(N_0_) //! The matrix A.
{ Eigen::MatrixXd A;
}
//! Moore-Penrose pseudo-inverse of A.
//! Zeroth shape matrix. Used for assertion only. Eigen::MatrixXd A_pinv;
Eigen::RowVectorXd const N_0;
//! Moore-Penrose pseudo-inverse of the nodal value to integration point
//! value interpolation matrix.
Eigen::MatrixXd p_inv;
}; };
/*! Maps (#nodes, #int_pts) to (N_0, QR decomposition), /*! Maps (#nodes, #int_pts) to (N_0, QR decomposition),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment