Skip to content

Commit 107a2fe

Browse files
committed
modified tutorial 6
1 parent 6e8e36d commit 107a2fe

File tree

2 files changed

+195
-81
lines changed

2 files changed

+195
-81
lines changed

tutorials/tutorial6/tutorial-6-ffd-rbf.ipynb

Lines changed: 163 additions & 39 deletions
Large diffs are not rendered by default.

tutorials/tutorial6/tutorial-6-ffd-rbf.py

Lines changed: 32 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,42 @@
1313
# The methodology that follows is very general and can be extended to many different scenario, since it basically requires only the coordinates of the nodes of the object geometry and of the (undeformed) initial mesh. For sake of simplicity, here we present the deformation of an [OpenFOAM](https://openfoam.org/) grid for simulating a 2D Navier-Stokes flow around a cylinder. We assume that this cilinder is the object to deform.
1414
# Even if the entire procedure is employable also when the deformation mapping applied to the initial object is unknown (we see in few lines that the required input is just the displacement of the initial object after the deformation), here we apply the *free-form deformation* method to the undeformed cylinder in order to parametrize its geometry.
1515

16-
# First of all, we import all the libraries which we're going to use:
17-
# - `numpy` and `matplotlib` for the generic scientific environment;
18-
# - `Smithers` for dealing with the OpenFOAM mesh;
19-
# - `PyGeM` for the object and mesh deformation.
20-
21-
# In[1]:
22-
16+
import sys
17+
import platform
18+
print(f"Python Version: {sys.version}")
19+
print(f"Platform: {sys.platform}")
20+
print(f"System: {platform.system()} {platform.release()}")
21+
22+
try:
23+
import pygem
24+
print(f"PyGeM version: {pygem.__version__}")
25+
except ImportError:
26+
print(f"PyGeM not found. Installing...")
27+
import subprocess
28+
subprocess.check_call([sys.executable, "-m", "pip", "install", "-e", ".[tut]"])
29+
import pygem
30+
print(f"PyGeM version: {pygem.__version__}")
2331

2432
import numpy as np
33+
np.random.seed(42)
34+
2535
import matplotlib.pyplot as plt
2636

2737
# mesh parsing
28-
from smithers.io.openfoamhandler import OpenFoamHandler
38+
try:
39+
import Ofpp
40+
except ImportError:
41+
print("Ofpp not found. Installing...")
42+
import subprocess
43+
subprocess.check_call([sys.executable, "-m", "pip", "install", "ofpp"])
44+
import Ofpp
45+
try:
46+
from smithers.io.openfoamhandler import OpenFoamHandler
47+
except ImportError:
48+
print("smithers not found. Installing from GitHub...")
49+
import subprocess
50+
subprocess.check_call([sys.executable, "-m", "pip", "install", "git+https://github.com/mathLab/Smithers.git"])
51+
from smithers.io.openfoamhandler import OpenFoamHandler
2952

3053
# interpolator
3154
from scipy.interpolate import Rbf
@@ -36,9 +59,6 @@
3659

3760
# Then we define the auxiliary function `scatter3d` which we're going to use often to plot several objects as lists of 3D points. You do not need to understand the exact details of this function since we are going to use it only to show the results:
3861

