Nodes inconsistency between 2D and 3D elements in GMSH - mesh

I am trying to produce a tetrahedral mesh of a cube. The problem I encounter is that a few nodes that are used to generate the triangular faces are then not used to generate any of the tetrahedral elements. Is there a way to avoid this?
This is the code.
cl__1 = 0.01;
Point(1) = {0, 0, 0, cl__1};
Point(2) = {1, 0, 0, cl__1};
Point(3) = {1, 1, 0, cl__1};
Point(4) = {0, 1, 0, cl__1};
Line(1) = {1, 2};
Line(2) = {2, 3};
Line(3) = {3, 4};
Line(4) = {4, 1};
Line Loop(5) = {4, 1, 2, 3};
Plane Surface(6) = {5};
Extrude {0, 0, 1} {
Surface{6};
}
Coherence;
Transfinite Line {1, 2, 3, 4, 9, 10, 11, 8, 18, 22, 13, 14} = 2 Using Progression 1;
Transfinite Surface {19};
Transfinite Surface {23};
Transfinite Surface {27};
Transfinite Surface {15};
Transfinite Surface {28};
Transfinite Surface {6};
Transfinite Volume{1} = {1, 2, 3, 4, 6, 10, 14, 5};
Physical Surface("top") = {28};
Physical Surface("bottom") = {6};
Physical Surface("x_min") = {15};
Physical Surface("x_max") = {23};
Physical Surface("y_min") = {19};
Physical Surface("y_max") = {27};
Physical Volume("bottom_volume") = {1};
Thanks
Jian

The result of that input gives these nodes:
$Nodes
8
1 0 0 0
2 1 0 0
3 1 1 0
4 0 1 0
5 0 1 1
6 0 0 1
7 1 0 1
8 1 1 1
$EndNodes
with these nodes you can define all the triangular faces and the tetrahedral elements that define that mesh (there is no inconsistency in my opinion).

Related

The current value is the maximum value in the most recent period

l = [5,1,1,1,5,3,6], and the expected returned data is [0, 0, 0, 0, 3, 0, 6]. Compare from right to left, if it is greater than, it will count cumulatively; if it is less than or equal to, it will interrupt the accumulation and start the next counting.
How to implement (numpy,pandas)?
pandas:
def TOPRANGE(S):
rt = np.zeros(len(S))
for i in range(1,len(S)): rt[i] = np.argmin(np.flipud(S[:i]<S[i]))
return rt.astype('int')
l = [5,1,1,1,5,3,6]
s = np.array(l)
TOPRANGE(s)
output: [0, 0, 0, 0, 3, 0, 0]
expected returned data is [0, 0, 0, 0, 3, 0, 6],Don't know how to solve it????
l = [5, 1, 1, 1, 5, 3, 6]
# l = [5, 1, 3, 6]
l.reverse(); out = []
for i in range(0,len(l)):
acc = 0
for j in range(i+1, len(l)):
if l[i] > l[j]: acc += 1
else: break # interrupt count
out.append(acc)
out.reverse(); out
Gives required output:
[0, 0, 0, 0, 3, 0, 6]
If I understand well the logic, this looks like an expanding comparison:
pure python
l = [5,1,3,6]
out = [sum(l[i]>x for x in l[:i]) for i in range(len(l))]
pandas
l = [5,1,3,6]
s = pd.Series(l)
out = s.expanding().apply(lambda x: sum(x.iloc[:-1].le(x.iloc[-1]))).astype(int)
out.tolist()
numpy:
l = [5,1,3,6]
a = np.array(l)
out = np.tril(a[:,None]>a).sum(1)
out.tolist()
output: [0, 0, 1, 3]

Some array indexing in numpy

lookup = np.array([60, 40, 50, 60, 90])
The values in the following arrays are equal to indices of lookup.
a = np.array([1, 2, 0, 4, 3, 2, 4, 2, 0])
b = np.array([0, 1, 2, 3, 3, 4, 1, 2, 1])
c = np.array([4, 2, 1, 4, 4, 0, 4, 4, 2])
array 1st column elements lookup value
a 1 --> 40
b 0 --> 60
c 4 --> 90
Maximum is 90.
So, first element of result is 4.
This way,
expected result = array([4, 2, 0, 4, 4, 4, 4, 4, 0])
How to get it?
I tried as:
d = np.vstack([a, b, c])
print (d)
res = lookup[d]
res = np.max(res, axis = 0)
print (d[enumerate(lookup)])
I got error
IndexError: only integers, slices (:), ellipsis (...), numpy.newaxis (None) and integer or boolean arrays are valid indices
Do you want this:
d = np.vstack([a,b,c])
# option 1
rows = lookup[d].argmax(0)
d[rows, np.arange(d.shape[1])]
# option 2
(lookup[:,None] == lookup[d].max(0)).argmax(0)
Output:
array([4, 2, 0, 4, 4, 4, 4, 4, 0])

