Skip to content

Added prevention of intersections in grid elements after deformation#1076

Merged
pcarruscag merged 8 commits intosu2code:developfrom
tollennaert:feature_invalidGridPrevention
Dec 23, 2020
Merged

Added prevention of intersections in grid elements after deformation#1076
pcarruscag merged 8 commits intosu2code:developfrom
tollennaert:feature_invalidGridPrevention

Conversation

@tollennaert
Copy link
Contributor

@tollennaert tollennaert commented Sep 20, 2020

Proposed Changes

After surface deformation, the surface points are checked for self-intersection within the FFD box. If that is the case, a recursive procedure is done to prevent those. After grid deformation, all elements are checked on convexity. If there are nonconvex elements, a procedure is started that starts from the undeformed mesh and recursively changes the deformation magnitude until no nonconvex elements are present.

Related Work

None that I know of.

PR Checklist

Put an X by all that apply. You can fill this out after submitting the PR. If you have any questions, don't hesitate to ask! We want to help. These are a guide for you to know what the reviewers will be looking for in your contribution.

  • I am submitting my contribution to the develop branch.

  • My contribution generates no new compiler warnings (try with the '-Wall -Wextra -Wno-unused-parameter -Wno-empty-body' compiler flags).

  • My contribution is commented and consistent with SU2 style.

  • I have added a test case that demonstrates my contribution, if necessary.

  • I have updated appropriate documentation (Tutorials, Docs Page, config_template.cpp) , if necessary.

  • With respect to the test case: this can be used with virtually any case that has deformation. If the scale in OPT_OBJECTIVE is set to a high enough value, the deformation will be so big that intersections will occur.

…orm deformation.

After deformation, the surface points are checked for self-intersection within the FFD box. If that is the case, a recursive procedure is done to prevent those. After grid deformation, all elements are checked on convexity. If there are nonconvex elements, a procedure is started that starts from the undeformed mesh and recursively changes the deformation magnitude until no nonconvex elements are present.
@pr-triage pr-triage bot added the PR: draft label Sep 20, 2020
Copy link
Member

@pcarruscag pcarruscag left a comment

Choose a reason for hiding this comment

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

Thank you for opening the PR Lennaertt, some comments below regarding making use of a few things we developed recently, and regarding our modernization efforts.

Comment on lines 387 to 404
for (iDim = 0; iDim < nDim; iDim++) {
edgeVector_1[iDim] = Coords_k[iDim] - Coords_i[iDim];
edgeVector_2[iDim] = Coords_j[iDim] - Coords_i[iDim];
}

/*--- Calculate cross product of edge vectors and its length---*/
ev1 = edgeVector_1;
ev2 = edgeVector_2;

crossProduct[0] = ev1[1]*ev2[2] - ev1[2]*ev2[1];
crossProduct[1] = ev1[2]*ev2[0] - ev1[0]*ev2[2];
crossProduct[2] = ev1[0]*ev2[1] - ev1[1]*ev2[0];

for (iDim = 0; iDim < nDim; iDim++) {
crossProductLength += crossProduct[iDim]*crossProduct[iDim];
}

crossProductLength = sqrt(crossProductLength);
Copy link
Member

Choose a reason for hiding this comment

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

There is a geometry toolbox that implements all these, please use it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Member

Choose a reason for hiding this comment

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

Thanks! There a few more things that the toolbox could do, like computing distance between 2 points, but we can do that latter.

