capytaine 2.3__cp310-cp310-macosx_14_0_arm64.whl → 3.0.0a1__cp310-cp310-macosx_14_0_arm64.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.
- capytaine/.dylibs/libgcc_s.1.1.dylib +0 -0
- capytaine/.dylibs/libgfortran.5.dylib +0 -0
- capytaine/.dylibs/libquadmath.0.dylib +0 -0
- capytaine/__about__.py +7 -2
- capytaine/__init__.py +8 -12
- capytaine/bem/engines.py +234 -354
- capytaine/bem/problems_and_results.py +30 -21
- capytaine/bem/solver.py +205 -81
- capytaine/bodies/bodies.py +279 -862
- capytaine/bodies/dofs.py +136 -9
- capytaine/bodies/hydrostatics.py +540 -0
- capytaine/bodies/multibodies.py +216 -0
- capytaine/green_functions/{libs/Delhommeau_float32.cpython-310-darwin.so → Delhommeau_float32.cpython-310-darwin.so} +0 -0
- capytaine/green_functions/{libs/Delhommeau_float64.cpython-310-darwin.so → Delhommeau_float64.cpython-310-darwin.so} +0 -0
- capytaine/green_functions/abstract_green_function.py +2 -2
- capytaine/green_functions/delhommeau.py +50 -31
- capytaine/green_functions/hams.py +19 -13
- capytaine/io/legacy.py +3 -103
- capytaine/io/xarray.py +15 -10
- capytaine/meshes/__init__.py +2 -6
- capytaine/meshes/abstract_meshes.py +375 -0
- capytaine/meshes/clean.py +302 -0
- capytaine/meshes/clip.py +347 -0
- capytaine/meshes/export.py +89 -0
- capytaine/meshes/geometry.py +244 -394
- capytaine/meshes/io.py +433 -0
- capytaine/meshes/meshes.py +621 -676
- capytaine/meshes/predefined/cylinders.py +22 -56
- capytaine/meshes/predefined/rectangles.py +26 -85
- capytaine/meshes/predefined/spheres.py +4 -11
- capytaine/meshes/quality.py +118 -407
- capytaine/meshes/surface_integrals.py +48 -29
- capytaine/meshes/symmetric_meshes.py +641 -0
- capytaine/meshes/visualization.py +353 -0
- capytaine/post_pro/free_surfaces.py +1 -4
- capytaine/post_pro/kochin.py +10 -10
- capytaine/tools/block_circulant_matrices.py +275 -0
- capytaine/tools/lists_of_points.py +2 -2
- capytaine/tools/memory_monitor.py +45 -0
- capytaine/tools/symbolic_multiplication.py +31 -5
- capytaine/tools/timer.py +68 -42
- {capytaine-2.3.dist-info → capytaine-3.0.0a1.dist-info}/METADATA +8 -14
- capytaine-3.0.0a1.dist-info/RECORD +65 -0
- capytaine-3.0.0a1.dist-info/WHEEL +6 -0
- capytaine/bodies/predefined/__init__.py +0 -6
- capytaine/bodies/predefined/cylinders.py +0 -151
- capytaine/bodies/predefined/rectangles.py +0 -111
- capytaine/bodies/predefined/spheres.py +0 -70
- capytaine/green_functions/FinGreen3D/.gitignore +0 -1
- capytaine/green_functions/FinGreen3D/FinGreen3D.f90 +0 -3589
- capytaine/green_functions/FinGreen3D/LICENSE +0 -165
- capytaine/green_functions/FinGreen3D/Makefile +0 -16
- capytaine/green_functions/FinGreen3D/README.md +0 -24
- capytaine/green_functions/FinGreen3D/test_program.f90 +0 -39
- capytaine/green_functions/LiangWuNoblesse/.gitignore +0 -1
- capytaine/green_functions/LiangWuNoblesse/LICENSE +0 -504
- capytaine/green_functions/LiangWuNoblesse/LiangWuNoblesseWaveTerm.f90 +0 -751
- capytaine/green_functions/LiangWuNoblesse/Makefile +0 -18
- capytaine/green_functions/LiangWuNoblesse/README.md +0 -2
- capytaine/green_functions/LiangWuNoblesse/test_program.f90 +0 -28
- capytaine/green_functions/libs/__init__.py +0 -0
- capytaine/io/mesh_loaders.py +0 -1086
- capytaine/io/mesh_writers.py +0 -692
- capytaine/io/meshio.py +0 -38
- capytaine/matrices/__init__.py +0 -16
- capytaine/matrices/block.py +0 -592
- capytaine/matrices/block_toeplitz.py +0 -325
- capytaine/matrices/builders.py +0 -89
- capytaine/matrices/linear_solvers.py +0 -232
- capytaine/matrices/low_rank.py +0 -395
- capytaine/meshes/clipper.py +0 -465
- capytaine/meshes/collections.py +0 -334
- capytaine/meshes/mesh_like_protocol.py +0 -37
- capytaine/meshes/properties.py +0 -276
- capytaine/meshes/quadratures.py +0 -80
- capytaine/meshes/symmetric.py +0 -392
- capytaine/tools/lru_cache.py +0 -49
- capytaine/ui/vtk/__init__.py +0 -3
- capytaine/ui/vtk/animation.py +0 -329
- capytaine/ui/vtk/body_viewer.py +0 -28
- capytaine/ui/vtk/helpers.py +0 -82
- capytaine/ui/vtk/mesh_viewer.py +0 -461
- capytaine-2.3.dist-info/RECORD +0 -92
- capytaine-2.3.dist-info/WHEEL +0 -4
- {capytaine-2.3.dist-info → capytaine-3.0.0a1.dist-info}/LICENSE +0 -0
- {capytaine-2.3.dist-info → capytaine-3.0.0a1.dist-info}/entry_points.txt +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""Generate meshes of cylinders and disks"""
|
|
2
|
-
# Copyright (C) 2017-
|
|
2
|
+
# Copyright (C) 2017-2025 Matthieu Ancellin
|
|
3
3
|
# See LICENSE file at <https://github.com/capytaine/capytaine>
|
|
4
4
|
|
|
5
5
|
import logging
|
|
@@ -8,10 +8,8 @@ from itertools import product
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
from numpy import pi, cos, sin
|
|
10
10
|
|
|
11
|
-
from capytaine.meshes.geometry import xOz_Plane, yOz_Plane, Oz_axis
|
|
12
11
|
from capytaine.meshes.meshes import Mesh
|
|
13
|
-
from capytaine.meshes.
|
|
14
|
-
from capytaine.meshes.symmetric import TranslationalSymmetricMesh, AxialSymmetricMesh, ReflectionSymmetricMesh
|
|
12
|
+
from capytaine.meshes.symmetric_meshes import RotationSymmetricMesh, ReflectionSymmetricMesh
|
|
15
13
|
|
|
16
14
|
LOG = logging.getLogger(__name__)
|
|
17
15
|
|
|
@@ -61,9 +59,6 @@ def mesh_disk(*, radius=1.0, center=(0, 0, 0), normal=(0, 0, 1),
|
|
|
61
59
|
nr = int(np.ceil(radius / (np.sqrt(2) * faces_max_radius)))
|
|
62
60
|
ntheta = int(np.ceil(2*pi*radius / (np.sqrt(2) * faces_max_radius)))
|
|
63
61
|
|
|
64
|
-
if name is None:
|
|
65
|
-
name = f"disk_{next(Mesh._ids)}"
|
|
66
|
-
|
|
67
62
|
if reflection_symmetry and axial_symmetry:
|
|
68
63
|
raise NotImplementedError("Disks with both symmetries have not been implemented.")
|
|
69
64
|
|
|
@@ -77,13 +72,13 @@ def mesh_disk(*, radius=1.0, center=(0, 0, 0), normal=(0, 0, 1),
|
|
|
77
72
|
half_mesh = mesh_disk(radius=radius, _theta_max=_theta_max/2, resolution=(nr, ntheta//2),
|
|
78
73
|
center=(0, 0, 0), normal=(0, 0, 1),
|
|
79
74
|
reflection_symmetry=False, axial_symmetry=False, name=f"half_of_{name}")
|
|
80
|
-
mesh = ReflectionSymmetricMesh(half_mesh, plane=
|
|
75
|
+
mesh = ReflectionSymmetricMesh(half_mesh, plane='xOz', name=name)
|
|
81
76
|
|
|
82
77
|
elif axial_symmetry:
|
|
83
78
|
mesh_slice = mesh_disk(radius=radius, _theta_max=_theta_max/ntheta, resolution=(nr, 1),
|
|
84
79
|
center=(0, 0, 0), normal=(0, 0, 1),
|
|
85
80
|
reflection_symmetry=False, axial_symmetry=False, name=f"slice_of_{name}")
|
|
86
|
-
mesh =
|
|
81
|
+
mesh = RotationSymmetricMesh(mesh_slice, axis='z+', n=ntheta, name=name)
|
|
87
82
|
|
|
88
83
|
else:
|
|
89
84
|
theta_range = np.linspace(0, _theta_max, ntheta+1)
|
|
@@ -94,10 +89,8 @@ def mesh_disk(*, radius=1.0, center=(0, 0, 0), normal=(0, 0, 1),
|
|
|
94
89
|
|
|
95
90
|
mesh = Mesh(nodes, panels, name=name)
|
|
96
91
|
|
|
97
|
-
mesh.
|
|
98
|
-
mesh.
|
|
99
|
-
mesh.rotate_around_center_to_align_vectors(center, mesh.faces_normals[0], normal)
|
|
100
|
-
mesh.geometric_center = np.asarray(center, dtype=float)
|
|
92
|
+
mesh = mesh.rotated_such_that_vectors_are_aligned(mesh.faces_normals[0], normal)
|
|
93
|
+
mesh = mesh.translated(center, name=name)
|
|
101
94
|
return mesh
|
|
102
95
|
|
|
103
96
|
|
|
@@ -153,9 +146,6 @@ def mesh_vertical_cylinder(*, length=10.0, radius=1.0, center=(0, 0, 0),
|
|
|
153
146
|
ntheta = 2*int(np.ceil(pi*radius / (np.sqrt(2) * faces_max_radius)))
|
|
154
147
|
nz = int(np.ceil(length / (np.sqrt(2) * faces_max_radius)))
|
|
155
148
|
|
|
156
|
-
if name is None:
|
|
157
|
-
name = f"cylinder_{next(Mesh._ids)}"
|
|
158
|
-
|
|
159
149
|
LOG.debug(f"New vertical cylinder of length {length}, radius {radius} and resolution {resolution}, named {name}.")
|
|
160
150
|
|
|
161
151
|
if reflection_symmetry and axial_symmetry:
|
|
@@ -170,13 +160,13 @@ def mesh_vertical_cylinder(*, length=10.0, radius=1.0, center=(0, 0, 0),
|
|
|
170
160
|
resolution=(nr, ntheta//2, nz), reflection_symmetry=False, axial_symmetry=False,
|
|
171
161
|
name=f"half_{name}", _theta_max=_theta_max/2)
|
|
172
162
|
|
|
173
|
-
mesh = ReflectionSymmetricMesh(half_cylinder, plane=
|
|
163
|
+
mesh = ReflectionSymmetricMesh(half_cylinder, plane='yOz', name=name)
|
|
174
164
|
|
|
175
165
|
elif axial_symmetry:
|
|
176
166
|
|
|
177
167
|
mesh_slice = mesh_vertical_cylinder(length=length, radius=radius, resolution=(nr, 1, nz), center=(0, 0, 0),
|
|
178
168
|
reflection_symmetry=False, axial_symmetry=False, name=f"slice_of_{name}", _theta_max=_theta_max/ntheta)
|
|
179
|
-
mesh =
|
|
169
|
+
mesh = RotationSymmetricMesh(mesh_slice, axis='z+', n=ntheta, name=name)
|
|
180
170
|
|
|
181
171
|
else:
|
|
182
172
|
theta_range = np.linspace(0, _theta_max, ntheta+1)
|
|
@@ -196,15 +186,13 @@ def mesh_vertical_cylinder(*, length=10.0, radius=1.0, center=(0, 0, 0),
|
|
|
196
186
|
|
|
197
187
|
mesh = Mesh(nodes, panels, name=name)
|
|
198
188
|
|
|
199
|
-
mesh.
|
|
200
|
-
mesh.translate(center)
|
|
201
|
-
mesh.geometric_center = np.asarray(center, dtype=float)
|
|
189
|
+
mesh = mesh.translated(center, name=name)
|
|
202
190
|
return mesh
|
|
203
191
|
|
|
204
192
|
|
|
205
193
|
def mesh_horizontal_cylinder(*, length=10.0, radius=1.0, center=(0, 0, 0),
|
|
206
194
|
resolution=(2, 8, 10), faces_max_radius=None,
|
|
207
|
-
reflection_symmetry=False,
|
|
195
|
+
reflection_symmetry=False, name=None, _theta_max=2*pi):
|
|
208
196
|
"""Cylinder aligned along Ox axis.
|
|
209
197
|
|
|
210
198
|
Total number of panels = (2*resolution[0] + resolution[2])*resolution[1]
|
|
@@ -243,9 +231,6 @@ def mesh_horizontal_cylinder(*, length=10.0, radius=1.0, center=(0, 0, 0),
|
|
|
243
231
|
|
|
244
232
|
assert len(center) == 3, "Position of the center of a cylinder should be given a 3-ple of values."
|
|
245
233
|
|
|
246
|
-
if name is None:
|
|
247
|
-
name = f"cylinder_{next(Mesh._ids)}"
|
|
248
|
-
|
|
249
234
|
LOG.debug(f"New horizontal cylinder of length {length}, radius {radius} and resolution {resolution}, named {name}.")
|
|
250
235
|
|
|
251
236
|
nr, ntheta, nx = resolution
|
|
@@ -268,47 +253,28 @@ def mesh_horizontal_cylinder(*, length=10.0, radius=1.0, center=(0, 0, 0),
|
|
|
268
253
|
half_cylinder = mesh_horizontal_cylinder(
|
|
269
254
|
length=length, radius=radius, center=(0, 0, 0),
|
|
270
255
|
resolution=(nr, ntheta//2, nx),
|
|
271
|
-
reflection_symmetry=False,
|
|
256
|
+
reflection_symmetry=False,
|
|
272
257
|
name=f"half_{name}", _theta_max=_theta_max/2,
|
|
273
258
|
)
|
|
274
259
|
|
|
275
|
-
mesh = ReflectionSymmetricMesh(half_cylinder, plane=
|
|
276
|
-
|
|
277
|
-
else:
|
|
278
|
-
if translation_symmetry:
|
|
279
|
-
slice = mesh_horizontal_cylinder(
|
|
280
|
-
length=length/nx, radius=radius, center=(-length/2 + length/(2*nx), 0, 0),
|
|
281
|
-
resolution=(0, ntheta, 1),
|
|
282
|
-
reflection_symmetry=False, translation_symmetry=False,
|
|
283
|
-
name=f"slice_of_{name}", _theta_max=_theta_max,
|
|
284
|
-
)
|
|
285
|
-
|
|
286
|
-
open_cylinder = TranslationalSymmetricMesh(
|
|
287
|
-
slice, translation=np.asarray([length / nx, 0.0, 0.0]),
|
|
288
|
-
nb_repetitions=nx-1, name=f"open_{name}")
|
|
260
|
+
mesh = ReflectionSymmetricMesh(half_cylinder, plane='xOz', name=name)
|
|
289
261
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
262
|
+
else: # General case
|
|
263
|
+
theta_range = np.linspace(0, _theta_max, ntheta+1)
|
|
264
|
+
x_range = np.linspace(-length/2, length/2, nx+1)
|
|
265
|
+
nodes = np.array([(x, radius*sin(t), -radius*cos(t)) for (x, t) in product(x_range, theta_range)])
|
|
294
266
|
|
|
295
|
-
|
|
296
|
-
|
|
267
|
+
panels = np.array([(i+j*(ntheta+1), i+1+j*(ntheta+1), i+1+(j+1)*(ntheta+1), i+(j+1)*(ntheta+1))
|
|
268
|
+
for (i, j) in product(range(ntheta), range(nx))])
|
|
297
269
|
|
|
298
|
-
|
|
270
|
+
mesh = Mesh(nodes, panels, name=f"open_{name}")
|
|
299
271
|
|
|
300
272
|
if nr > 0:
|
|
301
273
|
side = mesh_disk(radius=radius, center=(-length/2, 0, 0), normal=(-1, 0, 0),
|
|
302
274
|
reflection_symmetry=False, resolution=(nr, ntheta), name=f"side_of_{name}",
|
|
303
275
|
_theta_max=_theta_max)
|
|
304
|
-
other_side = side.mirrored(
|
|
305
|
-
mesh =
|
|
306
|
-
if not translation_symmetry:
|
|
307
|
-
mesh = mesh.merged()
|
|
308
|
-
else:
|
|
309
|
-
mesh = open_cylinder.copy(name=name)
|
|
276
|
+
other_side = side.mirrored('yOz', name=f"other_side_of_{name}")
|
|
277
|
+
mesh = Mesh.join_meshes(mesh, side, other_side, name=name)
|
|
310
278
|
|
|
311
|
-
mesh.
|
|
312
|
-
mesh.translate(center)
|
|
313
|
-
mesh.geometric_center = np.asarray(center, dtype=float)
|
|
279
|
+
mesh = mesh.translated(center, name=name)
|
|
314
280
|
return mesh
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
"""Generate rectangular bodies."""
|
|
2
2
|
# Copyright (C) 2017-2024 Matthieu Ancellin
|
|
3
3
|
# See LICENSE file at <https://github.com/capytaine/capytaine>
|
|
4
|
+
|
|
4
5
|
import logging
|
|
5
6
|
from itertools import product
|
|
6
7
|
|
|
7
8
|
import numpy as np
|
|
8
9
|
|
|
9
|
-
from capytaine.meshes.geometry import xOz_Plane, yOz_Plane
|
|
10
10
|
from capytaine.meshes.meshes import Mesh
|
|
11
|
-
from capytaine.meshes.
|
|
12
|
-
from capytaine.meshes.collections import CollectionOfMeshes
|
|
11
|
+
from capytaine.meshes.symmetric_meshes import ReflectionSymmetricMesh
|
|
13
12
|
|
|
14
13
|
LOG = logging.getLogger(__name__)
|
|
15
14
|
|
|
16
15
|
def mesh_rectangle(*, size=(5.0, 5.0), center=(0.0, 0.0, 0.0),
|
|
17
16
|
resolution=(5, 5), faces_max_radius=None,
|
|
18
17
|
normal=(0.0, 0.0, 1.0),
|
|
19
|
-
|
|
18
|
+
reflection_symmetry=False,
|
|
20
19
|
name=None):
|
|
21
20
|
"""One-sided rectangle.
|
|
22
21
|
|
|
@@ -36,8 +35,6 @@ def mesh_rectangle(*, size=(5.0, 5.0), center=(0.0, 0.0, 0.0),
|
|
|
36
35
|
changed to fit the constraint on the maximal radius.
|
|
37
36
|
normal: 3-ple of floats, optional
|
|
38
37
|
normal vector, default: (0, 0, 1)
|
|
39
|
-
translation_symmetry : bool, optional
|
|
40
|
-
if True, use the translation symmetry to speed up the computations
|
|
41
38
|
reflection_symmetry : bool, optional
|
|
42
39
|
if True, use the reflection symmetry to speed up the computations
|
|
43
40
|
name : string, optional
|
|
@@ -62,33 +59,21 @@ def mesh_rectangle(*, size=(5.0, 5.0), center=(0.0, 0.0, 0.0),
|
|
|
62
59
|
nw = int(np.ceil(width / (np.sqrt(2) * faces_max_radius)))
|
|
63
60
|
nh = int(np.ceil(height / (np.sqrt(2) * faces_max_radius)))
|
|
64
61
|
|
|
65
|
-
if name is None:
|
|
66
|
-
name = f"rectangle_{next(Mesh._ids)}"
|
|
67
|
-
|
|
68
|
-
if translation_symmetry and reflection_symmetry:
|
|
69
|
-
raise NotImplementedError("Rectangle generation with both reflection and translation symmetries "
|
|
70
|
-
"has not been implemented.")
|
|
71
|
-
|
|
72
62
|
if reflection_symmetry:
|
|
73
63
|
if nw % 2 == 1:
|
|
74
|
-
raise ValueError("To
|
|
64
|
+
raise ValueError("To define a rectangle mesh with reflection symmetry, "
|
|
75
65
|
"it should have an even number of panels in this direction.")
|
|
76
66
|
|
|
67
|
+
if not np.isclose(center[1], 0.0) or not np.isclose(normal[1], 0.0):
|
|
68
|
+
raise ValueError("To define a rectangle mesh with reflection symmetry, "
|
|
69
|
+
"its center should be in the xOz plane (that is y=0) "
|
|
70
|
+
"and so should also be its normal vector.")
|
|
71
|
+
|
|
77
72
|
half_mesh = mesh_rectangle(size=(width/2, height), resolution=(nw//2, nh),
|
|
78
|
-
center=(0, -width/4, 0), normal=
|
|
79
|
-
|
|
73
|
+
center=(0, -width/4, 0), normal=normal,
|
|
74
|
+
reflection_symmetry=False,
|
|
80
75
|
name=f"half_of_{name}")
|
|
81
|
-
mesh = ReflectionSymmetricMesh(half_mesh, plane=
|
|
82
|
-
|
|
83
|
-
elif translation_symmetry:
|
|
84
|
-
strip = mesh_rectangle(size=(width/nw, height), resolution=(1, nh),
|
|
85
|
-
center=(0, -width/2 + width/(2*nw), 0), normal=(0.0, 0.0, 1.0),
|
|
86
|
-
translation_symmetry=False, reflection_symmetry=False,
|
|
87
|
-
name=f"strip_of_{name}")
|
|
88
|
-
mesh = TranslationalSymmetricMesh(strip,
|
|
89
|
-
translation=np.asarray([0, width/nw, 0]),
|
|
90
|
-
nb_repetitions=int(nw)-1,
|
|
91
|
-
name=name)
|
|
76
|
+
mesh = ReflectionSymmetricMesh(half_mesh, plane='xOz', name=name)
|
|
92
77
|
|
|
93
78
|
else:
|
|
94
79
|
y_range = np.linspace(-width/2, width/2, nw+1)
|
|
@@ -98,17 +83,15 @@ def mesh_rectangle(*, size=(5.0, 5.0), center=(0.0, 0.0, 0.0),
|
|
|
98
83
|
for (i, j) in product(range(nw), range(nh))])
|
|
99
84
|
|
|
100
85
|
mesh = Mesh(nodes, panels, name=name)
|
|
86
|
+
mesh = mesh.rotated_such_that_vectors_are_aligned(mesh.faces_normals[0], normal)
|
|
101
87
|
|
|
102
|
-
mesh.
|
|
103
|
-
mesh.translate(center)
|
|
104
|
-
mesh.rotate_around_center_to_align_vectors(center, mesh.faces_normals[0], normal)
|
|
105
|
-
mesh.geometric_center = np.asarray(center, dtype=float)
|
|
88
|
+
mesh = mesh.translated(center, name=name)
|
|
106
89
|
return mesh
|
|
107
90
|
|
|
108
91
|
|
|
109
92
|
def mesh_parallelepiped(size=(1.0, 1.0, 1.0), center=(0, 0, 0),
|
|
110
93
|
resolution=(4, 4, 4), faces_max_radius=None,
|
|
111
|
-
missing_sides=set(), reflection_symmetry=False,
|
|
94
|
+
missing_sides=set(), reflection_symmetry=False,
|
|
112
95
|
name=None):
|
|
113
96
|
"""Six rectangles forming a parallelepiped.
|
|
114
97
|
|
|
@@ -130,9 +113,6 @@ def mesh_parallelepiped(size=(1.0, 1.0, 1.0), center=(0, 0, 0),
|
|
|
130
113
|
May be ignored when building a mesh with a symmetry.
|
|
131
114
|
reflection_symmetry : bool, optional
|
|
132
115
|
use xOz and yOz symmetry plane to generate the mesh
|
|
133
|
-
translation_symmetry : bool, optional
|
|
134
|
-
if True, use the translation symmetry in the x direction to speed up the computations.
|
|
135
|
-
To use the translation symmetry in the y direction, create a x-symmetric body and then rotate it by pi/2.
|
|
136
116
|
name : string, optional
|
|
137
117
|
a name for the body
|
|
138
118
|
"""
|
|
@@ -163,62 +143,25 @@ def mesh_parallelepiped(size=(1.0, 1.0, 1.0), center=(0, 0, 0),
|
|
|
163
143
|
nth = int(np.ceil(thickness / (np.sqrt(2) * faces_max_radius)))
|
|
164
144
|
nh = int(np.ceil(height / (np.sqrt(2) * faces_max_radius)))
|
|
165
145
|
|
|
166
|
-
if name is None:
|
|
167
|
-
name = f"rectangular_parallelepiped_{next(Mesh._ids)}"
|
|
168
|
-
|
|
169
|
-
if translation_symmetry and reflection_symmetry:
|
|
170
|
-
raise NotImplementedError("Parallelepiped generation with both reflection and translation symmetries "
|
|
171
|
-
"has not been implemented.")
|
|
172
|
-
|
|
173
146
|
if reflection_symmetry:
|
|
174
147
|
if (nw % 2 == 1 or nth % 2 == 1):
|
|
175
|
-
raise ValueError("To
|
|
176
|
-
"it should have an even number of panels in
|
|
148
|
+
raise ValueError("To define a parallelepiped mesh with reflection symmetry, "
|
|
149
|
+
"it should have an even number of panels in both direction.")
|
|
150
|
+
|
|
151
|
+
if not np.isclose(center[0], 0.0) or not np.isclose(center[1], 0.0):
|
|
152
|
+
raise ValueError("To define a rectangle mesh with reflection symmetry, "
|
|
153
|
+
"its center should be on the Oz axis (that is x=0 and y=0).")
|
|
177
154
|
|
|
178
155
|
missing_sides_in_quarter = missing_sides | {"right", "back"}
|
|
179
156
|
quarter_mesh = mesh_parallelepiped(
|
|
180
157
|
size=(width/2, thickness/2, height), resolution=(nw//2, nth//2, nh),
|
|
181
158
|
center=(-width/4, -thickness/4, 0), missing_sides=missing_sides_in_quarter,
|
|
182
|
-
reflection_symmetry=False,
|
|
159
|
+
reflection_symmetry=False,
|
|
183
160
|
name=f"quarter_of_{name}"
|
|
184
161
|
)
|
|
185
162
|
|
|
186
|
-
half_mesh = ReflectionSymmetricMesh(quarter_mesh, plane=
|
|
187
|
-
mesh = ReflectionSymmetricMesh(half_mesh, plane=
|
|
188
|
-
|
|
189
|
-
elif translation_symmetry:
|
|
190
|
-
|
|
191
|
-
missing_sides_in_strip = missing_sides | {"left", "right"}
|
|
192
|
-
strip = mesh_parallelepiped(
|
|
193
|
-
size=(width/nw, thickness, height), resolution=(1, nth, nh),
|
|
194
|
-
center=(-width/2 + width/(2*nw), 0, 0), missing_sides=missing_sides_in_strip,
|
|
195
|
-
reflection_symmetry=False, translation_symmetry=False,
|
|
196
|
-
name=f"strip_of_{name}"
|
|
197
|
-
)
|
|
198
|
-
|
|
199
|
-
open_parallelepiped = TranslationalSymmetricMesh(
|
|
200
|
-
strip,
|
|
201
|
-
translation=(width/nw, 0, 0), nb_repetitions=int(nw)-1,
|
|
202
|
-
name=f"body_of_{name}"
|
|
203
|
-
)
|
|
204
|
-
|
|
205
|
-
components_of_mesh = [open_parallelepiped]
|
|
206
|
-
if "right" not in missing_sides:
|
|
207
|
-
components_of_mesh.append(
|
|
208
|
-
mesh_rectangle(
|
|
209
|
-
size=(thickness, height), resolution=(nth, nh),
|
|
210
|
-
center=(width/2, 0, 0), normal=(1, 0, 0),
|
|
211
|
-
name=f"right_side_of_{name}"
|
|
212
|
-
))
|
|
213
|
-
if "left" not in missing_sides:
|
|
214
|
-
components_of_mesh.append(
|
|
215
|
-
mesh_rectangle(
|
|
216
|
-
size=(thickness, height), resolution=(nth, nh),
|
|
217
|
-
center=(-width/2, 0, 0), normal=(-1, 0, 0),
|
|
218
|
-
name=f"left_side_of_{name}"
|
|
219
|
-
))
|
|
220
|
-
|
|
221
|
-
mesh = CollectionOfMeshes(components_of_mesh, name=name)
|
|
163
|
+
half_mesh = ReflectionSymmetricMesh(quarter_mesh, plane='yOz', name=f"half_of_{name}")
|
|
164
|
+
mesh = ReflectionSymmetricMesh(half_mesh, plane='xOz', name=f"{name}")
|
|
222
165
|
|
|
223
166
|
else:
|
|
224
167
|
|
|
@@ -253,9 +196,7 @@ def mesh_parallelepiped(size=(1.0, 1.0, 1.0), center=(0, 0, 0),
|
|
|
253
196
|
mesh_rectangle(size=(thickness, width), resolution=(nth, nw), center=(0, 0, -height/2),
|
|
254
197
|
normal=(0, 0, -1), name=f"bottom_of_{name}")
|
|
255
198
|
)
|
|
256
|
-
mesh =
|
|
199
|
+
mesh = Mesh.join_meshes(*sides, name=name)
|
|
257
200
|
|
|
258
|
-
mesh.
|
|
259
|
-
mesh.translate(center)
|
|
260
|
-
mesh.geometric_center = np.asarray(center, dtype=float)
|
|
201
|
+
mesh = mesh.translated(center, name=name)
|
|
261
202
|
return mesh
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
"""Generate spherical bodies."""
|
|
2
2
|
# Copyright (C) 2017-2024 Matthieu Ancellin
|
|
3
3
|
# See LICENSE file at <https://github.com/capytaine/capytaine>
|
|
4
|
+
|
|
4
5
|
import logging
|
|
5
6
|
|
|
6
7
|
import numpy as np
|
|
7
8
|
from numpy import pi
|
|
8
9
|
|
|
9
|
-
from capytaine.meshes.
|
|
10
|
-
from capytaine.meshes.meshes import Mesh
|
|
11
|
-
from capytaine.meshes.symmetric import AxialSymmetricMesh
|
|
10
|
+
from capytaine.meshes.symmetric_meshes import RotationSymmetricMesh
|
|
12
11
|
|
|
13
12
|
LOG = logging.getLogger(__name__)
|
|
14
13
|
|
|
@@ -37,9 +36,6 @@ def mesh_sphere(*, radius=1.0, center=(0.0, 0.0, 0.0),
|
|
|
37
36
|
a name identifying the sphere (default: "sphere_id" where id is an unique integer).
|
|
38
37
|
"""
|
|
39
38
|
|
|
40
|
-
if name is None:
|
|
41
|
-
name = f"sphere_{next(Mesh._ids)}"
|
|
42
|
-
|
|
43
39
|
ntheta, nphi = resolution
|
|
44
40
|
if faces_max_radius is not None:
|
|
45
41
|
perimeter = 2*np.pi*radius
|
|
@@ -50,13 +46,10 @@ def mesh_sphere(*, radius=1.0, center=(0.0, 0.0, 0.0),
|
|
|
50
46
|
theta = np.linspace(0.0, pi, ntheta+1)
|
|
51
47
|
points_on_a_meridian = radius * np.stack([np.sin(theta), np.zeros_like(theta), -np.cos(theta)], axis=1)
|
|
52
48
|
|
|
53
|
-
|
|
54
|
-
mesh = AxialSymmetricMesh.from_profile(points_on_a_meridian, axis=symmetry_axis, nphi=nphi, name=name)
|
|
49
|
+
mesh = RotationSymmetricMesh.from_profile_points(points_on_a_meridian, n=nphi, name=name)
|
|
55
50
|
|
|
56
51
|
if not axial_symmetry:
|
|
57
52
|
mesh = mesh.merged()
|
|
58
53
|
|
|
59
|
-
mesh.
|
|
60
|
-
mesh.translate(center)
|
|
61
|
-
mesh.geometric_center = np.asarray(center, dtype=float)
|
|
54
|
+
mesh = mesh.translated(center, name=name)
|
|
62
55
|
return mesh
|