Extract PhysicalFace as 2D mesh in fipy

I created a mesh with Gmsh (a surface with a hole and then extruded it). Now I would like to plot the model in individual slices after a simulation with e.g. the MatplotlibViewer (Mayavi does not work on both my computers). I had hoped that it would be possible to define a new net using mesh.physicalFaces, but if that is possible, I have not figured it out yet. My second attempt was to apply the mesh again with Gmsh up to the Extrude command. But the mesh corresponds not to that of the 3D version. Can somebody give me a clue on this? Also like just another approach to representation.
I am working on Win10, Fipy 3.1.3, Python 3.6
import numpy as np
from fipy import *
#%%
def func_mesh():
mesh = Gmsh3D('''
Geometry.OCCAutoFix = 0;
SetFactory("OpenCASCADE");
x = 1.;
bseg = 0.08;
bs= bseg*x;
ls = 2.1;
cl = 0.01;
radius = 0.006;
// Exterior (bounding box) of mesh
Point(1) = {0, 0, 0, cl};
Point(2) = {0, bs, 0, cl};
Point(4) = { bs, 0, 0, cl};
Point(3) = {bs, bs, 0, cl};
Line(1) = {1, 2};
Line(2) = {2, 3};
Line(3) = {3, 4};
Line(4) = {4, 1};
Line Loop (21) = {1,2,3,4};
//Circle
Point(5) = {bseg/2 - radius, bseg/2, 0, cl};
Point(6) = {bseg/2, bseg/2 + radius, 0, cl};
Point(7) = { bseg/2 + radius, bseg/2, 0, cl};
Point(8) = {bseg/2, bseg/2 - radius, 0, cl};
Point(9) = {bseg/2, bseg/2, 0, cl};
Circle(10) = {5,9,6};
Circle(11) = {6,9,7};
Circle(12) = {7,9,8};
Circle(13) = {8,9,5};
Line Loop(22) = {10,11,12,13};
Plane Surface(40) = {22}; //cycl
Plane Surface(15) = {21, 22}; //Surface with a hole
id[] = Extrude {0, 0, ls} {Surface{15}; Layers{210}; Recombine;};
Surface Loop(2) = {46, 45, 48, 47, 49, 41, 44, 43, 42, 15};
Physical Volume("Vol") = {id[]};
Physical Surface("surf_ges") = {41, 42, 43, 44, 49, 47, 45, 48, 46, 15};
Physical Surface("HX") = {45, 46, 48, 47};
Physical Surface("Extr") = {15};
''')
return mesh
mesh = func_mesh()
x,y,z = mesh.cellCenters
X,Y,Z = mesh.faceCenters
tS = CellVariable(name="storage",
mesh=mesh,
value=367.,
hasOld=True)
submesh = mesh.physicalFaces['Extr']
xsub, ysub = submesh.cellCenters
tSslice = CellVariable(name = 'tSsclice',
mesh = submesh,
value = tS[z== z[0]])
viewer = MatplotlibViewer(vars = tSslice)
The error message for this attemp is: AttributeError: 'binOp' object has no attribute 'cellCenters'.
If I redefine the mesh only until the extrude order I get:
"ValueError: too many values to unpack (expected 2)" because of the shape of tSslice.
I am grateful for any help
submesh is not a Mesh; it's a mask identifying which faces of mesh are included in the surface Extr.
FiPy has no facility for extracting a mesh out of another mesh. It should be feasible to create a Mesh2D using the submesh mask, mesh.vertexCoords, and mesh.faceVertexIDs, but it's not trivial.
In theory, you could invoke Gmsh2D with everything up to Plane Surface(15) = {21, 22}; //Surface with a hole, but I find that doesn't generate the same number of elements as your 3D slice at z == z[0].
Ahah, I see the issue. I thought the Extrude operation resulted in prismatic cells, but it does not. The cells are tetrahedral. Since the cells of mesh do not all have the same tetrahedral geometry, the cells that have their bases on Extr are not all guaranteed to have their centers at z == z[0]. A better way is to use FiPy's CellVariable interpolation to extract the values of tS at the coordinates of tSslice:
from fipy import *
geo = '''
Geometry.OCCAutoFix = 0;
SetFactory("OpenCASCADE");
x = 1.;
bseg = 0.08;
bs= bseg*x;
ls = 2.1;
cl = 0.01;
radius = 0.006;
// Exterior (bounding box) of mesh
Point(1) = {0, 0, 0, cl};
Point(2) = {0, bs, 0, cl};
Point(4) = { bs, 0, 0, cl};
Point(3) = {bs, bs, 0, cl};
Line(1) = {1, 2};
Line(2) = {2, 3};
Line(3) = {3, 4};
Line(4) = {4, 1};
Line Loop (21) = {1,2,3,4};
//Circle
Point(5) = {bseg/2 - radius, bseg/2, 0, cl};
Point(6) = {bseg/2, bseg/2 + radius, 0, cl};
Point(7) = { bseg/2 + radius, bseg/2, 0, cl};
Point(8) = {bseg/2, bseg/2 - radius, 0, cl};
Point(9) = {bseg/2, bseg/2, 0, cl};
Circle(10) = {5,9,6};
Circle(11) = {6,9,7};
Circle(12) = {7,9,8};
Circle(13) = {8,9,5};
Line Loop(22) = {10,11,12,13};
Plane Surface(40) = {22}; //cycl
Plane Surface(15) = {21, 22}; //Surface with a hole
id[] = Extrude {0, 0, ls} {Surface{15}; Layers{210}; Recombine;};
Surface Loop(2) = {46, 45, 48, 47, 49, 41, 44, 43, 42, 15};
Physical Volume("Vol") = {id[]};
Physical Surface("Extr") = {15};
'''
mesh = Gmsh3D(geo + '''
Physical Surface("surf_ges") = {41, 42, 43, 44, 49, 47, 45, 48, 46, 15};
Physical Surface("HX") = {45, 46, 48, 47};
'''
)
submesh = Gmsh2D(geo)
x,y,z = mesh.cellCenters
X,Y = submesh.cellCenters[..., submesh.physicalCells['Extr']]
Z = numerix.ones(X.shape) * z[0]
tS = CellVariable(name="storage",
mesh=mesh,
value=mesh.x * mesh.y * mesh.z,
hasOld=True)
tSslice = CellVariable(name = 'tSsclice',
mesh = submesh)
# interpolate values of tS at positions of tSslice
tSslice[..., submesh.physicalCells['Extr']] = tS(numerix.vstack([X, Y, Z]))
viewer = MatplotlibViewer(vars = tSslice)
Here, I use the same .geo script to define both mesh and submesh. I add the surf_ges and HX physical surfaces only to the definition of mesh, because otherwise all of these faces will be imported into submesh as well, although with an effective z value of 0, so they obscure the faces you're interested in.
Frankly, I think a better way to achieve a slice through 3D data like this is to use either a customized MayaviClient (see the Cahn-Hilliard sphere and sphereDaemon.py for an example) or export with a VTKViewer and then render your data slices with a tool like ParaView, VisIt, or Mayavi.

