Problem importing 3D Mesh by Gmsh in fipy - mesh

I am trying to import a 3D mesh produced with Gmsh in FiPy. A test with a 2D mesh worked fine. If the model then is extruded and imported with Gmsh3D I get an error message.
GmshException: Gmsh hasn't produced any cells! Check your Gmsh code.
I'm working on Win10 with Python 3.7.3, Fipy 3.1.3 and Gmsh 3.0.6 (as recommended).
The test2D.geo test file:
SetFactory("OpenCASCADE");
cl = 0.5;
bs = 2.;
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(5) = {1, 2};
Line(6) = {2, 3};
Line(7) = {3, 4};
Line(8) = {4, 1};
Line Loop(10) = {6, 7, 8, 5};
Plane Surface(1) = {10};
Extrude {0, 0, 1} {
Surface{1};
}
and:
from fipy import *
mesh = Gmsh3D("test2D.msh")
The error message is:
GmshException: Gmsh hasn't produced any cells! Check your Gmsh code.
I don't see my mistake and hope someone can help me here.
Thanks in advance
Edited for the Gmsh output:
Gmsh output:
Info : Running 'gmsh C:\Users\Tinka\AppData\Local\Temp\tmpj4zr8g_c.geo -3 -nopopup -format msh -o C:\Users\Tinka\AppData\Local\Temp\tmpnz1bp4vu.msh' [Gmsh 3.0.6, 1 node, max. 1 thread]
Info : Started on Tue May 28 19:50:42 2019
Info : Reading 'C:\Users\Tinka\AppData\Local\Temp\tmpj4zr8g_c.geo'...
Info : Done reading 'C:\Users\Tinka\AppData\Local\Temp\tmpj4zr8g_c.geo'
Info : Finalized high order topology of periodic connections
Info : Meshing 1D...
Info : Done meshing 1D (0 s)
Info : Meshing 2D...
Info : Done meshing 2D (0 s)
Info : Meshing 3D...
Info : Done meshing 3D (0 s)
Info : 0 vertices 0 elements
Info : Writing 'C:\Users\Tinka\AppData\Local\Temp\tmpnz1bp4vu.msh'...
Info : Done writing 'C:\Users\Tinka\AppData\Local\Temp\tmpnz1bp4vu.msh'
Info : Stopped on Tue May 28 19:50:42 2019

This problem with gmsh and spyder has been fixed in FiPy 3.3, released earlier today; thank you for reporting it.
The other problem you reported in the chat is different. As documented for Gmsh2D, but not Gmsh3D:
... // attention: if you use any "Physical" labels, you *must* label
... // all elements that correspond to FiPy Cells (Physical Surface in 2D
... // and Physical Volume in 3D) or Gmsh will not include them and FiPy
... // will not be able to include them in the Mesh.
...
... // note: if you do not use any labels, all Cells will be included.
Adding Physical Volumes("cells") = {1}; to your .geo script will remedy that issue.

