Skip to content
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

Second shape derivatives transform implementation #11253

Merged

Conversation

jgonzalezusua
Copy link
Member

📝 Description
This PR is aim to implement the transformation of the second derivatives of the shape functions from isoparametric coordinates. The implementation follows this method: https://scicomp.stackexchange.com/questions/25196/implementing-higher-order-derivatives-for-finite-element

Please mark the PR with appropriate tags:

  • Core
  • Feature

🆕 Changelog

  • Added ShapeFunctionsIntegrationPointsSecondDerivatives in geometry.h
  • Added VerifyShapeFunctionsSecondDerivativesInterpolation in geometry_tester.cpp

@philbucher
Copy link
Member

Is this intended to be overridden for different geometries?

If not then I suggest to move it to the GeomUtils, to not further overload the Geometry

@jgonzalezusua
Copy link
Member Author

I do not think so, it is analogous to the calculation of the first derivatives on integration points

Copy link
Member

@rubenzorrilla rubenzorrilla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree @jgonzalezusua observation. For the user it would be a bit counterintuitive to have the 1st derivatives in the Geometry and 2nd ones in a separate class. I think we should throw an error in those geometries that would require an especific treatment (i.e. non-square Jacobian ones).

In any case, I'd like @RiccardoRossi to have a special look to this one.

Comment on lines 3723 to 3724
KRATOS_ERROR_IF_NOT(this->WorkingSpaceDimension() == this->LocalSpaceDimension())
<< "\'ShapeFunctionsIntegrationPointsSecondDerivatives\' is not defined for current geometry type as second derivatives are only defined in the local space." << std::endl;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, better than the check I was proposing.

@pooyan-dadvand
Copy link
Member

@KratosMultiphysics/technical-committee would like to ask why the GlobalSpaceDerivatives won't work in this context.

Another concern is the performance as we think that doing the loop over the Gauss points in the element would be more efficient rather than creating a vector of vectors and returning the results.

@jgonzalezusua
Copy link
Member Author

@KratosMultiphysics/technical-committee would like to ask why the GlobalSpaceDerivatives won't work in this context.

As far as I know in GlobalSpaceDerivatives we can compute the first derivatives but not the second order. The key with this implementation is to obtain the transform from isoparametric coordinates of the shape function second derivatives

@jgonzalezusua
Copy link
Member Author

jgonzalezusua commented Jun 20, 2023

@KratosMultiphysics/technical-committee when do you think we can merge this PR? Do you think I need to change the implementation?

@jgonzalezusua
Copy link
Member Author

@pooyan-dadvand, did the committe reject the current implementation?

@RiccardoRossi
Copy link
Member

we are pending @sunethwarna to speak with @tteschemacher or @oberbichler about how that funciton should be used

@tteschemacher
Copy link
Contributor

Thank you @jgonzalezusua for your implementation. Generally, that looks like a good feature with good code quality. I do have a couple of comments. Please consider that I am not @KratosMultiphysics/technical-committee , therefore, they will have the last word. I think some of my points are at least important to be discussed. Sorry for my very late reply. I will try to stay in the loop to finish that up quickly.

@KratosMultiphysics/technical-committee would like to ask why the GlobalSpaceDerivatives won't work in this context.

The GlobalSpaceDerivatives would return the evaluated base vectors and their derivatives in global space. Basically, evaluated shape functions * node coordinates. Your function computes in local space, please add a comment to make it clear? It would be handy, if you could add your function to the GlobalSpaceDerivatives it. However, it is complementary to your function. If you consider doing this, please do this in a later PR.

I do have a general question, is your function valid for any type of geometry, or is it restrained to linear mesh elements? Do you need any given polynomial degree (which?). If so, you could add a check to it.

@RiccardoRossi
Copy link
Member

@tteschemacher first of all thank you for taking the time to review this.

One of our issues was that by looking at the signature

virtual void GlobalSpaceDerivatives(
        std::vector<CoordinatesArrayType>& rGlobalSpaceDerivatives,
        const CoordinatesArrayType& rLocalCoordinates,
        const SizeType DerivativeOrder) const

