Forum Message

 

 

We have moved the forum to https://forum.ngsolve.org . This is an archived version of the topics until 05/05/23. All the topics were moved to the new forum and conversations can be continued there. This forum is just kept as legacy to not invalidate old links. If you want to continue a conversation just look for the topic in the new forum.

Notice

The forum is in read only mode.

co-normal value on a 1D surface segment

More
2 years 9 months ago #3852 by Guosheng Fu
Hi Michael,

Please see the attached minimal example where I use the 1D normal. I need it for the evaluation of the element boundary of surface segments (codim 2). For this purpose, the co-normal shall (consistently) take -1 on the left end point and +1 on the right end point, which was what the gfn trying to do in the code.
I can not make it work using the consistent tangential vector
Code:
from ngsolve import * from ngsolve.meshes import MakeStructured2DMesh N = 4 mesh = MakeStructured2DMesh(nx=N, ny=1, mapping=lambda x, y: (x, y/N)) gfn = GridFunction(Compress(SurfaceL2(mesh, order=1, definedon=mesh.Boundaries("bottom")))) count = 0 for e in mesh.Elements(BND): if e.mat=="bottom": if e.vertices[0].nr > e.vertices[1].nr: gfn.vec[2*count+1] = -1 else: gfn.vec[2*count+1] = 1 count += 1 n = specialcf.normal(2) # HDiv interpolation gfInterp = GridFunction(HDiv(mesh, order=1)) gfInterp.Set(gfn*n, definedon=mesh.Boundaries("bottom")) Draw(gfInterp[1], mesh) ## V = Compress(H1(mesh, definedon=mesh.Boundaries("bottom"))) u,v = V.TnT() t = specialcf.tangential(2) t1 = specialcf.tangential(2, consistent=True) f = LinearForm(V) # This works f += t*t1*v*ds(element_boundary=True, definedon=mesh.Boundaries("bottom")) # f += gfn*v*ds(element_boundary=True, definedon=mesh.Boundaries("bottom")) f.Assemble() print(f.vec)

Best,
Guosheng
More
2 years 9 months ago #3855 by mneunteufel
Hi Guosheng,

yes, you are right, there is a detail missing for the consistent tangential vector for 1D manifolds.

Until this is fixed you can rotate the normal vector, which does not change from element to element.
Code:
n = specialcf.normal(2) t1 = CF( (-n[1],n[0]) )
With this I got the correct results for your minimal example.

Best,
Michael
More
2 years 9 months ago #3856 by joachim
Hi Guosheng,

we can now access Jacobians, and the coordinates from the reference element via special CoefficientFunctions (thx to Michael). This allows to build the co-normal vector.

The Logging - CoefficientFunction is useful to inspect the function evaluations.

- Joachim

Code:
from netgen.geom2d import unit_square from ngsolve import * mesh = Mesh(unit_square.GenerateMesh(maxh=0.3)) fes = SurfaceL2(mesh, order=1) u,v = fes.TnT() f = LinearForm(fes) t = specialcf.tangential(2) jac = specialcf.JacobianMatrix(2,1)[:,0] xref = specialcf.xref(1) conormal = (2*xref[0]-1)*jac from ngsolve.fem import LoggingCF conormal = LoggingCF (conormal) f += conormal*t *v * ds("bottom", element_boundary=True) f.Assemble()
More
2 years 9 months ago #3862 by Guosheng Fu
Thanks!
I've now moved to a 3D mesh with a embedded 2D surface. I use mixed FEM to discrete a Laplace operator on the surface.
The following test case does not work: mesh is a unit cube, and the "flat surface" is simply its top boundary.
I use HDivSurface/SurfaceL2 spaces to build the finite element pair on "top" boundary, but it seems that I can not use these spaces directly here as the bilinear form assembler complained about inconsistent # of DOFs. Any idea what's going on?!
Code:
from ngsolve.meshes import MakeStructured3DMesh from ngsolve import * mesh = MakeStructured3DMesh(hexes=False, nx=10, ny=10, nz=2) V = Compress(HDivSurface(mesh, order=1, definedon=mesh.Boundaries("top"))) W = Compress(SurfaceL2(mesh, order=0, definedon=mesh.Boundaries("top"))) fes = V*W (u, p), (v, q) = fes.TnT() a = BilinearForm(fes) a += (u.Trace()*v.Trace()-div(u).Trace()*q.Trace()-p.Trace()*div(v).Trace())*ds("top") a.Assemble()
More
2 years 9 months ago #3863 by mneunteufel
Hi Guosheng,

a definedon-check was missing in the HDivSurface, should be fixed in the next nightly-build.

Best,
Michael
More
2 years 9 months ago #3865 by Guosheng Fu
Hi Michael,

Thanks for the very quick fix. I will check it out.
Also, I just realized that your co-normal is not exactly what I am looking for... I haven't express the problem clear enough. In the attached file, I depicted what I want: a scalar function a 1D surface mesh that acts exactly as the 1D normal direction for a plain 1D mesh, that is, given an orientation of the line segment, it should return a -1 on the left end of the segment and +1 on the right end of segment. (I don't think it should be called a co-normal as it is a lower dimensional quantity)... Since I couldn't function such a built-in function, the above surfaceL2 gridfunction gfn is a hacker that do the job.

Since the tangential/normal directions are quantities defined on edges, not vertices, the associated value on left/right endpoints of the segments will always be the same, which is not what I want.

*** More background: I use this "co-normal" to reinforce nodal continuity of a SurfaceL2 function:
Code:
# u is a surface L2 trial function # v is a H1 trial function # this bilinearform shall return nodal continuity of u (hybridized!) a += u*v*con*ds(element_boundary=True)

This has been a very fruitful discussion! Thanks again for the quick responses.


This browser does not support PDFs. Please download the PDF to view it: Download PDF



Best,
Guosheng
Attachments:
Time to create page: 0.148 seconds