I changed the name of the argument in Gmsh3D to test2D.geo and removed the first line from the geo file and things seem to be working.
>>> from fipy import Gmsh3D
>>> mesh = Gmsh("test2D.geo")
>>> print(mesh.cellCenters)
[[1.34821429 1.24404762 1.34821429 ...
...
I'm not sure what the first line does, but I get Error : Gmsh requires OpenCASCADE to add vertex and no vertices or cells are generated if it's included, but it isn't necessary for generating the mesh.
I think that FiPy Gmsh classes take both geo and msh formatted files, but the file name does need to refer to the actually file on disk.
I'm using FiPy version, 3.2+2.gccec299e, and Gmsh version, 3.0.6.

Related

Triangulated vtp File Plot Problem - matplotlib OpenFOAM vs Paraview Cut

maybe you can help me out with a right comment or hint for my problem.
Pretty easy, I would like to plot a 2D slice vtp file (OpenFOAM) via matplotlib as tricontourf plot.
1.) Creating the vtp slice by Paraview and saving as vtp file works like a charme
2.) Using the runtime vtp file, created by cuttingPlane - libsampling OpenFOAM creates a weird triangle order.
What am I missing?
Best,
def loadVTPFile(filename):
import vtk
from vtk.util.numpy_support import vtk_to_numpy
from vtk.util import numpy_support as npvtk
reader = vtk.vtkXMLPolyDataReader()
reader.SetFileName(filename)
reader.Update()
data = reader.GetOutput()
points = data.GetPoints()
npts = points.GetNumberOfPoints()
x = vtk_to_numpy(points.GetData())
triangles= vtk_to_numpy(data.GetPolys().GetData())
ntri = triangles.size // 4 # number of cells
tri = np.take(triangles,[n for n in range(triangles.size) if n%4 != 0]).reshape(ntri,3)
n_arrays = reader.GetNumberOfPointArrays()
for i in range(n_arrays):
print(reader.GetPointArrayName(i))
X = vtk_to_numpy(points.GetData())
x=X[:,0]
y=X[:,1]
z=X[:,2]
# Define the velocity components U=(u,v,w)
U = vtk_to_numpy(data.GetPointData().GetArray('UMean'))
u = U[:,0]
v = U[:,1]
w = U[:,2]
magU=np.sqrt(u**2+v**2+w**2)
p = vtk_to_numpy(data.GetPointData().GetArray('pMean'))
Ma = vtk_to_numpy(data.GetPointData().GetArray('MaMean'))
rho = vtk_to_numpy(data.GetPointData().GetArray('rhoMean'))
return x,y,z,u,v,w,magU,p,Ma,rho,tri
1st: Paraview vtp slice via matplotlib:
Paraview vtp slice via matplotlib
2nd image OpenFOAM cut via libsampling
2nd image OpenFOAM cut via libsampling
Thanks for your help
OpenFOAM vtp slice export:
cellPoint, triangulated true/false, interpolated true/false and so on...

Creating a mesh within spherical shell with gmsh 4.7.1

I'm trying to use gmsh 4.7.1 to create a mesh within a 3D volume, that is a sphere with a concentric spherical hole (in other words, I have a spherical shell). In order to do so, I wrote the following .geo file:
// Gmsh project created on Wed Feb 17 15:22:45 2021
SetFactory("OpenCASCADE");
//+
Sphere(1) = {0, 0, 0, 0.1, -Pi/2, Pi/2, 2*Pi};
//+
Sphere(2) = {0, 0, 0, 1, -Pi/2, Pi/2, 2*Pi};
//+
Surface Loop(3) = {2};
//+
Surface Loop(4) = {1};
//+
Volume(3) = {3, 4};
//+
Physical Surface(1) = {1};
//+
Physical Surface(2) = {2};
//+
Physical Volume(3) = {3};
But, as soon as I create a 3D mesh by using the 3D command in the gmsh gui, my inner hole gets meshed too, while I'd like to have no elements of the mesh within the hole.
What am I doing wrong? How can I obtain the desired result? Thank you.
There are several issues at play here:
Sphere command, already creates a volume, not surfaces as you expect.
due to the point above, the command Surface Loop(3) = {2}; is assumed to create a surface loop from a volume, which is 1) not a supported operation. 2) will try to use the surface with the tag 2. It is unclear, what it will do in reality (as a surface with the tag 2 probably still exists).
Thus, the Volume command gets some weird things as an input
and it is all connected with the fact that the characteristic length is not setup, thus the mesh density is quite arbitrary.
If you insist on using the OpenCASCADE kernel, you probably want to use boolean operations.
Here is the code I have with an arbitrarily chosen characteristic length of 0.05 for all the points defining the solid spherical shell:
SetFactory("OpenCASCADE");
Sphere(1) = {0, 0, 0, 0.1, -Pi/2, Pi/2, 2*Pi};
Sphere(2) = {0, 0, 0, 1, -Pi/2, Pi/2, 2*Pi};
BooleanDifference(3) = { Volume{2}; Delete; }{ Volume{1}; Delete; };
Characteristic Length{ PointsOf{ Volume{3}; } } = 0.05;
Visualization from Paraview of the produced mesh with clipping:

Exported mesh in Gmsh V2 Ascii Format is empty

I made a trinagle in Gmsh. The .geo file looks like this:
// Gmsh project created on Tue Jun 30 13:15:37 2020
SetFactory("OpenCASCADE");
//+
Point(1) = {0, 0, 0, 1.0};
//+
Point(2) = {1, 0, 0, 1.0};
//+
Point(3) = {0, 1, 0, 1.0};
//+
Line(1) = {1, 2};
//+
Line(2) = {2, 3};
//+
Line(3) = {3, 1};
//+
Curve Loop(1) = {1, 2, 3};
//+
Plane Surface(1) = {1};
Now I need a .msh V2 Ascii file. I export it (I tried checking the options "Save all elements" and "Save parametric coordinates" and I always get the following:
$MeshFormat
2.2 0 8
$EndMeshFormat
$Nodes
0
$EndNodes
$Elements
0
$EndElements
So it's basically empty and I just can't figure out whats wrong.
It is highly likely, that you have not generated the mesh yet. Thus, there are no elements to be exported.
Since you have a surface model, you are probably up for a 2-D mesh:
Mesh->2D
After that, you can proceed with exporting it in a .msh V2 format as you identified in your question.
The same can be achieved by pressing m->2 on the keyboard.
While this will work, the model you currently have is missing Physical Surfaces. And, potentially, Physical Lines if you are interested in 1-D meshes as well. By default, GMSH outputs all elements; however, very often one needs finer control over what mesh elements are exported and with which tags.
Your mesh is a 2D problem. You can generate the msh file in ascii v2 by exectuing in the terminal:
gmsh -2 <input_name>.geo -o <output_name>.msh -format msh2
The -2 indicates the dimension (for a 3D problem, it would be -3) and msh2 will save the file in ascii v2.

Exporting TFRecords training patches with Google Earth Engine (kernelSize issues)

I've been using GEE to export some training patches from Sentinel-2 to be used in Python.
I could make it work, by following the GEE guide https://developers.google.com/earth-engine/tfrecord, and using the Export.image.toDrive function and then I can parse the exported TFRecord file to reconstruct my tiles.
var image_export_options = {
'patchDimensions': [366, 366],
'maxFileSize': 104857600,
// 'kernelSize': [366, 366],
'compressed': true
}
Export.image.toDrive({
image: clipped_img.select(bands.concat(['classes'])),
description: 'PatchesExport',
fileNamePrefix: 'Oros_1',
scale: 10,
folder: 'myExportFolder',
fileFormat: 'TFRecord',
region: export_area,
formatOptions: image_export_options,
})
However, when I try to specify the kernelSize in the formatOptions (that was supposed to "overlaps adjacent tiles by [kernelSize[0]/2, kernelSize[1]/2]", according to the guide) the files are exported but the '*mixer.json' doesn't reflect the increased number of patches and I am not able to iterate through the patches afterwards. The following command crashes the google colab session:
image_dataset = tf.data.TFRecordDataset(str(path/(file_prefix+'-00000.tfrecord.gz')), compression_type='GZIP')
first = next(iter(image_dataset))
first
The weird is that the problem happens only when I add the kernelSize to the formatOptions.
After some time trying to overcome this issue, I realized a not well documented behavior when one uses the kernel size to export patches from GEE.
Bundled with the exported TFRecord, there exists one xml file called mixer.
It doesn't matter if we use:
'patchDimensions': [184, 184],
'kernelSize': [1, 1], #default for no overlapping
or
'patchDimensions': [184, 184],
'kernelSize': [184, 184], #half patch overlapping
The mixer file remains the same and no mention to the kernel/overlapping size:
{'patchDimensions': [184, 184],
'patchesPerRow': 8,
'projection': {'affine': {'doubleMatrix': [10.0,
0.0,
493460.0,
0.0,
-10.0,
9313540.0]},
'crs': 'EPSG:32724'},
'totalPatches': 40}
In the second case, if we try to parse the patches using tf.io.parse_single_example(example_proto, image_features_dict), where image_features_dict equals something like:
{'B2': FixedLenFeature(shape=[184, 184], dtype=tf.float32, default_value=None),
'B3': FixedLenFeature(shape=[184, 184], dtype=tf.float32, default_value=None),
'B4': FixedLenFeature(shape=[184, 184], dtype=tf.float32, default_value=None)}
it will raise the error:
_FallbackException: This function does not handle the case of the path where all inputs are not already EagerTensors.
Can't parse serialized Example. [Op:ParseExampleV2]
Instead, to parse these records which have kernelSize > 1, we have to consider patchDimentions + kernelSize as the resulting patch size, even though the mixer.xml file says on contraty. In this example, our patchSize would be 368 (original patch size + kernelSize). Be aware that for odd kernel sizes, the number to be added to the original patch size is kernelSize - 1.

Gmsh cannot mesh element inside a volume

I'm trying to make a mesh of a piece of beam with stirrup and bars, but I'm having some trouble with stirrup, it is inside the main domain, and I do not know how to solve it. I'm attaching the .geo file, hoping someone could help. Maybe there are other way to mesh it, I do not know.
SetFactory("OpenCASCADE");
// Input
Rectangle(1) = {0, 0, 0, 300, 300, 0};
Disk(2) = {50, 50, 0, 10, 10};
Disk(3) = {50,250,0,10,10};
Disk(4) = {250,250,0,10,10};
Disk(5) = {250,50,0,10,10};
Rectangle(6) = {30,30,146,240,240,10};
Rectangle(7) = {40,40,146,220,220,10};
// Start Operations
s() = BooleanFragments{ Surface{1}; Delete; }{ Surface{2,3,4,5}; Delete;};
ext() = Extrude{0,0,300} {Surface{s()}; Layers{10}; Recombine;};
st() = BooleanFragments{ Surface{6}; Delete;}{Surface{7}; Delete;};
Recursive Delete {Surface{7}; }
Extrude{0,0,10} {Surface{22}; Layers{10}; Recombine;}
BooleanFragments{ Volume{5}; Delete;}{Volume{6}; Delete;}
// Mesh Options all elements needs to be Hexa
Mesh.RecombineAll = 2;
Not a complete answer; however, I think I identified the problem that probably causes the major troubles:
The circular extrusions (cylinders) touch the stirrup exactly at the vertices, thus creating complications to OpenCASCADE-based BooleanFragments operation.
The following code:
SetFactory("OpenCASCADE");
// Input
Rectangle(1) = {0, 0, 0, 300, 300, 0};
Disk(2) = {52, 52, 0, 10, 10};
Disk(3) = {52,248,0,10,10};
Disk(4) = {248,248,0,10,10};
Disk(5) = {248,52,0,10,10};
Rectangle(6) = {30,30,146,240,240,10};
Rectangle(7) = {40,40,146,220,220,10};
// Start Operations
s() = BooleanFragments{ Surface{1}; Delete; }{ Surface{2,3,4,5}; Delete;};
ext() = Extrude{0,0,300} {Surface{s()}; Layers{10}; Recombine;};
st() = BooleanFragments{ Surface{6}; Delete;}{Surface{7}; Delete;};
Recursive Delete {Surface{7}; }
Extrude{0,0,10} {Surface{22}; Layers{10}; Recombine;}
BooleanFragments{ Volume{5}; Delete;}{Volume{6}; Delete;}
// Mesh Options all elements needs to be Hexa
Mesh.RecombineAll = 2;
where I slightly shifted the cylinders to the inside (50->52 and 250 -> 248) should not have the meshing problem.
However, this disconnects the cylinders from the loop and modifies the problem drastically. Here is a zoom on the problematic part in the original, unmodified setup.
So, what you required from the CAD tool, is to handle the merging of those two surfaces (the loop and the cylinder) automatically using BooleanFragments, which might be problematic, especially if one has to take floating-point arithmetic aspects into account.