Comment on lines 299 to 300
void CVolumetricMovement::ComputenNonconvexElements(CGeometry *geometry, bool Screen_Output) {
unsigned long iElem, PointCorners[8];
Copy link
Member

Choose a reason for hiding this comment

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

If this routine is not super expensive we should include it in the mesh quality metrics.

@bigfooted
Copy link
Contributor

Hi Lennaert, I've un-commented the items 'added a testcase' and 'added documentation'. We can use the testcase that you've worked on, and we can use one of your presentations as documentation, but it needs to be put somewhere.

@bigfooted
Copy link
Contributor

@tollennaert, can you comment on the points raised by @pcarruscag ? I think you tried to address all points in your latest update? That makes it clear to everybody that all points have been addressed. I hope you still have time for this.

@pcarruscag pcarruscag marked this pull request as ready for review December 1, 2020 17:26
@tollennaert
Copy link
Contributor Author

@tollennaert, can you comment on the points raised by @pcarruscag ? I think you tried to address all points in your latest update? That makes it clear to everybody that all points have been addressed. I hope you still have time for this.

I indeed tried to solve all issues that were mentioned earlier. Could you take another look to see whether I have done this well enough?

@tollennaert
Copy link
Contributor Author

Hi Lennaert, I've un-commented the items 'added a testcase' and 'added documentation'. We can use the testcase that you've worked on, and we can use one of your presentations as documentation, but it needs to be put somewhere.

With respect to the test case and documentation: I have tried to find the best location to put this, but I could not find this. How can this be done best?

@bigfooted
Copy link
Contributor

Hi Lennaert, I've un-commented the items 'added a testcase' and 'added documentation'. We can use the testcase that you've worked on, and we can use one of your presentations as documentation, but it needs to be put somewhere.

With respect to the test case and documentation: I have tried to find the best location to put this, but I could not find this. How can this be done best?

should we add a testcase to the SU2/TestCases/incomp_navierstokes repository?

Comment on lines +8199 to +8209
tuple<bool, unsigned short, unsigned short> GetFFD_IntPrev(void) {
return make_tuple(FFD_IntPrev, FFD_IntPrev_MaxIter, FFD_IntPrev_MaxDepth);
}

/*!
* \brief Get information about whether to do a check on convexity of the mesh elements.
* \param[out] ConvexityCheck: <code>TRUE</code> if convexity check is active; otherwise <code>FALSE</code>.
* \param[out] ConvexityCheck_MaxIter: Maximum number of iterations in the convexity check.
* \param[out] ConvexityCheck_MaxDepth: Maximum recursion depth in the convexity check.
*/
tuple<bool, unsigned short, unsigned short> GetConvexityCheck(void) {
Copy link
Member

Choose a reason for hiding this comment

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

Thanks for changing the return type 👍 these 2 methods can be const

* \brief Get the amount of nonconvex elements in the mesh.
* \param[out] nNonconvexElements- amount of nonconvex elements in the mesh
*/
unsigned long GetnNonconvexElements(void) {return nNonconvexElements;}
Copy link
Member

Choose a reason for hiding this comment

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

This one const too.

* \param[in] config - Definition of the particular problem.
*/
void SetSurface_Deformation(CGeometry *geometry, CConfig *config) override;
void SetSurface_Deformation(CGeometry *geometry, CConfig *config, su2double** totaldeformation = nullptr);
Copy link
Member

Choose a reason for hiding this comment

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

The compiler is probably giving a warning about this function no? (because it has the same signature but it no longer overrides, instead it "hides" the original virtual SetSurface_Deformation)

Comment on lines +273 to +275
TotalDeformation[iDV] = new su2double[config_container[iZone]->GetnDV_Value(iDV)];
for (iDV_Value = 0; iDV_Value < config_container[iZone]->GetnDV_Value(iDV); iDV_Value++){
TotalDeformation[iDV][iDV_Value] = 0.0;
Copy link
Member

Choose a reason for hiding this comment

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

You can use the following syntax to initialize to zero:
TotalDeformation[iDV] = new su2double[config_container[iZone]->GetnDV_Value(iDV)] ();
(note the () at the end).

Comment on lines 285 to 293
unsigned long iPoint, nPoint = geometry_container[iZone]->GetnPoint();
unsigned short iDim, nDim = geometry_container[iZone]->GetnDim();
su2double OriginalCoordinates[nPoint][nDim];

for (iPoint = 0; iPoint < nPoint; iPoint++) {
for (iDim = 0; iDim < nDim; iDim++) {
OriginalCoordinates[iPoint][iDim] = geometry_container[iZone]->nodes->GetCoord(iPoint, iDim);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

There is an easier way to do this.
auto OriginalCoordinates = geometry_container[iZone]->nodes->GetCoord();
or su2activematrix instead of auto.
This: su2double OriginalCoordinates[nPoint][nDim]; is actually not standard c++

@pcarruscag
Copy link
Member

Thank you @tollennaert, I added a few notes but if you don't have time we can take care of it after this is merged (I understand that your project is finished).
Regarding the testcase, ideally add it to TestCases/deformation (making it a regression, preferably in parallel_regression.py) and if possible use one of the existing grids (this should be easier than having to add a mesh file to the TestCases repo).
Finally it would be great if you could add a little more info on the options and how to use them, either in config_template or in the new testcase you add.

Copy link
Contributor

@TobiKattmann TobiKattmann left a comment

Choose a reason for hiding this comment

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

Hi @tollennaert, the code looks generally really tidy and thanks a lot for the contribution 💐
I have just a very few minor things, some of which are also up to debate.

With respect to the test case and documentation: I have tried to find the best location to put this, but I could not find this. How can this be done best?

For a start if you have a pdf, pptx you can share you can just dump them in here for now, so we can look at it together. And in terms of regression test I think just like pedro mentioned to take an existing testcase and modify it so it showcases your contributions. Or of course if you have a nice case at hand you can just add it as a new one.

As you have already finished your project it is ok if you dont want to spend any more time on it. But if you want to finish it: perfect, and disregard the following paragraph, otherwise:
Please allow us to push commits by checking one box on the side if it isn't enabled yet (not sure though who qualifies as 'maintainer' here). If you don't want us to push on your forks branch we could merge this and open a follow-up PR directly if changes are necessary.

Cheers, Tobi

Edit: Oh right and I didn't really understand what the depth-variables are for exactly tbh. I guess you half-en the DV_VALUE and check whether that solved the problem and try that a max of iter times. So what is the depth for 🤔

Comment on lines +2567 to +2568
/* DESCRIPTION: Procedure to prevent self-intersections within the FFD box based on Jacobian determinant */
addBoolOption("FFD_INTPREV", FFD_IntPrev, NO);
Copy link
Contributor

Choose a reason for hiding this comment

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

I am in favor of FFD_INTERSECTION_PREVENTION just for the cfg-name not the c++ variable name (same for the other two) to be a bit more intuitive. No need to save a few chars here imo

Comment on lines +2576 to +2577
/* DESCRIPTION: Convexity check on all mesh elements */
addBoolOption("CONVEXITY_CHECK", ConvexityCheck, NO);
Copy link
Contributor

Choose a reason for hiding this comment

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

And here I would go maybe for MESH_CONVEXITY_CHECK just to add a little more intuition


}

/*--- Set total deformation values in config ---*/
Copy link
Contributor

Choose a reason for hiding this comment

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

well, not anymore in config right?

Comment on lines +333 to +335
/*--- Calculate Jacobian determinant for FFD-deformation to check for self-intersection in FFD box.
Procedure from J.E. Gain & N.A. Dodgson, "Preventing Self-Intersection under Free Form Deformation".
IEEE transactions on Visualization and Computer Graphics, vol. 7 no. 4. October-December 2001 ---*/
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 for including the resource

Comment on lines +4919 to +4924
unsigned long iSurfacePoints;
unsigned short iMarker;
unsigned long negative_determinants = 0;

/*--- Loop over the surface points ---*/
for (iSurfacePoints = 0; iSurfacePoints < FFDBox->GetnSurfacePoint(); iSurfacePoints++) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Here one could use:

for(auto iSurfacePoints = 0ul; ...)

for unsigned long also for the i,j,kdegree loops below i guess the with 0us... but that's nothing important

}
}

unsigned long negative_determinants_local = negative_determinants; negative_determinants = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

I would spend 2 lines here.

for (iZone = 0; iZone < nZone; iZone++){

/*--- Initialize total deformation of design variables to zero ---*/
su2double **TotalDeformation;
Copy link
Contributor

Choose a reason for hiding this comment

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

Use su2activematrix instead of su2double**. from @pcarruscag prob still applies here in the new home of TotalDeformation?
You then would most likely

su2activematrix TotalDeformation;
TotalDeformation.resize(nDV,nDV_Value) = su2double(0.0);

... that resizing in the loop is not that nice, so I would like to hear pedros opinion before anything is changed here

Comment on lines +1356 to +1360
% Parameters for prevention of self-intersections within FFD box
FFD_INTPREV = YES
FFD_INTPREV_ITER = 10
FFD_INTPREV_DEPTH = 3

Copy link
Contributor

Choose a reason for hiding this comment

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

Here in the config template I would prefer to have an explanation for each option. Imo the best way is to have a suitable explanation in the CConfig.cpp and just pasting it here.

@tollennaert
Copy link
Contributor Author

Hello all,

My apologies for taking so much time to respond. As much as I would have liked to finish this part of the project nicely, I am afraid I must come to the conclusion that I have taken on too many responsibilities to finish the code andfinalize the pull request.

I have attached a pptx to this comment that explains a little more about how the procedures work, the "allow edits by maintainers" box is checked. If you have any questions for me I will still be available to answer them, but I am not able to actively work on this anymore. The test cases should be available for @bigfooted, is it possible for you to place them where they are required?

As for the depth that was mentioned in an earlier comment of @TobiKattmann : the depth is an option that can be used as a stopping criterion. For every iteration without problems the recursion depth is increased. This way, it can be used as a measure for how close to the limit you are going to stop, as opposed to stopping after the maximum amount of iterations.

invalidGridPrevention.pptx

@pcarruscag pcarruscag merged commit 90d156a into su2code:develop Dec 23, 2020
@pcarruscag
Copy link
Member

Merged because it is a pain to push to branches in forks.

@pcarruscag
Copy link
Member

@bigfooted please open a PR to add the testcases @tollennaert mentioned you have.

pcarruscag added a commit that referenced this pull request Dec 28, 2020
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.

5 participants