39-
# In[2]:
40-
41-
4262
def scatter3d(arr, figsize=(8, 8), s=10, draw=True, ax=None, alpha=1, labels=None):
4363
if ax is None:
4464
fig = plt.figure(figsize=figsize)
@@ -65,19 +85,13 @@ def scatter3d(arr, figsize=(8, 8), s=10, draw=True, ax=None, alpha=1, labels=Non
6585
#
6686
# As we mentioned before, in this tutorial we use the library `Smithers` to load the OpenFOAM mesh from the folder `openfoam_mesh` which serves as example. First of all, we use the method `read()` from the class `OpenFoamHandler` to load the data. This method returns a dictionary which contains all the informations available about the mesh, included the list of points (`mesh['points']`).
6787

68-
# In[3]:
69-
70-
7188
# we load the OpenFOAM mesh
7289
openfoam_handler = OpenFoamHandler()
7390
mesh = openfoam_handler.read("openfoam_mesh")
7491

7592

7693
# Moreover, the object returned by `read()` contains a list of points for each *boundary*, represented by a list of indexes which refers to `mesh['points']`. We can use these lists to obtain the coordinates of the points which compose the cylinder (which we call *obstacle*) and walls.
7794

78-
# In[4]:
79-
80-
8195
wall_keys = [b"inlet", b"outlet", b"top", b"bottom"]
8296
walls = mesh["points"][
8397
np.concatenate([mesh["boundary"][k]["points"] for k in wall_keys])
@@ -88,9 +102,6 @@ def scatter3d(arr, figsize=(8, 8), s=10, draw=True, ax=None, alpha=1, labels=Non
88102

89103
# At this point we can plot the obstacle and the walls using the auxiliary function `scatter3d`:
90104

91-
# In[5]:
92-
93-
94105
scatter3d([obstacle, walls], s=1, labels=["obstacle", "walls"])
95106

96107

@@ -102,9 +113,6 @@ def scatter3d(arr, figsize=(8, 8), s=10, draw=True, ax=None, alpha=1, labels=Non
102113
#
103114
# We use the `FFD` deformation from [PyGeM](https://github.com/mathLab/PyGeM) (for a reference check [this tutorial](http://mathlab.github.io/PyGeM/tutorial-1-ffd.html)) to deform the original object (the upper and lower faces of a cylinder). We create the new `FFD` object and set its attributes in order to create a simple deformation
104115

105-
# In[6]:
106-
107-
108116
ffd = FFD([2, 2, 2])
109117

110118
ffd.box_origin = np.array([-2.6, -2.6, -1.1])
@@ -119,9 +127,6 @@ def scatter3d(arr, figsize=(8, 8), s=10, draw=True, ax=None, alpha=1, labels=Non
119127

120128
# We then operate the deformation and plot the result, against the old version of the obstacle.
121129

122-
# In[7]:
123-
124-
125130
new_obstacle = ffd(obstacle)
126131
scatter3d([new_obstacle, obstacle], s=3, labels=["deformed", "original"])
127132

@@ -134,9 +139,6 @@ def scatter3d(arr, figsize=(8, 8), s=10, draw=True, ax=None, alpha=1, labels=Non
134139
# For a reference on the parameters available when using the class `RBF` from **PyGeM**, please check the [documentation](http://mathlab.github.io/PyGeM/rbf.html). We keep the default values for all the parameters except `radius`, for which we set `radius=5`. This parameter is a scaling coefficient which affects the shape of the radial basis function used for the interpolation.
135140
# A practical note: long story short, `RBF` solves a linear system to fit the input data. However the matrix representing our system may result singular if we pass more times the same point(s). To avoid this issue, we just extract the `unique` points, as show in the next cell.
136141

137-
# In[8]:
138-
139-
140142
undeformed_points = np.vstack([walls, obstacle])
141143
deformed_points = np.vstack([walls, new_obstacle])
142144

@@ -152,9 +154,6 @@ def scatter3d(arr, figsize=(8, 8), s=10, draw=True, ax=None, alpha=1, labels=Non
152154

153155
# As visual proof, we plot the original and deformed control points we pass to `RBF` constructor!
154156

155-
# In[9]:
156-
157-
158157
scatter3d(
159158
[rbf.original_control_points, rbf.deformed_control_points],
160159
s=0.5,
@@ -166,19 +165,13 @@ def scatter3d(arr, figsize=(8, 8), s=10, draw=True, ax=None, alpha=1, labels=Non
166165
#
167166
# We can use the `RBF.__call__()` method to determine the new position of the points which compose the mesh. This is a resource-intensive computation and may slow down the device on which you're running this notebook.
168167

169-
# In[10]:
170-
171-
172168
new_mesh_points = rbf(mesh["points"])
173169

174170

175171
# And basically that's all! The array `new_mesh_points` contains the new coordinates of the mesh points, and give us the possibility to store it in a new file or exploit them for some computation.
176172
#
177173
# The last thing we show here is the visualization of the deformed mesh. In order to plot the results we prefer a 2D scatter plot of the upper part of the mesh (`z=0.5`). Therefore we define the auxiliary function `upper_layer` which extracts the points at `z=0.5` from the given list of points.
178174

179-
# In[11]:
180-
181-
182175
def upper_layer(*arrs):
183176
points = arrs[0]
184177
idxes = points[:, 2] > 0
@@ -191,9 +184,6 @@ def upper_layer(*arrs):
191184

192185
# We can now plot the interpolated mesh, with the *deformed* and *original* obstacle.
193186

194-
# In[12]:
195-
196-
197187
plt.figure(figsize=(20, 8), dpi=300)
198188
plt.scatter(*upper_layer(new_mesh_points)[:, :2].T, s=0.2, label="Interpolated mesh")
199189
plt.scatter(*upper_layer(obstacle)[:, :2].T, s=1, color="g", label="Original obstacle")
@@ -217,4 +207,4 @@ def upper_layer(*arrs):
217207
plt.legend(prop={"size": 15}, markerscale=15)
218208
plt.title("New mesh [zoom]")
219209

220-
plt.show()
210+
plt.show()

0 commit comments

Comments
 (0)