-
Notifications
You must be signed in to change notification settings - Fork 248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[GeoMechanicsApplication] Extract a static utility function for the calculation of the Mass Matrix (M) #12299
Conversation
- raw pointer - index++ - 4 for loops into 2 for loops
…ientInitialConfiguration
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like this PR, it cleaned up nicely and took away unnecessary responsibilities from the element (and the function is already on the element level as opposed to integration points)!
I have suggestions for improvements (apart from the discussed unit tests that indeed still need to be added) of the calculation code now that it's moved to the utilities and I think we might need a bit more discussion on the diff order/non-diff order calculations, but this is a very nice step!
MatrixType MassMatrix(ElementSize, ElementSize); | ||
|
||
this->CalculateMassMatrix(MassMatrix, rCurrentProcessInfo); | ||
MatrixType MassMatrix = GeoTransportEquationUtilities::CalculateMassMatrixDiffOrder( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is a local variable, this should be snake case (problem of course is that it seems this class very inconsistent with that right now, maybe we can fix it only in the functions we touch?)
MatrixType MassMatrix = GeoTransportEquationUtilities::CalculateMassMatrixDiffOrder( | |
MatrixType mass_matrix = GeoTransportEquationUtilities::CalculateMassMatrixDiffOrder( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you. Yesterday I made the same comments to Mohamed ;(
for (SizeType i = 0; i < NumberPNodes; ++i) { | ||
solution_vector[i] = rGeom[i].FastGetSolutionStepValue(SolutionVariable); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be a transform 😃 :
for (SizeType i = 0; i < NumberPNodes; ++i) { | |
solution_vector[i] = rGeom[i].FastGetSolutionStepValue(SolutionVariable); | |
} | |
std::transform(rGeom.begin(), rGeom.end(), solution_vector.begin(), | |
[&SolutionVariable](const auto& node) { | |
return node.FastGetSolutionStepValue(SolutionVariable); | |
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great! Used it.
return inner_prod(rNp, rPressureVector); | ||
} | ||
|
||
static Vector GetSolutionVector(SizeType NumberPNodes, const Geometry<Node>& rGeom, const Variable<double>& SolutionVariable) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpicking:
static Vector GetSolutionVector(SizeType NumberPNodes, const Geometry<Node>& rGeom, const Variable<double>& SolutionVariable) | |
static Vector GetSolutionVector(SizeType NumberPNodes, const Geometry<Node>& rGeom, const Variable<double>& rSolutionVariable) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, changed.
return mass_matrix; | ||
} | ||
|
||
static double CalculateFluidPressure(const Vector& rNp, const Vector& rPressureVector) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this function can be private
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, made more functions private. No need to make unit tests!
return inner_prod(rNp, rPressureVector); | ||
} | ||
|
||
static Vector GetSolutionVector(SizeType NumberPNodes, const Geometry<Node>& rGeom, const Variable<double>& SolutionVariable) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this function can be private
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -79,6 +86,174 @@ class GeoTransportEquationUtilities | |||
{ | |||
return -PORE_PRESSURE_SIGN_FACTOR * BiotModulusInverse * outer_prod(rNp, rNp) * IntegrationCoefficient; | |||
} | |||
|
|||
|
|||
static Matrix CalculateMassMatrixDiffOrder(const Geometry<Node>& rGeom, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed, it is probably a good idea to let one of the functions call the other, such that we avoid duplications which are still there at this moment. Ideally the utilities shouldn't care about diff order/non-diff order, would it be possible to prepare the inputs for this functions in such a way in the diff order element that we can use the standard version? That way, all real 'diff-order' functionality stays in that element.
However, I haven't spend as much time as you in this piece of code and I think this is already a nice improvement, so we could leave it to a later PR in my opinion if that would be too much work for this one.
What is your opinion here @avdg81?
for (SizeType i = 0; i < number_U_nodes * dimension; ++i) { | ||
for (SizeType j = 0; j < number_U_nodes * dimension; ++j) { | ||
mass_matrix(i, j) += mass_matrix_contribution(i, j); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks very similar to this function in element utilities, maybe we can re-use it?
Kratos/applications/GeoMechanicsApplication/custom_utilities/element_utilities.hpp
Lines 600 to 611 in f8087c7
template <typename MatrixType1, typename MatrixType2> | |
static void AddMatrixAtPosition(const MatrixType1& rSourceMatrix, | |
MatrixType2& rDestinationMatrix, | |
std::size_t RowOffset, | |
std::size_t ColumnOffset) | |
{ | |
for (auto i = std::size_t{0}; i < rSourceMatrix.size1(); ++i) { | |
for (auto j = std::size_t{0}; j < rSourceMatrix.size2(); ++j) { | |
rDestinationMatrix(i + RowOffset, j + ColumnOffset) += rSourceMatrix(i, j); | |
} | |
} | |
} |
Although I see it's private, what is your opinion @avdg81 (since you added that function)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank for the info. I used AssembleUUBlockMatrix than both functions CalculateMassMatrix became more similar.
applications/GeoMechanicsApplication/custom_utilities/transport_equation_utilities.hpp
Show resolved
Hide resolved
rGeom.IntegrationPoints(IntegrationMethod); | ||
const unsigned int number_G_points = integration_points.size(); | ||
|
||
Matrix N_container = rGeom.ShapeFunctionsValues(IntegrationMethod); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the ShapeFunctionsValues
function returns a const Matrix&, I'd suggest to make this const& to avoid the copy
Matrix N_container = rGeom.ShapeFunctionsValues(IntegrationMethod); | |
const Matrix& N_container = rGeom.ShapeFunctionsValues(IntegrationMethod); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed.
const unsigned int number_G_points = integration_points.size(); | ||
|
||
Matrix N_container = rGeom.ShapeFunctionsValues(IntegrationMethod); | ||
Vector pressure_vector = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be const
Vector pressure_vector = | |
const Vector pressure_vector = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
… rGeom from CalculateMassMatrix input
…lities to elements
Hi guys, following our conversation this Monday: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for incorporating the changes, I think the function is turning out to be very clear and readable and you extracted and cleaned up a lot of other duplications in this PR! I only have a few comments left about includes that could be removed/moved from the header.
Matrix GeoEquationOfMotionUtilities::CalculateMassMatrix(SizeType dimension, | ||
SizeType number_U_nodes, | ||
SizeType NumberIntegrationPoints, | ||
const Matrix& Nu_container, | ||
const Vector& rSolidDensities, | ||
const std::vector<double>& rIntegrationCoefficients) | ||
{ | ||
const SizeType block_element_size = number_U_nodes * dimension; | ||
Matrix Nu = ZeroMatrix(dimension, block_element_size); | ||
Matrix aux_density_matrix = ZeroMatrix(dimension, block_element_size); | ||
Matrix density_matrix = ZeroMatrix(dimension, dimension); | ||
Matrix mass_matrix = ZeroMatrix(block_element_size, block_element_size); | ||
|
||
for (unsigned int g_point = 0; g_point < NumberIntegrationPoints; ++g_point) { | ||
GeoElementUtilities::AssembleDensityMatrix(density_matrix, rSolidDensities(g_point)); | ||
GeoElementUtilities::CalculateNuMatrix(dimension, number_U_nodes, Nu, Nu_container, g_point); | ||
noalias(aux_density_matrix) = prod(density_matrix, Nu); | ||
mass_matrix += prod(trans(Nu), aux_density_matrix) * rIntegrationCoefficients[g_point]; | ||
} | ||
return mass_matrix; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This became a very easy-to-read and generic function!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, it is a real team work!
// Project includes | ||
|
||
// Application includes | ||
#include "custom_utilities/element_utilities.hpp" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor, but I think this include can move to the cpp file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved it to the cpp file but I had to add other h files. Nevertheless, a number of dependencies is decreased.
namespace Kratos::Testing | ||
{ | ||
|
||
KRATOS_TEST_CASE_IN_SUITE(CalculateMassMatrix2D6NDiffOrderGivesCorrectResults, KratosGeoMechanicsFastSuite) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like that we have these unit tests to make sure these functions keep doing what they're doing now!
#include "containers/model.h" | ||
#include "custom_utilities/transport_equation_utilities.hpp" | ||
#include "includes/checks.h" | ||
#include "testing/testing.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we need the containers/model.h, could we try to remove it?
#include "containers/model.h" | |
#include "custom_utilities/transport_equation_utilities.hpp" | |
#include "includes/checks.h" | |
#include "testing/testing.h" | |
#include "custom_utilities/transport_equation_utilities.hpp" | |
#include "includes/checks.h" | |
#include "testing/testing.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, yes we can and I made it now.
#pragma once | ||
|
||
#include "geo_aliases.h" | ||
#include "includes/properties.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This include we might be able to move to the cpp file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Gennady,
I think a large improvement is made with this pull request. Please judge what you think of the remarks is still useful and what is more suited for next actions.
Wijtze Pieter
if (rMassMatrix.size1() != element_size || rMassMatrix.size2() != element_size) | ||
rMassMatrix.resize(element_size, element_size, false); | ||
noalias(rMassMatrix) = ZeroMatrix(element_size, element_size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The resize will test for the size itself, so no need for check before.
ZeroMatrix will set the size correctly, but I'm not certain about the noalias.
I think line 462 can be omitted
The same happens for the dampingmatrix below at 494
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
noalias does not change the size. I think it will be a decision on all noalias'es later.
if (rDampingMatrix.size1() != element_size) | ||
rDampingMatrix.resize(element_size, element_size, false); | ||
noalias(rDampingMatrix) = ZeroMatrix(element_size, element_size); | ||
|
||
if (rProp.Has(RAYLEIGH_ALPHA)) noalias(rDampingMatrix) += rProp[RAYLEIGH_ALPHA] * MassMatrix; | ||
else noalias(rDampingMatrix) += rCurrentProcessInfo[RAYLEIGH_ALPHA] * MassMatrix; | ||
if (r_prop.Has(RAYLEIGH_ALPHA)) noalias(rDampingMatrix) += r_prop[RAYLEIGH_ALPHA] * mass_matrix; | ||
else noalias(rDampingMatrix) += rCurrentProcessInfo[RAYLEIGH_ALPHA] * mass_matrix; | ||
|
||
if (rProp.Has(RAYLEIGH_BETA)) noalias(rDampingMatrix) += rProp[RAYLEIGH_BETA] * StiffnessMatrix; | ||
if (r_prop.Has(RAYLEIGH_BETA)) | ||
noalias(rDampingMatrix) += r_prop[RAYLEIGH_BETA] * StiffnessMatrix; | ||
else noalias(rDampingMatrix) += rCurrentProcessInfo[RAYLEIGH_BETA] * StiffnessMatrix; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When first the Rayleigh parameters are determined, the setting of the damping matrix becomes like the formula. e.g.
const double rayleigh_alpha = r_prop.Has(RAYLEIGH_ALPHA) ? r_prop[RAYLEIGH_ALPHA] : rCurrentProcessInfo[RAYLEIGH_ALPHA];
const double rayleigh_beta = r_prop.Has(RAYLEIGH_BETA) ? r_prop[RAYLEIGH_BETA] : rCurrentProcessInfo[RAYLEIGH_BETA];
rDampingMatrix = rayleigh_alpha * mass_matrix + rayleigh_beta + stiffness_matrix;
( I didn't check my syntax here, just trying to write down the intention )
As focus is on the mass matrix first, this is probably for a next pull request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed that it is better in any sense: visibility, understanding etc.
Vector SmallStrainUPwDiffOrderElement::GetPressureSolutionVector() | ||
{ | ||
Vector result(mpPressureGeometry->PointsNumber()); | ||
std::transform(this->GetGeometry().begin(), | ||
this->GetGeometry().begin() + mpPressureGeometry->PointsNumber(), result.begin(), | ||
[](const auto& node) { return node.FastGetSolutionStepValue(WATER_PRESSURE); }); | ||
return result; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a very useful functionality, variants of it exist in custom_ulitities/element_utilities.hpp, the GetNodalVariableVector and GetNodalVariableMatrix. I think that is the place where these belong, but your implementation is more elegant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
template <unsigned int TDim, unsigned int TNumNodes> | ||
Vector UPwSmallStrainElement<TDim, TNumNodes>::GetPressureSolutionVector() | ||
{ | ||
Vector result(TNumNodes); | ||
std::transform(this->GetGeometry().begin(), this->GetGeometry().end(), result.begin(), | ||
[](const auto& node) { return node.FastGetSolutionStepValue(WATER_PRESSURE); }); | ||
return result; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very similar (but nicer written) to the GetNodalVariableVector or Matrix functions in element_utilities.hpp
Maybe this functionality belongs there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for all your hard work on this PR! From my side, this is ready to go!
📝 Description
An utility function to calculate the mass matrix has been extracted.
🆕 Changelog
Please summarize the changes in one list to generate the changelog:
E.g.