- Thank you received: 6
co-normal value on a 1D surface segment
- Guosheng Fu
- Topic Author
- Offline
- Elite Member
Less
More
3 years 4 months ago #3852
by Guosheng Fu
Replied by Guosheng Fu on topic co-normal value on a 1D surface segment
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
Best,
Guosheng
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
- mneunteufel
- Offline
- Premium Member
Less
More
- Thank you received: 59
3 years 4 months ago #3855
by mneunteufel
Replied by mneunteufel on topic co-normal value on a 1D surface segment
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.
With this I got the correct results for your minimal example.
Best,
Michael
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]) )
Best,
Michael
3 years 4 months ago #3856
by joachim
Replied by joachim on topic co-normal value on a 1D surface segment
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
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()
- Guosheng Fu
- Topic Author
- Offline
- Elite Member
Less
More
- Thank you received: 6
3 years 4 months ago #3862
by Guosheng Fu
Replied by Guosheng Fu on topic co-normal value on a 1D surface segment
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?!
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()
- mneunteufel
- Offline
- Premium Member
Less
More
- Thank you received: 59
3 years 4 months ago #3863
by mneunteufel
Replied by mneunteufel on topic co-normal value on a 1D surface segment
Hi Guosheng,
a definedon-check was missing in the HDivSurface, should be fixed in the next nightly-build.
Best,
Michael
a definedon-check was missing in the HDivSurface, should be fixed in the next nightly-build.
Best,
Michael
- Guosheng Fu
- Topic Author
- Offline
- Elite Member
Less
More
- Thank you received: 6
3 years 4 months ago #3865
by Guosheng Fu
Replied by Guosheng Fu on topic co-normal value on a 1D surface segment
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:
This has been a very fruitful discussion! Thanks again for the quick responses.
Best,
Guosheng
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.
Best,
Guosheng
Attachments:
Time to create page: 0.111 seconds