Implement Hessians and Identity Mapping for embedded elements#1257
Implement Hessians and Identity Mapping for embedded elements#1257henrij22 wants to merge 11 commits intoFerrite-FEM:masterfrom
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1257 +/- ##
==========================================
- Coverage 94.19% 0.00% -94.20%
==========================================
Files 40 40
Lines 6662 6628 -34
==========================================
- Hits 6275 0 -6275
- Misses 387 6628 +6241 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
lijas
left a comment
There was a problem hiding this comment.
Nice!
Can you also add the hessian equation (for embeded elements) to the docs, similar to how we do it here: https://ferrite-fem.github.io/Ferrite.jl/stable/topics/FEValues/#Identity-mapping
And add a reference to where it is taken from (or perhaps show the derivation :) )
| J += otimes_helper(x[j], dMdξ) | ||
|
|
||
| # J += x[j] ⊗ dMdξ | ||
| # H += x[j] ⊗ d2Mdξ2 |
There was a problem hiding this comment.
where did the computation of the hessian go?
There was a problem hiding this comment.
Aha, I only added it in above. This code then might not be tested atm. Also, what is the difference between calculate_mapping(gip::ScalarInterpolation) and calculate_mapping(geo_mapping::GeometryMapping). They seem quite similar.
| @test shape_hessian(cv_ref2, qp, 1)[1, 1, 1] ≈ shape_hessian(cv_ref2n, qp, 1)[1, 1, 1] | ||
| @test shape_hessian(cv_ref2, qp, 1)[1, 2, 1] ≈ shape_hessian(cv_ref2n, qp, 1)[1, 2, 1] | ||
| @test shape_hessian(cv_ref2, qp, 1)[2, 1, 1] ≈ shape_hessian(cv_ref2n, qp, 1)[2, 1, 1] | ||
| @test shape_hessian(cv_ref2, qp, 1)[2, 2, 1] ≈ shape_hessian(cv_ref2n, qp, 1)[2, 2, 1] |
There was a problem hiding this comment.
I think we can add tests for the function_hessian also, as we do here:
coords_nl = [x + rand(x) * 0.01 for x in coords] # add some displacement to nodes
reinit!(cv, coords_nl)
_ue_nl = [u_funk(coords_nl[i], V, G, H) for i in 1:n_basefunc_base]
ue_nl = reinterpret(Float64, _ue_nl)
for i in 1:getnquadpoints(cv)
xqp = spatial_coordinate(cv, i, coords_nl)
Hqp, Gqp, Vqp = Tensors.hessian(x -> function_value_from_physical_coord(func_interpol, coords_nl, x, ue_nl), xqp, :all)
@test function_value(cv, i, ue_nl) ≈ Vqp
@test function_gradient(cv, i, ue_nl) ≈ Gqp
if update_hessians
@test Ferrite.function_hessian(cv, i, ue_nl) ≈ Hqp
end
end
Can you add a similar test in this @testset for hessians? (I am not sure if function_value_from_physical_coord works with embedded elements)
There was a problem hiding this comment.
This might be more difficult than i first thought. For the embedded case, the function_value_from_physical_coord would need some signed distance search to find the parametric coord on the surface
| @inline function dothelper(A::SMatrix{vdim, sdim}, B::SArray{Tuple{sdim, rdim, rdim}}) where {vdim, rdim, sdim} | ||
| return SArray{Tuple{vdim, rdim, rdim}}( | ||
| (dothelper(A[i, :], B)[j, k] for i in 1:vdim, j in 1:rdim, k in 1:rdim) | ||
| ) |
There was a problem hiding this comment.
I think this type of construction of SArrays is fine, but I dont know how efficiently the compiler can optimize it, maybe someone else can review this part :)
There was a problem hiding this comment.
You were right, there are a lot of calls in there.
This implementation takes 24 ns on my system, I found a better version which only takes about 2 ns
|
Thanks @lijas for the review. I will adress the rest of your points when I have more time :) |
|
I compared the results from function_hessian from the hessian computed with AD: The function value and gradient test passes, but the hessian does not. So I suspect that there is some error in you hessian computation. For this test to work, I needed to change this function to |
|
@lijas Thanks, okay then I have to take a second look. It's a bit tricky to see where the error could be, its either in the computation of the Hessian (of the geometry) or in the Edit: I think the error should be in |
|
@lijas So my idea to implement this was to use the existing derivation from https://ferrite-fem.github.io/Ferrite.jl/stable/topics/FEValues/#mapping_theory @tullio d2Ndx2[i, j] := Jinv[s, j] * d2Ndξ2[s, r] * Jinv[r, i]
@tullio d2Ndx2[i, j] += -dNdξ[r] * (Jinv[r, k] * H[k, p, s] * Jinv[p, i]) * Jinv[s, j]However it does not pass your test ... |
|
Hmm, i dont think the equations for the hessian for solids is directly transfereble to embedded elements (the first part in your code snippet maybe is, but not the the second part). Can I ask, what do you need the embedded hessian for? :) |
|
Yeah I figured ... unfortuntly :( |
|
Cool, I guess you are using Kirchhoff-Love theory then if you need the Hessian? How are you getting C^1 continuity? For fun, I was "vibe-mathing" with ChatGPT, and I think it was able to derive the hessian. Perhaps an approach you can take if you dont find any good reference in the litterature haha. |
|
@lijas Haha good idea. |
IMO please keep spamming :D (Or make a separate discussion/issue for shell implementations as this is something the current support is not very good for). These discussions are often super-useful for anyone wanting to implement these things in the future! |
|
Perfect :D |
Just noting that I'm currently trying to push this one over the finish line - so if you want to try stuff with that functionality do feel free to and happy to get feedback on this one! |
|
@KnutAM thanks for the heads up. The mixed tensors look great! |
|
I haven't worked much with shells, but I think some key issues (that you might already have hit/solved). If you already have derived things in this direction that you could share, that would be nice and perhaps we can push it in the right direction. I think it could be useful to see the complete formulation that you are aiming at (not necessarily in research but say the KL-formulation for curved shells):
|
|
I think the master thesis you linked to uses the gradient/hessian w.r.t surface coordiantes, e.g dN/ds where s is a coordinates along the surface (dim(s) = rdim). This PR implements dN/dX where dim(X) = sdim. In my experience, shell formulation are often expressed and implemented in terms of dN/ds because the constituve law often requires it, so it would be nice to have this aswell. But I dont know if it is easy to put this in to CellValues directly, or if a new EmbeddedCellValues would be easier. |
Good point! I'm unsure though how we add in that |
|
Hi, [1] J. Kiendl, K.-U. Bletzinger, J. Linhard, und R. Wüchner, „Isogeometric shell analysis with Kirchhoff–Love elements“, Computer Methods in Applied Mechanics and Engineering, Bd. 198, Nr. 49–52, S. 3902–3914, Nov. 2009, doi: 10.1016/j.cma.2009.08.013. |
This does not correctly work at the moment
This implements two things:
Linking also for reference : Ferrite-FEM/Tensors.jl#188