we do not reallt understand how the output is organized. Can u explain what is the content of rGlobalSpaceDerivatives on output? imagine for example that we have a quadrilateral and we ask for the third derivatives. How would they be organized in the output vector? (i am aware they would be zero...but it is really not clear to us how they would be stored since that output vector has variable size (it is a std:.vector), but always contains entries of size 3 ...

@tteschemacher
Copy link
Contributor

The function itself contains the comment about the order:

/**
* @brief This method maps from dimension space to working space and computes the
* number of derivatives at the dimension parameter.
* @param rGlobalSpaceDerivatives The derivative in global space.
* @param rLocalCoordinates the local coordinates
* @param rDerivativeOrder of computed derivatives
* @return std::vector<array_1d<double, 3>> with the coordinates in working space
* The list is structured as following:
* [0] - global coordinates
* [1 - loc_space_dim] - base vectors (du, dv, dw)
* [...] - second order vectors:
* 1D: du^2
* 2D: du^2, dudv, dv^2
* 3D: du^2, dudv, dudw, dv^2, dvdw, dw^2
* [...] - third order vectors:
* 1D: du^3
* 2D: du^3, du^2dv, dudv^2, dv^3
*/

It is:
[0] location
[1] du
[2] dv
[3] du^2
[4] du dv
[5] dv^2
....

Unfortunately, there's nothing to ensure that this is done right.

If that is still difficult to understand, I should update the comment.

@jgonzalezusua
Copy link
Member Author

Hi @tteschemacher, this function is not restraint to linear elements. In fact, if you use triangle or tetrahedra, the output of this function should be 0. I have implemented a test to compute the second derivatives of a two order polynomial using a quadratic hexahedra and it works well.

@RiccardoRossi
Copy link
Member

@tteschemacher the point is that i am not clear with what you mean by that

imagine i have the shape functions N1, N2, N3, N4 referring to the nodes 1,2,3,4 respectively

where do i find

d^3 N1 / dxdydz ??

where is

d^3 N3 / dxdydz ??

@tteschemacher
Copy link
Contributor

@tteschemacher the point is that i am not clear with what you mean by that

imagine i have the shape functions N1, N2, N3, N4 referring to the nodes 1,2,3,4 respectively

where do i find

d^3 N1 / dxdydz ??

where is

d^3 N3 / dxdydz ??

That vector does not contain shape functions per se. It contains its evaluation towards location and base vectors.

for (IndexType k = 0; k < WorkingSpaceDimension(); ++k) {
const double value = r_coordinates[k];
for (IndexType m = 0; m < local_space_dimension; ++m) {
rGlobalSpaceDerivatives[m + 1][k] += value * shape_functions_gradients(i, m);

All that should be in x, y, z coordinates in the global system (That is in type of CoordinatesArrayType). That is why I think the two functions are complemantary and it would be nice to complete them.

@RiccardoRossi
Copy link
Member

sorry @tteschemacher but i really do not understand what you mean by telling "That vector does not contain shape functions per se. It contains its evaluation towards location and base vectors"

could you be a bit more explicative about that...

@jgonzalezusua
Copy link
Member Author

@oberbichler, I hope you could share your opinion about this implementation

@jgonzalezusua
Copy link
Member Author

Sorry if I am a little tiresome but I have openned this PR last month, and it seems stucked. @KratosMultiphysics/technical-committee, do you have more comments about it? What do we need to do to approve this PR?

@oberbichler
Copy link
Contributor

@oberbichler, I hope you could share your opinion about this implementation

Dear @jgonzalezusua,

as I already told @sunethwarna, I am working on new projects and have no time to deal with Kratos. Moreover, I have never worked with Kratos - apart from some short experiments - and have never used Kratos for my research. Therefore, I can neither comment on your code nor explain any Kratos functions.

Reading the comments, however, there seems to be a big misunderstanding. @tteschemacher probably has NURBS in mind, while @RiccardoRossi thinks of something else. Points of NURBS are linear combinations of the control points and therefore d^3 N1 / dxdydz = d^3 N3 / dxdydz = 0. If I remember correctly, this misunderstanding has been around for over 6 years 🤷.

Best regards
Thomas

@jgonzalezusua
Copy link
Member Author

@oberbichler, I hope you could share your opinion about this implementation

Dear @jgonzalezusua,

as I already told @sunethwarna, I am working on new projects and have no time to deal with Kratos. Moreover, I have never worked with Kratos - apart from some short experiments - and have never used Kratos for my research. Therefore, I can neither comment on your code nor explain any Kratos functions.

Reading the comments, however, there seems to be a big misunderstanding. @tteschemacher probably has NURBS in mind, while @RiccardoRossi thinks of something else. Points of NURBS are linear combinations of the control points and therefore d^3 N1 / dxdydz = d^3 N3 / dxdydz = 0. If I remember correctly, this misunderstanding has been around for over 6 years shrug.

Best regards Thomas

Ok thanks. If you are not involved in Kratos, I do not know why they request your presence here. Anyway, I hope we can conclude soon this PR.

Copy link
Contributor

@tteschemacher tteschemacher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are a couple of more questions.

Comment on lines 3718 to 3721
virtual void ShapeFunctionsIntegrationPointsSecondDerivatives(
DenseVector<DenseVector<Matrix>>& rResult,
IntegrationMethod ThisMethod ) const
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In most of those functions we have actually intended to separate betweem the functions which use the integration method and the functions which are called with all the information obtained from it.

That would allow to use the same function with own integration rules. In most of my cases that had been apparent. Therefore, I would like to ask you if that makes sense here. I know that this deducts slightly the efficiency. But as I checked through the code, it appears that this effect can be kept minor.

If the function is only capable to express the shapes of integration points from the pre-evaluated points, then you should add a comment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To compute the second derivatives you need to know the integration method in order to get the number of integration points. This function has been implemented preserving the same format as ShapeFunctionsIntegrationPointsGradients, which does the same for the case of first derivatives.

* https://scicomp.stackexchange.com/questions/25196/implementing-higher-order-derivatives-for-finite-element
*/
virtual void ShapeFunctionsIntegrationPointsSecondDerivatives(
DenseVector<DenseVector<Matrix>>& rResult,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

@jgonzalezusua jgonzalezusua Jul 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This data type is DenseVector<DenseVector< Matrix > > and the one you cite is DenseVector< Matrix >

* The method used can be found here.
* https://scicomp.stackexchange.com/questions/25196/implementing-higher-order-derivatives-for-finite-element
*/
virtual void ShapeFunctionsIntegrationPointsSecondDerivatives(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably I would rename this function to ShapeFunctionsSecondDerivatives to overload the existing function. Or let me know what are the intended differences?

Copy link
Member Author

@jgonzalezusua jgonzalezusua Jul 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function ShapeFunctionsSecondDerivatives is not the same as ShapeFunctionsIntegrationPointsSecondDerivatives.

  • ShapeFunctionsSecondDerivatives computes the isoparametric second derivatives of the shape functions and depends on the geometry you use (linear, bilinear, quadratic, biquadratic, etc). Then, it is called from the element you use.
  • ShapeFunctionsIntegrationPointsSecondDerivatives computes the mapping between the isoparametric and natural coordinates.

So it cannot be renamed as you said.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, it really looks like this is a problematic one.

I now took at least 1h to try to understand this PR and honestly i am lost.

To assess the current situation, the geometry already has a function to compute second (and third) order derivatives IN THE LOCAL SPACE (xi eta zeta).
your goal is to have that in the global space (x y z)? It that is so, the name or at least the documentation of the function should reflect that very clearly.

could we have a meeting, either online or in person to discuss this?

Copy link
Member

@RiccardoRossi RiccardoRossi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ouch, i thought i sent this last week...

* The method used can be found here.
* https://scicomp.stackexchange.com/questions/25196/implementing-higher-order-derivatives-for-finite-element
*/
virtual void ShapeFunctionsIntegrationPointsSecondDerivatives(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, it really looks like this is a problematic one.

I now took at least 1h to try to understand this PR and honestly i am lost.

To assess the current situation, the geometry already has a function to compute second (and third) order derivatives IN THE LOCAL SPACE (xi eta zeta).
your goal is to have that in the global space (x y z)? It that is so, the name or at least the documentation of the function should reflect that very clearly.

could we have a meeting, either online or in person to discuss this?

@jgonzalezusua
Copy link
Member Author

ouch, i thought i sent this last week...

Yes, we can meet in person or online. If you are in the university we can have the meeting right now.

@RiccardoRossi
Copy link
Member

I am in my office, just pass by if you can

@jgonzalezusua
Copy link
Member Author

jgonzalezusua commented Jul 20, 2023

As @RiccardoRossi and @philbucher suggested, I have changes the transform of the second derivatives of the shape functions to geometry_utilities.h and geometry_utilities.cpp

@jgonzalezusua
Copy link
Member Author

Something happens with the ContactMechanics but I have not modified nothing from it. Others PRs have the same problem...

@jgonzalezusua
Copy link
Member Author

@RiccardoRossi I did the changes as you suggested

@pooyan-dadvand
Copy link
Member

@KratosMultiphysics/technical-committee agrees with the change as it is now an utility and not changing the geometry base class.

@RiccardoRossi will review it

@@ -1029,6 +1034,86 @@ bool GeometryTesterUtility::VerifyShapeFunctionsSecondDerivativesValues(
return true;
}

bool GeometryTesterUtility::VerifyShapeFunctionsSecondDerivativesInterpolation(
GeometryType& rGeometry,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can u make this const?

* @return true If teh test fails, true otherwise¡
*/
bool VerifyShapeFunctionsSecondDerivativesInterpolation(
GeometryType& rGeometry,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const

/***********************************************************************************/

void GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnIntegrationPoint(
Matrix DN_DX,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is input or output?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DN_DX is an input

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If so you can pass a const reference to avoid the copy.

rGeometry.ShapeFunctionsSecondDerivatives(DDN_DDe, rLocalIntegrationPointCoordinates);

Matrix A, Ainv;
double DetA;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function will fail if WorkingSpaceDimension is different from LocalSpaceDimension.

i think you should thow an error if that is the case

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already done in line 527

for (IndexType p = 0; p < rGeometry.PointsNumber(); ++p) {
Vector rhs, result;
if (rGeometry.WorkingSpaceDimension() == 2){
rhs.resize(3);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are resizing this once per every point number. put the resize outside of the loop?

also use the false in the resize

rhs[2] = DDN_DDe[p](0,1) - DN_DX(p,0) * H[0](0,1) - DN_DX(p,1) * H[1](0,1);
}
else if (rGeometry.WorkingSpaceDimension() == 3){
rhs.resize(6);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same


aux[p].resize(rGeometry.WorkingSpaceDimension(), rGeometry.WorkingSpaceDimension(), false );

result = prod(Ainv, rhs);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

noalias

kratos/utilities/geometry_utilities.cpp Show resolved Hide resolved
@@ -345,6 +345,10 @@ bool GeometryTesterUtility::StreamTestQuadrilateral2D9N(

array_1d<double,3> point_in(3,1.0/3.0);
if( !VerifyShapeFunctionsSecondDerivativesValues(geometry,point_in,rErrorMessage) ) successful = false;
Quadrilateral2D9<NodeType> exact_geometry( rModelPart.pGetNode(1), rModelPart.pGetNode(3), rModelPart.pGetNode(9), rModelPart.pGetNode(7),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as a general comment, not for this PR, why the geometry_tester is in the utilities? if it is only for testing it should be in the testing folder.

aux[p](1,2) = result[4];
}
}
rResult = aux;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

noalias

@jgonzalezusua
Copy link
Member Author

@RiccardoRossi, I have made the changes that you suggested.

@@ -518,7 +518,7 @@ void GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoin
/***********************************************************************************/

void GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnIntegrationPoint(
Matrix DN_DX,
const Matrix DN_DX,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are passing this by copy. is it intentional?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I think we can pass it as a reference

@@ -519,7 +519,7 @@ class KRATOS_API(KRATOS_CORE) GeometryTesterUtility
GeometryType& rGeometry,
GeometryType::CoordinatesArrayType& rGlobalCoordinates,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rGlobalCoordinates should also be const no?

Copy link
Member Author

@jgonzalezusua jgonzalezusua Sep 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case I follow the same definition as VerifyShapeFunctionValues method defined just above. Why should we pass rGlobalCoordinates as a const in VerifyShapeFunctionsSecondDerivativesValues but not in VerifyShapeFunctionValues?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, mostly because if you do not change it then it is nice to know it is const ... if it is "incorrectly" not const in the other function i would not replicate the same mistake here ...

@@ -691,7 +691,7 @@ class KRATOS_API(KRATOS_CORE) GeometryUtils
* @param rResult the transform of the second derivative of the shape function on the integration point
*/
static void ShapeFunctionsSecondDerivativesTransformOnIntegrationPoint(
Matrix DN_DX,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Copy link
Member Author

@jgonzalezusua jgonzalezusua Sep 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RiccardoRossi, I have already changed it

@@ -519,7 +519,7 @@ class KRATOS_API(KRATOS_CORE) GeometryTesterUtility
GeometryType& rGeometry,
GeometryType::CoordinatesArrayType& rGlobalCoordinates,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, mostly because if you do not change it then it is nice to know it is const ... if it is "incorrectly" not const in the other function i would not replicate the same mistake here ...

@jgonzalezusua jgonzalezusua merged commit e0d67b3 into master Sep 27, 2023
11 checks passed
@jgonzalezusua jgonzalezusua deleted the second_shape_derivatives_transform_implementation branch September 27, 2023 08:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants