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

Test coverage for PointEval with nonlinear geometries #820

Open
wants to merge 17 commits into
base: master
Choose a base branch
from

Conversation

termi-official
Copy link
Member

@termi-official termi-official commented Oct 13, 2023

Point evaluation on master just does not work on nonlinear geometries. Here is an attempt to make it work. Fixes #763 but might not completely fix the point eval.

TODO

  • docs
  • flexibility for inner solver not sure how. Should be a separate PR.
  • expose inner solver parameters
  • fix point eval for mixed-dimensional and embedded grids

@termi-official termi-official changed the title Try to fix PointEval for nonlinear geometris Try to fix PointEval for nonlinear geometries Oct 13, 2023
@codecov-commenter
Copy link

codecov-commenter commented Oct 18, 2023

Codecov Report

Attention: 16 lines in your changes are missing coverage. Please review.

Comparison is base (e806ed9) 93.27% compared to head (8b93b9b) 93.04%.

Files Patch % Lines
src/FEValues/GeometryMapping.jl 56.66% 13 Missing ⚠️
src/PointEvalHandler.jl 94.59% 2 Missing ⚠️
src/FEValues/common_values.jl 90.00% 1 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #820      +/-   ##
==========================================
- Coverage   93.27%   93.04%   -0.24%     
==========================================
  Files          36       36              
  Lines        5235     5276      +41     