Two Material Circular Mesh - Gmsh

I have the following .geo for GMSH:
cl__1 = 1.125;
Point(1) = {0, 0, 0, cl__1};
Point(2) = {1, 0, 0, cl__1};
Point(3) = {1, 1, 0, cl__1};
Point(4) = {0, 1, 0, cl__1};
Point(5) = {0.350000,0.100000,cl__1};
Point(6) = {0.350000,0.350000,cl__1};
Point(7) = {0.100000,0.350000,cl__1};
Point(8) = {0.85,0.85,cl__1};
Line(1) = {1, 2};
Line(2) = {2, 3};
Line(3) = {3, 4};
Line(4) = {4, 1};
Circle(5) = {5,6,7};
Line(6) = {7,8};
Line(7) = {8,5};
Line Loop(1) = {1, 2, 3, 4};
Line Loop(2) = {5,6,7};
Plane Surface(1) = {1,2};
Plane Surface(2) = {2};
Circle {5} In Surface {2};
Line {6} In Surface {2};
Line {7} In Surface {2};
I have drawn exactly the geometry I want to build but somehow Gmsh is only meshing inside Plane Surface 2.
Is there anything wrong in this code?
The point definition for points 5 - 8 are not in plane z = 0 they are in plane (z = cl_1). A suggestion, when you write this kind of files try to arrange things in the following way:
cl_1 = 1.125;
Point(1) = {0 , 0 , 0, cl_1};
Point(2) = {1 , 0 , 0, cl_1};
Point(3) = {1 , 1 , 0, cl_1};
Point(4) = {0 , 1 , 0, cl_1};
Point(5) = {0.350000, 0.100000, 0, cl_1};
Point(6) = {0.350000, 0.350000, 0, cl_1};
Point(7) = {0.100000, 0.350000, 0, cl_1};
Point(8) = {0.85 , 0.85 , 0, cl_1};
Line(1) = {1, 2};
Line(2) = {2, 3};
Line(3) = {3, 4};
Line(4) = {4, 1};
Circle(5) = {5,6,7};
Line(6) = {7,8};
Line(7) = {8,5};
Line Loop(1) = {1, 2, 3, 4};
Line Loop(2) = {5,6,7};
Plane Surface(8) = {1, 2};
Plane Surface(9) = {2};
you can save lot of time only by inspection.

