bluemesh2d 0.1.1.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bluemesh2d/_version.py +24 -0
- bluemesh2d/aabb_tree/findball.py +121 -0
- bluemesh2d/aabb_tree/findtria.py +299 -0
- bluemesh2d/aabb_tree/maketree.py +147 -0
- bluemesh2d/aabb_tree/mapvert.py +72 -0
- bluemesh2d/aabb_tree/queryset.py +83 -0
- bluemesh2d/aabb_tree/scantree.py +124 -0
- bluemesh2d/dependencies.py +83 -0
- bluemesh2d/feedback.py +142 -0
- bluemesh2d/geom_util/boundary_util.py +216 -0
- bluemesh2d/geom_util/getiso.py +194 -0
- bluemesh2d/geom_util/poly_util.py +795 -0
- bluemesh2d/geom_util/proj_util.py +250 -0
- bluemesh2d/geomesh_util/border_util.py +283 -0
- bluemesh2d/geomesh_util/depth_field.py +333 -0
- bluemesh2d/geomesh_util/grd_util.py +1000 -0
- bluemesh2d/geomesh_util/interpolation_mesh.py +318 -0
- bluemesh2d/geomesh_util/merge_circumcenters.py +268 -0
- bluemesh2d/geomesh_util/water_polygon.py +406 -0
- bluemesh2d/hfun_util/build_hfun.py +589 -0
- bluemesh2d/hfun_util/hfun_dispersion.py +96 -0
- bluemesh2d/hfun_util/lfshfn.py +110 -0
- bluemesh2d/hfun_util/limhfn.py +65 -0
- bluemesh2d/hfun_util/make_constant_hfun.py +32 -0
- bluemesh2d/hfun_util/make_depth_hfun.py +51 -0
- bluemesh2d/hfun_util/smooth_and_precomput.py +188 -0
- bluemesh2d/hfun_util/trihfn.py +84 -0
- bluemesh2d/hjac_util/limgrad.py +105 -0
- bluemesh2d/mesh_ball/cdtbal1.py +38 -0
- bluemesh2d/mesh_ball/cdtbal2.py +104 -0
- bluemesh2d/mesh_ball/inv_2x2.py +61 -0
- bluemesh2d/mesh_ball/inv_3x3.py +72 -0
- bluemesh2d/mesh_ball/pwrbal2.py +134 -0
- bluemesh2d/mesh_ball/tribal2.py +27 -0
- bluemesh2d/mesh_cost/relhfn.py +62 -0
- bluemesh2d/mesh_cost/triang.py +59 -0
- bluemesh2d/mesh_cost/triarea.py +51 -0
- bluemesh2d/mesh_cost/trideg.py +44 -0
- bluemesh2d/mesh_cost/triscr.py +43 -0
- bluemesh2d/mesh_file/bnd_util.py +664 -0
- bluemesh2d/mesh_file/loadmsh.py +165 -0
- bluemesh2d/mesh_file/ugrid.py +308 -0
- bluemesh2d/mesh_util/cfmtri.py +118 -0
- bluemesh2d/mesh_util/deltri.py +131 -0
- bluemesh2d/mesh_util/idxtri.py +53 -0
- bluemesh2d/mesh_util/isfeat.py +90 -0
- bluemesh2d/mesh_util/minlen.py +46 -0
- bluemesh2d/mesh_util/setset.py +49 -0
- bluemesh2d/mesh_util/tricon.py +90 -0
- bluemesh2d/mesh_util/tridiv.py +187 -0
- bluemesh2d/meshgen.py +202 -0
- bluemesh2d/ortho_merge/constants.py +27 -0
- bluemesh2d/ortho_merge/geometry.py +64 -0
- bluemesh2d/ortho_merge/ortho_merge_iter.py +812 -0
- bluemesh2d/ortho_merge/orthogonalize.py +2989 -0
- bluemesh2d/pipeline.py +277 -0
- bluemesh2d/poly_data/airfoil.msh +958 -0
- bluemesh2d/poly_data/channel.msh +212 -0
- bluemesh2d/poly_data/islands.msh +13819 -0
- bluemesh2d/poly_data/lake.msh +612 -0
- bluemesh2d/poly_data/river.msh +690 -0
- bluemesh2d/poly_test/inpoly.py +105 -0
- bluemesh2d/poly_test/inpoly_mat.py +104 -0
- bluemesh2d/refine.py +972 -0
- bluemesh2d/smood.py +623 -0
- bluemesh2d/smooth.py +522 -0
- bluemesh2d/tricost.py +426 -0
- bluemesh2d/tridemo.py +723 -0
- bluemesh2d/triread.py +53 -0
- bluemesh2d-0.1.1.dev0.dist-info/METADATA +139 -0
- bluemesh2d-0.1.1.dev0.dist-info/RECORD +74 -0
- bluemesh2d-0.1.1.dev0.dist-info/WHEEL +5 -0
- bluemesh2d-0.1.1.dev0.dist-info/licenses/LICENSE +674 -0
- bluemesh2d-0.1.1.dev0.dist-info/top_level.txt +1 -0
bluemesh2d/tricost.py
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import matplotlib.pyplot as plt
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from .mesh_cost.relhfn import relhfn
|
|
5
|
+
from .mesh_cost.triang import triang
|
|
6
|
+
from .mesh_cost.trideg import trideg
|
|
7
|
+
from .mesh_cost.triscr import triscr
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def tricost(vert=None, conn=None, tria=None, tnum=None, hvrt=None):
|
|
11
|
+
"""Plot quality-metric histograms for a 2D triangle mesh.
|
|
12
|
+
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
vert : ndarray of shape (V, 2)
|
|
16
|
+
Vertex coordinates.
|
|
17
|
+
conn : ndarray of shape (E, 2)
|
|
18
|
+
Constrained edges.
|
|
19
|
+
tria : ndarray of shape (T, 3)
|
|
20
|
+
Triangle connectivity.
|
|
21
|
+
tnum : ndarray of shape (T, 1), optional
|
|
22
|
+
Part index per triangle.
|
|
23
|
+
hvrt : ndarray of shape (V,), optional
|
|
24
|
+
Vertex mesh-size values; when provided, also plots relative edge lengths.
|
|
25
|
+
|
|
26
|
+
Notes
|
|
27
|
+
-----
|
|
28
|
+
Displays histograms of element quality scores, angles, relative sizes
|
|
29
|
+
(when ``hvrt`` is given), and node degree.
|
|
30
|
+
|
|
31
|
+
References
|
|
32
|
+
----------
|
|
33
|
+
Translation of the MESH2D function ``TRICOST``.
|
|
34
|
+
Original MATLAB source: https://github.com/dengwirda/mesh2d
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
if not all(
|
|
38
|
+
isinstance(x, (np.ndarray, type(None))) for x in [vert, conn, tria, tnum, hvrt]
|
|
39
|
+
):
|
|
40
|
+
raise TypeError("tricost:incorrectInputClass - Incorrect input class.")
|
|
41
|
+
|
|
42
|
+
if vert is None or conn is None or tria is None:
|
|
43
|
+
raise ValueError("tricost: missing required inputs (vert, conn, tria).")
|
|
44
|
+
|
|
45
|
+
if vert.ndim != 2 or conn.ndim != 2 or tria.ndim != 2:
|
|
46
|
+
raise ValueError("tricost:incorrectDimensions - Inputs must be 2D arrays.")
|
|
47
|
+
|
|
48
|
+
if vert.shape[1] != 2 or conn.shape[1] < 2 or tria.shape[1] < 3:
|
|
49
|
+
raise ValueError("tricost:incorrectDimensions - Invalid input sizes.")
|
|
50
|
+
|
|
51
|
+
nvrt = vert.shape[0]
|
|
52
|
+
_ntri = tria.shape[0]
|
|
53
|
+
|
|
54
|
+
if np.min(conn[:, :2]) < 0 or np.max(conn[:, :2]) > nvrt:
|
|
55
|
+
raise ValueError("tricost:invalidInputs - Invalid EDGE input array.")
|
|
56
|
+
|
|
57
|
+
if np.min(tria[:, :3]) < 0 or np.max(tria[:, :3]) > nvrt:
|
|
58
|
+
raise ValueError("tricost:invalidInputs - Invalid TRIA input array.")
|
|
59
|
+
|
|
60
|
+
axpos31 = [0.125, 0.750, 0.800, 0.150]
|
|
61
|
+
axpos32 = [0.125, 0.450, 0.800, 0.150]
|
|
62
|
+
axpos33 = [0.125, 0.150, 0.800, 0.150]
|
|
63
|
+
|
|
64
|
+
axpos41 = [0.125, 0.835, 0.800, 0.135]
|
|
65
|
+
axpos42 = [0.125, 0.590, 0.800, 0.135]
|
|
66
|
+
axpos43 = [0.125, 0.345, 0.800, 0.135]
|
|
67
|
+
axpos44 = [0.125, 0.100, 0.800, 0.135]
|
|
68
|
+
|
|
69
|
+
fig = plt.figure(figsize=(6, 6))
|
|
70
|
+
fig.patch.set_facecolor("w")
|
|
71
|
+
|
|
72
|
+
if hvrt is not None and hvrt.size > 0:
|
|
73
|
+
ax1 = fig.add_axes(axpos41)
|
|
74
|
+
ax1.set_title("Quality score")
|
|
75
|
+
scrhist(triscr(vert, tria), "tria3", ax=ax1)
|
|
76
|
+
|
|
77
|
+
ax2 = fig.add_axes(axpos42)
|
|
78
|
+
ax2.set_title("Angles")
|
|
79
|
+
anghist(triang(vert, tria), "tria3", ax=ax2)
|
|
80
|
+
|
|
81
|
+
ax3 = fig.add_axes(axpos43)
|
|
82
|
+
ax3.set_title("Relative size")
|
|
83
|
+
hfnhist(relhfn(vert, tria, hvrt), "tria3", ax=ax3)
|
|
84
|
+
|
|
85
|
+
ax4 = fig.add_axes(axpos44)
|
|
86
|
+
ax4.set_title("Node degree")
|
|
87
|
+
deghist(trideg(vert, tria), "tria3", ax=ax4)
|
|
88
|
+
|
|
89
|
+
else:
|
|
90
|
+
ax1 = fig.add_axes(axpos31)
|
|
91
|
+
ax1.set_title("Quality score")
|
|
92
|
+
scrhist(triscr(vert, tria), "tria3", ax=ax1)
|
|
93
|
+
|
|
94
|
+
ax2 = fig.add_axes(axpos32)
|
|
95
|
+
ax2.set_title("Angles")
|
|
96
|
+
anghist(triang(vert, tria), "tria3", ax=ax2)
|
|
97
|
+
|
|
98
|
+
ax3 = fig.add_axes(axpos33)
|
|
99
|
+
ax3.set_title("Node degree")
|
|
100
|
+
deghist(trideg(vert, tria), "tria3", ax=ax3)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def mad(ff):
|
|
104
|
+
"""Compute the mean absolute deviation from the mean.
|
|
105
|
+
|
|
106
|
+
Parameters
|
|
107
|
+
----------
|
|
108
|
+
ff : array_like
|
|
109
|
+
Input values.
|
|
110
|
+
|
|
111
|
+
Returns
|
|
112
|
+
-------
|
|
113
|
+
mf : float
|
|
114
|
+
Mean absolute deviation.
|
|
115
|
+
|
|
116
|
+
References
|
|
117
|
+
----------
|
|
118
|
+
Translation of the MESH2D function ``MAD``.
|
|
119
|
+
Original MATLAB source: https://github.com/dengwirda/mesh2d
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
ff = np.asarray(ff, dtype=float)
|
|
123
|
+
mf = np.mean(np.abs(ff - np.mean(ff)))
|
|
124
|
+
return mf
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def deghist(dd, ty, ax=None):
|
|
128
|
+
"""Plot a histogram of node degree.
|
|
129
|
+
|
|
130
|
+
Parameters
|
|
131
|
+
----------
|
|
132
|
+
dd : array_like
|
|
133
|
+
Node degrees.
|
|
134
|
+
ty : str
|
|
135
|
+
Mesh type label (``'tria3'`` or ``'tria4'``).
|
|
136
|
+
ax : matplotlib.axes.Axes, optional
|
|
137
|
+
Axes to draw on; defaults to the current axes.
|
|
138
|
+
|
|
139
|
+
References
|
|
140
|
+
----------
|
|
141
|
+
Translation of the MESH2D function ``DEGHIST``.
|
|
142
|
+
Original MATLAB source: https://github.com/dengwirda/mesh2d
|
|
143
|
+
"""
|
|
144
|
+
if ax is None:
|
|
145
|
+
ax = plt.gca()
|
|
146
|
+
dd = np.asarray(dd).ravel()
|
|
147
|
+
be = np.arange(1, np.max(dd) + 1)
|
|
148
|
+
hc, _ = np.histogram(dd, bins=np.append(be, np.max(be) + 1))
|
|
149
|
+
|
|
150
|
+
k = (0.60, 0.60, 0.60)
|
|
151
|
+
|
|
152
|
+
# Histogram
|
|
153
|
+
ax.bar(be, hc, width=1.05, color=k, edgecolor=k)
|
|
154
|
+
|
|
155
|
+
ax.axis("tight")
|
|
156
|
+
ax.set_yticks([])
|
|
157
|
+
ax.set_xticks(np.arange(2, 13, 2))
|
|
158
|
+
ax.tick_params(axis="both", which="both", length=5, width=2)
|
|
159
|
+
ax.set_xlim([0, 12])
|
|
160
|
+
ax.set_xlabel("", fontsize=22)
|
|
161
|
+
|
|
162
|
+
# Axis label depends on the triangulation type
|
|
163
|
+
if ty == "tria4":
|
|
164
|
+
ax.text(-0.225, 0, r"$|d|_{\tau}$", ha="right", fontsize=22)
|
|
165
|
+
elif ty == "tria3":
|
|
166
|
+
ax.text(-0.225, 0, r"$|d|_{f}$", ha="right", fontsize=22)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def anghist(ad, ty, ax=None):
|
|
170
|
+
"""Plot a histogram of triangle angles.
|
|
171
|
+
|
|
172
|
+
Parameters
|
|
173
|
+
----------
|
|
174
|
+
ad : array_like
|
|
175
|
+
Internal angles in degrees.
|
|
176
|
+
ty : str
|
|
177
|
+
Mesh type label (``'tria3'`` or ``'tria4'``).
|
|
178
|
+
ax : matplotlib.axes.Axes, optional
|
|
179
|
+
Axes to draw on; defaults to the current axes.
|
|
180
|
+
|
|
181
|
+
References
|
|
182
|
+
----------
|
|
183
|
+
Translation of the MESH2D function ``ANGHIST``.
|
|
184
|
+
Original MATLAB source: https://github.com/dengwirda/mesh2d
|
|
185
|
+
"""
|
|
186
|
+
if ax is None:
|
|
187
|
+
ax = plt.gca()
|
|
188
|
+
ad = np.asarray(ad).ravel()
|
|
189
|
+
be = np.linspace(0.0, 180.0, 91)
|
|
190
|
+
bm = (be[:-1] + be[1:]) / 2.0
|
|
191
|
+
hc, _ = np.histogram(ad, bins=be)
|
|
192
|
+
|
|
193
|
+
if ty == "tria4":
|
|
194
|
+
poor = (bm < 10.0) | (bm >= 160.0)
|
|
195
|
+
okay = ((bm >= 10.0) & (bm < 20.0)) | ((bm >= 140.0) & (bm < 160.0))
|
|
196
|
+
good = ((bm >= 20.0) & (bm < 30.0)) | ((bm >= 120.0) & (bm < 140.0))
|
|
197
|
+
best = (bm >= 30.0) & (bm < 120.0)
|
|
198
|
+
elif ty == "tria3":
|
|
199
|
+
poor = (bm < 15.0) | (bm >= 150.0)
|
|
200
|
+
okay = ((bm >= 15.0) & (bm < 30.0)) | ((bm >= 120.0) & (bm < 150.0))
|
|
201
|
+
good = ((bm >= 30.0) & (bm < 45.0)) | ((bm >= 90.0) & (bm < 120.0))
|
|
202
|
+
best = (bm >= 45.0) & (bm < 90.0)
|
|
203
|
+
else:
|
|
204
|
+
raise ValueError("Type must be 'tria3' or 'tria4'.")
|
|
205
|
+
|
|
206
|
+
r = (0.85, 0.00, 0.00)
|
|
207
|
+
y = (1.00, 0.95, 0.00)
|
|
208
|
+
g = (0.00, 0.90, 0.00)
|
|
209
|
+
k = (0.60, 0.60, 0.60)
|
|
210
|
+
|
|
211
|
+
ax.bar(bm[poor], hc[poor], width=1.05, color=r, edgecolor=r)
|
|
212
|
+
ax.bar(bm[okay], hc[okay], width=1.05, color=y, edgecolor=y)
|
|
213
|
+
ax.bar(bm[good], hc[good], width=1.05, color=g, edgecolor=g)
|
|
214
|
+
ax.bar(bm[best], hc[best], width=1.05, color=k, edgecolor=k)
|
|
215
|
+
|
|
216
|
+
ax.axis("tight")
|
|
217
|
+
ax.set_yticks([])
|
|
218
|
+
ax.set_xticks(np.arange(0, 181, 30))
|
|
219
|
+
ax.set_xlim([0.0, 180.0])
|
|
220
|
+
ax.tick_params(axis="both", which="both", length=5, width=2, labelsize=14)
|
|
221
|
+
|
|
222
|
+
mina = max(1.000, np.min(ad))
|
|
223
|
+
maxa = min(179.0, np.max(ad))
|
|
224
|
+
|
|
225
|
+
mada_val = mad(ad)
|
|
226
|
+
|
|
227
|
+
ax.axvline(x=mina, color="r", linewidth=1.5)
|
|
228
|
+
ax.axvline(x=maxa, color="r", linewidth=1.5)
|
|
229
|
+
|
|
230
|
+
if mina > 25.0:
|
|
231
|
+
ax.text(
|
|
232
|
+
mina - 1.8, 0.90 * np.max(hc), f"{np.min(ad):.1f}", ha="right", fontsize=15
|
|
233
|
+
)
|
|
234
|
+
else:
|
|
235
|
+
ax.text(
|
|
236
|
+
mina + 1.8, 0.90 * np.max(hc), f"{np.min(ad):.1f}", ha="left", fontsize=15
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
if maxa < 140.0:
|
|
240
|
+
ax.text(
|
|
241
|
+
maxa + 1.8, 0.90 * np.max(hc), f"{np.max(ad):.1f}", ha="left", fontsize=15
|
|
242
|
+
)
|
|
243
|
+
else:
|
|
244
|
+
ax.text(
|
|
245
|
+
maxa - 1.8, 0.90 * np.max(hc), f"{np.max(ad):.1f}", ha="right", fontsize=15
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
if maxa < 100.0:
|
|
249
|
+
ax.text(
|
|
250
|
+
maxa - 16.0,
|
|
251
|
+
0.45 * np.max(hc),
|
|
252
|
+
r"$\bar{\sigma}_{\theta}\!=$",
|
|
253
|
+
ha="left",
|
|
254
|
+
fontsize=16,
|
|
255
|
+
)
|
|
256
|
+
ax.text(
|
|
257
|
+
maxa + 1.8, 0.45 * np.max(hc), f"{mada_val:.2f}", ha="left", fontsize=15
|
|
258
|
+
)
|
|
259
|
+
else:
|
|
260
|
+
ax.text(
|
|
261
|
+
maxa - 16.0,
|
|
262
|
+
0.45 * np.max(hc),
|
|
263
|
+
r"$\bar{\sigma}_{\theta}\!=$",
|
|
264
|
+
ha="left",
|
|
265
|
+
fontsize=16,
|
|
266
|
+
)
|
|
267
|
+
ax.text(
|
|
268
|
+
maxa + 1.8, 0.45 * np.max(hc), f"{mada_val:.3f}", ha="left", fontsize=15
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
if ty == "tria4":
|
|
272
|
+
ax.text(-9.0, 0.0, r"$\theta_{\tau}$", ha="right", fontsize=22)
|
|
273
|
+
elif ty == "tria3":
|
|
274
|
+
ax.text(-9.0, 0.0, r"$\theta_{f}$", ha="right", fontsize=22)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def scrhist(sc, ty, ax=None):
|
|
278
|
+
"""Plot a histogram of element quality scores.
|
|
279
|
+
|
|
280
|
+
Parameters
|
|
281
|
+
----------
|
|
282
|
+
sc : array_like
|
|
283
|
+
Quality scores in ``[0, 1]``.
|
|
284
|
+
ty : str
|
|
285
|
+
Mesh type label (``'tria3'``, ``'tria4'``, ``'dual3'``, or ``'dual4'``).
|
|
286
|
+
ax : matplotlib.axes.Axes, optional
|
|
287
|
+
Axes to draw on; defaults to the current axes.
|
|
288
|
+
|
|
289
|
+
References
|
|
290
|
+
----------
|
|
291
|
+
Translation of the MESH2D function ``SCRHIST``.
|
|
292
|
+
Original MATLAB source: https://github.com/dengwirda/mesh2d
|
|
293
|
+
"""
|
|
294
|
+
|
|
295
|
+
if ax is None:
|
|
296
|
+
ax = plt.gca()
|
|
297
|
+
sc = np.asarray(sc).ravel()
|
|
298
|
+
be = np.linspace(0.0, 1.0, 101)
|
|
299
|
+
bm = (be[:-1] + be[1:]) / 2.0
|
|
300
|
+
hc, _ = np.histogram(sc, bins=be)
|
|
301
|
+
|
|
302
|
+
if ty in ("tria4", "dual4"):
|
|
303
|
+
poor = bm < 0.25
|
|
304
|
+
okay = (bm >= 0.25) & (bm < 0.50)
|
|
305
|
+
good = (bm >= 0.50) & (bm < 0.75)
|
|
306
|
+
best = bm >= 0.75
|
|
307
|
+
elif ty in ("tria3", "dual3"):
|
|
308
|
+
poor = bm < 0.30
|
|
309
|
+
okay = (bm >= 0.30) & (bm < 0.60)
|
|
310
|
+
good = (bm >= 0.60) & (bm < 0.90)
|
|
311
|
+
best = bm >= 0.90
|
|
312
|
+
else:
|
|
313
|
+
raise ValueError("Type must be 'tria3','tria4','dual3' or 'dual4'.")
|
|
314
|
+
|
|
315
|
+
r = (0.85, 0.00, 0.00)
|
|
316
|
+
y = (1.00, 0.95, 0.00)
|
|
317
|
+
g = (0.00, 0.90, 0.00)
|
|
318
|
+
k = (0.60, 0.60, 0.60)
|
|
319
|
+
|
|
320
|
+
ax.bar(bm[poor], hc[poor], width=1.05 / 100, color=r, edgecolor=r)
|
|
321
|
+
ax.bar(bm[okay], hc[okay], width=1.05 / 100, color=y, edgecolor=y)
|
|
322
|
+
ax.bar(bm[good], hc[good], width=1.05 / 100, color=g, edgecolor=g)
|
|
323
|
+
ax.bar(bm[best], hc[best], width=1.05 / 100, color=k, edgecolor=k)
|
|
324
|
+
|
|
325
|
+
ax.axis("tight")
|
|
326
|
+
ax.set_yticks([])
|
|
327
|
+
ax.set_xticks(np.arange(0.0, 1.01, 0.2))
|
|
328
|
+
ax.set_xlim([0.0, 1.0])
|
|
329
|
+
ax.tick_params(axis="both", which="both", length=5, width=2, labelsize=14)
|
|
330
|
+
|
|
331
|
+
mins = max(0.010, np.min(sc))
|
|
332
|
+
_maxs = min(0.990, np.max(sc))
|
|
333
|
+
|
|
334
|
+
ax.axvline(x=mins, color="r", linewidth=1.5)
|
|
335
|
+
ax.axvline(x=np.mean(sc), color="r", linewidth=1.5)
|
|
336
|
+
|
|
337
|
+
if mins > 0.4:
|
|
338
|
+
ax.text(
|
|
339
|
+
mins - 0.01, 0.9 * np.max(hc), f"{np.min(sc):.3f}", ha="right", fontsize=15
|
|
340
|
+
)
|
|
341
|
+
else:
|
|
342
|
+
ax.text(
|
|
343
|
+
mins + 0.01, 0.9 * np.max(hc), f"{np.min(sc):.3f}", ha="left", fontsize=15
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
if np.mean(sc) > mins + 0.150:
|
|
347
|
+
ax.text(
|
|
348
|
+
np.mean(sc) - 0.01,
|
|
349
|
+
0.9 * np.max(hc),
|
|
350
|
+
f"{np.mean(sc):.3f}",
|
|
351
|
+
ha="right",
|
|
352
|
+
fontsize=15,
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
if ty == "tria4":
|
|
356
|
+
ax.text(
|
|
357
|
+
-0.04, 0.0, r"$\mathcal{Q}^{\mathcal{T}}_{\tau}$", ha="right", fontsize=22
|
|
358
|
+
)
|
|
359
|
+
elif ty == "tria3":
|
|
360
|
+
ax.text(-0.04, 0.0, r"$\mathcal{Q}^{\mathcal{T}}_{f}$", ha="right", fontsize=22)
|
|
361
|
+
elif ty == "dual4":
|
|
362
|
+
ax.text(
|
|
363
|
+
-0.04, 0.0, r"$\mathcal{Q}^{\mathcal{D}}_{\tau}$", ha="right", fontsize=22
|
|
364
|
+
)
|
|
365
|
+
elif ty == "dual3":
|
|
366
|
+
ax.text(-0.04, 0.0, r"$\mathcal{Q}^{\mathcal{D}}_{f}$", ha="right", fontsize=22)
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def hfnhist(hf, ty, ax=None):
|
|
370
|
+
"""Plot a histogram of relative mesh-size ratios.
|
|
371
|
+
|
|
372
|
+
Parameters
|
|
373
|
+
----------
|
|
374
|
+
hf : array_like
|
|
375
|
+
Ratio of actual to target edge length.
|
|
376
|
+
ty : str
|
|
377
|
+
Mesh type label (kept for API compatibility).
|
|
378
|
+
ax : matplotlib.axes.Axes, optional
|
|
379
|
+
Axes to draw on; defaults to the current axes.
|
|
380
|
+
|
|
381
|
+
References
|
|
382
|
+
----------
|
|
383
|
+
Translation of the MESH2D function ``HFNHIST``.
|
|
384
|
+
Original MATLAB source: https://github.com/dengwirda/mesh2d
|
|
385
|
+
"""
|
|
386
|
+
|
|
387
|
+
if ax is None:
|
|
388
|
+
ax = plt.gca()
|
|
389
|
+
hf = np.asarray(hf).ravel()
|
|
390
|
+
|
|
391
|
+
be = np.linspace(0.0, 2.0, 101)
|
|
392
|
+
bm = (be[:-1] + be[1:]) / 2.0
|
|
393
|
+
hc, _ = np.histogram(hf, bins=be)
|
|
394
|
+
|
|
395
|
+
poor = (bm < 0.40) | (bm >= 1.6)
|
|
396
|
+
okay = ((bm >= 0.40) & (bm < 0.60)) | ((bm >= 1.4) & (bm < 1.6))
|
|
397
|
+
good = ((bm >= 0.60) & (bm < 0.80)) | ((bm >= 1.2) & (bm < 1.4))
|
|
398
|
+
best = (bm >= 0.80) & (bm < 1.2)
|
|
399
|
+
|
|
400
|
+
r = (0.85, 0.00, 0.00)
|
|
401
|
+
y = (1.00, 0.95, 0.00)
|
|
402
|
+
g = (0.00, 0.90, 0.00)
|
|
403
|
+
k = (0.60, 0.60, 0.60)
|
|
404
|
+
|
|
405
|
+
ax.bar(bm[poor], hc[poor], width=1.05 / 100, color=r, edgecolor=r)
|
|
406
|
+
ax.bar(bm[okay], hc[okay], width=1.05 / 100, color=y, edgecolor=y)
|
|
407
|
+
ax.bar(bm[good], hc[good], width=1.05 / 100, color=g, edgecolor=g)
|
|
408
|
+
ax.bar(bm[best], hc[best], width=1.05 / 100, color=k, edgecolor=k)
|
|
409
|
+
|
|
410
|
+
ax.axis("tight")
|
|
411
|
+
ax.set_yticks([])
|
|
412
|
+
ax.set_xticks(np.arange(0.0, 2.1, 0.5))
|
|
413
|
+
ax.set_xlim([0.0, 2.0])
|
|
414
|
+
ax.tick_params(axis="both", which="both", length=5, width=2, labelsize=14)
|
|
415
|
+
|
|
416
|
+
maxhf = np.max(hf)
|
|
417
|
+
ax.axvline(x=maxhf, color="r", linewidth=1.5)
|
|
418
|
+
|
|
419
|
+
ax.text(maxhf + 0.02, 0.90 * np.max(hc), f"{maxhf:.2f}", ha="left", fontsize=15)
|
|
420
|
+
|
|
421
|
+
ax.text(
|
|
422
|
+
maxhf - 0.18, 0.45 * np.max(hc), r"$\bar{\sigma}_{h} =$", ha="left", fontsize=16
|
|
423
|
+
)
|
|
424
|
+
ax.text(maxhf + 0.02, 0.45 * np.max(hc), f"{mad(hf):.2f}", ha="left", fontsize=15)
|
|
425
|
+
|
|
426
|
+
ax.text(-0.10, 0.0, r"$h_{r}$", ha="right", fontsize=22)
|