==========================================
+ Hits         4883     4909      +26     
- Misses        352      367      +15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@termi-official termi-official marked this pull request as ready for review October 18, 2023 14:25
@@ -267,7 +267,7 @@ default_interpolation(::Type{Wedge}) = Lagrange{RefPrism,
default_interpolation(::Type{Pyramid}) = Lagrange{RefPyramid, 1}()

# TODO: Remove this, used for Quadrilateral3D
edges(c::Quadrilateral#=3D=#) = faces(c)
edges(c::C) where {C <: AbstractCell{<:AbstractRefShape{2}}} = faces(c)
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 hotfixes dof distribution on embedded elements.

@termi-official termi-official added the awaiting review PR is finished from the authors POV, waiting for feedback label Nov 15, 2023
src/PointEval/PointEvalHandler.jl Outdated Show resolved Hide resolved
src/Grid/utils.jl Outdated Show resolved Hide resolved
src/Grid/utils.jl Outdated Show resolved Hide resolved
src/Grid/utils.jl Outdated Show resolved Hide resolved
src/PointEval/PointEvalHandler.jl Outdated Show resolved Hide resolved
@termi-official termi-official changed the title Try to fix PointEval for nonlinear geometries Test coverage for PointEval with nonlinear geometries Jan 22, 2024
@termi-official
Copy link
Member Author

I moved the computation of J and x without the caches (i.e. GeometryMapping) into GeometryMapping.jl and common_values.jl and changed the signature for the PointEvalHandler to support also mixed-dimensional grids (which are e.g. obtained by mixing shells, beams and solid elements in one grid). These functions are up to further optimization in subsequent PRs (i.e. the stuff which I do in the GPU support PR).

I also fixed an oopsie in the line searcher (which we need to identify the cell boundary for nonlinear cells).

Docs have been added as suggested.

src/Grid/utils.jl Outdated Show resolved Hide resolved
Co-authored-by: Knut Andreas Meyer <knutam@gmail.com>
Copy link
Member

@KnutAM KnutAM left a comment

Choose a reason for hiding this comment

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

Nice work - really cool with the ever-increasing support for embedded elements!

  • I would suggest leaving the inclusion of sample_random_point into src to a separate pr for now.

  • I like the renaming of x to cell_coordinates, but on the other hand such a renaming is unrelated? If renamed it should probably also be renamed in the reinit! methods? Should this renaming take place in a separate pr then?

I'm unsure regarding iterations for embedded elements. I would have thought we should find the value of $\xi$ which gives zero distance to the sought coordinate, $\boldsymbol{x}_0$, projected onto the element. And then potentially say didn't find if the distance to the element surface is too large.

$$\begin{align} \boldsymbol{x}(\boldsymbol{\xi}) &= \boldsymbol{x}_i N_i(\boldsymbol{\xi})\\\ \boldsymbol{r}(\boldsymbol{\xi}) &= [\boldsymbol{x}(\boldsymbol{\xi}) - \boldsymbol{x}_0] \cdot \frac{\partial\boldsymbol{x}}{\partial \boldsymbol{\xi}}, \quad \text{Potentially normalizing each column in }\frac{\partial\boldsymbol{x}}{\partial \boldsymbol{\xi}} \ \\\ \frac{\partial\boldsymbol{r}}{\partial \boldsymbol{\xi}} &= [\boldsymbol{x}(\boldsymbol{\xi}) - \boldsymbol{x}_0] \cdot \frac{\partial^2\boldsymbol{x}}{\partial \boldsymbol{\xi}^2} + \left[\frac{\partial\boldsymbol{x}}{\partial \boldsymbol{\xi}}\right]^T \cdot \left[ \frac{\partial\boldsymbol{x}}{\partial \boldsymbol{\xi}} \right] \end{align}$$

I suppose the pinv updates are then doing this in some quasi-newton fashion? (But last time I checked, this is quite slow, so probably the above algorithm is faster even with the higher order derivative calculations?)

But since we are using autodiff anyway to compute the gradients of hessians of the base functions, perhaps it would be equally efficient to just define the residual function and just iterate on this? I.e.

function residual(ξ::Vec{dim}, x0::Vec{dim}, ip, cell_coordinates::AbstractVector{<:Vec{dim}) where dim
    return spatial_coordinate(ip, ξ, cell_coordinates) - x0
end
function residual(ξ::Vec{dim}, x0::Vec{dim}, ip, cell_coordinates::AbstractVector{<:Vec{dim}) where dim
    dxdξ, x = gradient(ξ_ -> spatial_coordinate(ip, ξ_, cell_coordinates), :all)
    # do scaling if desired or needed?
    return (x - x0) \cdot dxdξ
end

(And even if not used this modified residual, I suppose the first definition of residual can be used to remove the need for the calculate_mapping_and_spatial_coordinate functions?

src/PointEvalHandler.jl Outdated Show resolved Hide resolved
src/FEValues/GeometryMapping.jl Outdated Show resolved Hide resolved
src/FEValues/common_values.jl Outdated Show resolved Hide resolved
``\\mathbf{x} = \\sum\\limits_{i = 1}^n M_i (\\mathbf{\\xi}) \\mathbf{\\hat{x}}_i``.

where ``\\xi``is the coordinate of the given quadrature point `q_point` of the associated
quadrature rule.
"""
function spatial_coordinate(fe_v::AbstractValues, q_point::Int, x::AbstractVector{<:Vec})
Copy link
Member

Choose a reason for hiding this comment

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

Change to cell_coordinates here too then?

Copy link
Member Author

Choose a reason for hiding this comment

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

Here or separate PR?

src/PointEvalHandler.jl Outdated Show resolved Hide resolved
@termi-official
Copy link
Member Author

Thanks for taking the time @KnutAM and @fredrikekre !

* I would suggest leaving the inclusion of `sample_random_point` into `src` to a separate pr for now.

* I like the renaming of `x` to `cell_coordinates`, but on the other hand such a renaming is unrelated? If renamed it should probably also be renamed in the `reinit!` methods? Should this renaming take place in a separate pr then?

I am not a big fan of making many small 1-5 line PRs (i.e. add docs, move function with same name from one file to another, ..) due to the associated overhead and dependencies, but I can make many tiny PRs if it is preferred.

I'm unsure regarding iterations for embedded elements. I would have thought we should find the value of ξ which gives zero distance to the sought coordinate, x0, projected onto the element. And then potentially say didn't find if the distance to the element surface is too large.

I suppose the pinv updates are then doing this in some quasi-newton fashion? (But last time I checked, this is quite slow, so probably the above algorithm is faster even with the higher order derivative calculations?)

My initial idea was also to have better modularity for the inner solver, but I could not find a good way how to do it. The rationale behind the current Newton solver for embedded (nonlinear) stuff is that it does not converge to a root if the coordinate is not in the element. You can interpret the solution of the linear system in a least square sense, as pinv returns by default the Moore-Penrose pseudoinverse. The problem with the projection is that you need additional infrastructure to handle the projections properly. Both approaches are valid tho.

But since we are using autodiff anyway to compute the gradients of hessians of the base functions, perhaps it would be equally efficient to just define the residual function and just iterate on this? I.e.

function residual(ξ::Vec{dim}, x0::Vec{dim}, ip, cell_coordinates::AbstractVector{<:Vec{dim}) where dim
    return spatial_coordinate(ip, ξ, cell_coordinates) - x0
end
function residual(ξ::Vec{dim}, x0::Vec{dim}, ip, cell_coordinates::AbstractVector{<:Vec{dim}) where dim
    dxdξ, x = gradient(ξ_ -> spatial_coordinate(ip, ξ_, cell_coordinates), :all)
    # do scaling if desired or needed?
    return (x - x0) \cdot dxdξ
end

(And even if not used this modified residual, I suppose the first definition of residual can be used to remove the need for the calculate_mapping_and_spatial_coordinate functions?

I am not sure if I follow the idea here. So you are proposing to use a gradient descend over a Newton with line search as default? I think this will end up with the same issues as master for points near (or even on) element boundaries.

Co-authored-by: Knut Andreas Meyer <knutam@gmail.com>
@KnutAM
Copy link
Member

KnutAM commented Jan 23, 2024

I am not a big fan of making many small 1-5 line PRs (i.e. add docs, move function with same name from one file to another, ..) due to the associated overhead and dependencies, but I can make many tiny PRs if it is preferred.

I rather prefer the opposite, when one PR does one thing (of course - introducing a new feature should also include updated docs and test) and refactoring is left as a standalone pr as this makes the review easier. Furthermore, some changes such as the change from x to cell_coordinates in the function signature are easy and non-controversial and I feel confident review + merge on those. But algorithmic changes / new features etc. might require more discussions.

The reason for suggesting to wait with the inclusion of the testing functions was simply because I think a utils package or including these functions in core is worthwhile discussing, and would be bad to have that discussion stopping this pr.

I am not sure if I follow the idea here. So you are proposing to use a gradient descend over a Newton with line search as default? I think this will end up with the same issues as master for points near (or even on) element boundaries.

No, rather the opposite - the current implementation is a quasi-newton for embedded elements due to the pseudo-inverse. With that code the regular elements would have no change in algorithm, but with easy extension to the embedded elements (but there, it is not guaranteed that the problem is convex / has a solution, not sure if the pseudo inverse approach can circumvent this). I'm struggling with makie-issues, so to take a quick break I'll add a PR to this branch showing what I meant (and check if it actually works :)) (Edit: #876)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting review PR is finished from the authors POV, waiting for feedback
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bug in PointValues
5 participants