Wavefront OBJ import to OpenGL ES 2.0 problems

I finally finished building my Wavefront OBJ parser, but still have some issues rendering my test object (cube).
So this is how i have parsed my vertices and indices (faces) into arrays of data. I have ignored textures and normals for now.
Vertices:
v -0.307796 0.00433517 0
v 0.299126 0.00433517 0
v 0.299126 0.00433517 0.48337
v -0.307796 0.00433517 0.48337
v -0.307796 0.364153 0.48337
v 0.299126 0.364153 0.48337
v 0.299126 0.364153 0
v -0.307796 0.364153 0
As:
const Vertex Vertices[] = {
{-0.307796,0.00433517,0},
{0.299126,0.00433517,0},
{0.299126,0.00433517,0.48337},
{-0.307796,0.00433517,0.48337},
{-0.307796,0.364153,0.48337},
{0.299126,0.364153,0.48337},
{0.299126,0.364153,0},
{-0.307796,0.364153,0}
};
Faces:
f 7/1/1 3/2/2 2/3/3
f 3/4/4 7/5/5 6/6/6
f 5/7/7 1/8/8 4/9/9
f 1/10/10 5/11/11 8/12/12
f 7/13/13 1/14/14 8/15/15
f 1/16/16 7/17/17 2/18/18
f 3/19/19 5/20/20 4/21/21
f 5/22/22 3/23/23 6/24/24
f 5/25/25 7/26/26 8/27/27
f 7/28/28 5/29/29 6/30/30
f 3/31/31 1/32/32 2/33/33
f 1/34/34 3/35/35 4/36/36
As:
const GLubyte Indices[] = {
7,1,1, 3,2,2, 2,3,3,
3,4,4, 7,5,5, 6,6,6,
5,7,7, 1,8,8, 4,9,9,
1,10,10, 5,11,11, 8,12,12,
7,13,13, 1,14,14, 8,15,15,
1,16,16, 7,17,17, 2,18,18,
3,19,19, 5,20,20, 4,21,21,
5,22,22, 3,23,23, 6,24,24,
5,25,25, 7,26,26, 8,27,27,
7,28,28, 5,29,29, 6,30,30,
3,31,31, 1,32,32, 2,33,33,
1,34,34, 3,35,35, 4,36,36
};
Indices only as vertex positions:
const GLubyte Indices[] = {
7, 3, 2,
3, 7, 6,
5, 1, 4,
1, 5, 8,
7, 1, 8,
1, 7, 2,
3, 5, 4,
5, 3, 6,
5, 7, 8,
7, 5, 6,
3, 1, 2,
1, 3, 4
};
SetupVBO:
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
GLuint indexBuffer;
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
Renderingcode:
glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
CC3GLMatrix *projection = [CC3GLMatrix matrix];
float h = 4.0f * self.frame.size.height / self.frame.size.width;
[projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:4 andFar:10];
glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix);
CC3GLMatrix *modelView = [CC3GLMatrix matrix];
[modelView populateFromTranslation:CC3VectorMake(sin(CACurrentMediaTime()), 0, -7)];
_currentRotation += displayLink.duration * 90;
[modelView rotateBy:CC3VectorMake(_currentRotation, _currentRotation, 0)];
glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);
// 1
glViewport(0, 0, self.frame.size.width, self.frame.size.height);
// 2
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));
// 3
glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0);
And the result is pretty much nothing at all, so there must be something that im doing completely wrong.
Furthermore will the indices cause any problems since i have not initialized the normals or texture coords?
The Wavefront obj format says that if you have sequences of 3 in the face definitions then their meaning is:
vertex-index/vertex-texture-index/vector-normal-index
You are reading all of the indices into a single array GLubyte Indices[] and using it as it if was just the indices of the vertices.
If you want to do away with textures and normals, you need to take only the first number of every triplet.
In
f 6/1/1 3/2/2 2/3/3 7/4/4
The face is a quad of vertices of indices [6,3,2,7]. Using the indices array like you have requires that you tell OpenGl that the indices are multiplexed in triplets. It does not look like you do that. It also requires additional buffers for normal and texture coordinates.