capytaine 2.3.1__cp38-cp38-win_amd64.whl → 3.0.0a1__cp38-cp38-win_amd64.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.
Files changed (89) hide show
  1. capytaine/__about__.py +7 -2
  2. capytaine/__init__.py +10 -14
  3. capytaine/bem/engines.py +234 -354
  4. capytaine/bem/problems_and_results.py +14 -13
  5. capytaine/bem/solver.py +204 -80
  6. capytaine/bodies/bodies.py +278 -869
  7. capytaine/bodies/dofs.py +136 -9
  8. capytaine/bodies/hydrostatics.py +540 -0
  9. capytaine/bodies/multibodies.py +216 -0
  10. capytaine/green_functions/{libs/Delhommeau_float32.cp38-win_amd64.dll.a → Delhommeau_float32.cp38-win_amd64.dll.a} +0 -0
  11. capytaine/green_functions/Delhommeau_float32.cp38-win_amd64.pyd +0 -0
  12. capytaine/green_functions/{libs/Delhommeau_float64.cp38-win_amd64.dll.a → Delhommeau_float64.cp38-win_amd64.dll.a} +0 -0
  13. capytaine/green_functions/Delhommeau_float64.cp38-win_amd64.pyd +0 -0
  14. capytaine/green_functions/abstract_green_function.py +2 -2
  15. capytaine/green_functions/delhommeau.py +31 -16
  16. capytaine/green_functions/hams.py +19 -13
  17. capytaine/io/legacy.py +3 -103
  18. capytaine/io/xarray.py +11 -6
  19. capytaine/meshes/__init__.py +2 -6
  20. capytaine/meshes/abstract_meshes.py +375 -0
  21. capytaine/meshes/clean.py +302 -0
  22. capytaine/meshes/clip.py +347 -0
  23. capytaine/meshes/export.py +89 -0
  24. capytaine/meshes/geometry.py +244 -394
  25. capytaine/meshes/io.py +433 -0
  26. capytaine/meshes/meshes.py +617 -681
  27. capytaine/meshes/predefined/cylinders.py +22 -56
  28. capytaine/meshes/predefined/rectangles.py +26 -85
  29. capytaine/meshes/predefined/spheres.py +4 -11
  30. capytaine/meshes/quality.py +118 -407
  31. capytaine/meshes/surface_integrals.py +48 -29
  32. capytaine/meshes/symmetric_meshes.py +641 -0
  33. capytaine/meshes/visualization.py +353 -0
  34. capytaine/post_pro/free_surfaces.py +1 -4
  35. capytaine/post_pro/kochin.py +10 -10
  36. capytaine/tools/block_circulant_matrices.py +275 -0
  37. capytaine/tools/lists_of_points.py +2 -2
  38. capytaine/tools/memory_monitor.py +45 -0
  39. capytaine/tools/symbolic_multiplication.py +13 -1
  40. capytaine/tools/timer.py +58 -34
  41. capytaine-3.0.0a1.dist-info/DELVEWHEEL +2 -0
  42. {capytaine-2.3.1.dist-info → capytaine-3.0.0a1.dist-info}/METADATA +7 -2
  43. capytaine-3.0.0a1.dist-info/RECORD +71 -0
  44. capytaine/bodies/predefined/__init__.py +0 -6
  45. capytaine/bodies/predefined/cylinders.py +0 -151
  46. capytaine/bodies/predefined/rectangles.py +0 -111
  47. capytaine/bodies/predefined/spheres.py +0 -70
  48. capytaine/green_functions/FinGreen3D/.gitignore +0 -1
  49. capytaine/green_functions/FinGreen3D/FinGreen3D.f90 +0 -3589
  50. capytaine/green_functions/FinGreen3D/LICENSE +0 -165
  51. capytaine/green_functions/FinGreen3D/Makefile +0 -16
  52. capytaine/green_functions/FinGreen3D/README.md +0 -24
  53. capytaine/green_functions/FinGreen3D/test_program.f90 +0 -39
  54. capytaine/green_functions/LiangWuNoblesse/.gitignore +0 -1
  55. capytaine/green_functions/LiangWuNoblesse/LICENSE +0 -504
  56. capytaine/green_functions/LiangWuNoblesse/LiangWuNoblesseWaveTerm.f90 +0 -751
  57. capytaine/green_functions/LiangWuNoblesse/Makefile +0 -16
  58. capytaine/green_functions/LiangWuNoblesse/README.md +0 -2
  59. capytaine/green_functions/LiangWuNoblesse/test_program.f90 +0 -28
  60. capytaine/green_functions/libs/Delhommeau_float32.cp38-win_amd64.pyd +0 -0
  61. capytaine/green_functions/libs/Delhommeau_float64.cp38-win_amd64.pyd +0 -0
  62. capytaine/green_functions/libs/__init__.py +0 -0
  63. capytaine/io/mesh_loaders.py +0 -1086
  64. capytaine/io/mesh_writers.py +0 -692
  65. capytaine/io/meshio.py +0 -38
  66. capytaine/matrices/__init__.py +0 -16
  67. capytaine/matrices/block.py +0 -592
  68. capytaine/matrices/block_toeplitz.py +0 -325
  69. capytaine/matrices/builders.py +0 -89
  70. capytaine/matrices/linear_solvers.py +0 -232
  71. capytaine/matrices/low_rank.py +0 -395
  72. capytaine/meshes/clipper.py +0 -465
  73. capytaine/meshes/collections.py +0 -342
  74. capytaine/meshes/mesh_like_protocol.py +0 -37
  75. capytaine/meshes/properties.py +0 -276
  76. capytaine/meshes/quadratures.py +0 -80
  77. capytaine/meshes/symmetric.py +0 -462
  78. capytaine/tools/lru_cache.py +0 -49
  79. capytaine/ui/vtk/__init__.py +0 -3
  80. capytaine/ui/vtk/animation.py +0 -329
  81. capytaine/ui/vtk/body_viewer.py +0 -28
  82. capytaine/ui/vtk/helpers.py +0 -82
  83. capytaine/ui/vtk/mesh_viewer.py +0 -461
  84. capytaine-2.3.1.dist-info/DELVEWHEEL +0 -2
  85. capytaine-2.3.1.dist-info/RECORD +0 -98
  86. {capytaine-2.3.1.dist-info → capytaine-3.0.0a1.dist-info}/LICENSE +0 -0
  87. {capytaine-2.3.1.dist-info → capytaine-3.0.0a1.dist-info}/WHEEL +0 -0
  88. {capytaine-2.3.1.dist-info → capytaine-3.0.0a1.dist-info}/entry_points.txt +0 -0
  89. capytaine.libs/{.load-order-capytaine-2.3.1 → .load-order-capytaine-3.0.0a1} +2 -2
@@ -1,5 +1,5 @@
1
1
  """Generate meshes of cylinders and disks"""
2
- # Copyright (C) 2017-2022 Matthieu Ancellin
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.collections import CollectionOfMeshes
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=xOz_Plane, name=name)
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 = AxialSymmetricMesh(mesh_slice, axis=Oz_axis, nb_repetitions=ntheta - 1, name=name)
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.heal_mesh()
98
- mesh.translate(center)
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=yOz_Plane, name=name)
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 = AxialSymmetricMesh(mesh_slice, axis=Oz_axis, nb_repetitions=ntheta - 1, name=name)
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.heal_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, translation_symmetry=False, name=None, _theta_max=2*pi):
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, translation_symmetry=translation_symmetry,
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=xOz_Plane, name=name)
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
- else: # General case
291
- theta_range = np.linspace(0, _theta_max, ntheta+1)
292
- x_range = np.linspace(-length/2, length/2, nx+1)
293
- nodes = np.array([(x, radius*sin(t), -radius*cos(t)) for (x, t) in product(x_range, theta_range)])
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
- panels = np.array([(i+j*(ntheta+1), i+1+j*(ntheta+1), i+1+(j+1)*(ntheta+1), i+(j+1)*(ntheta+1))
296
- for (i, j) in product(range(ntheta), range(nx))])
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
- open_cylinder = Mesh(nodes, panels, name=f"open_{name}")
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(yOz_Plane, name=f"other_side_of_{name}")
305
- mesh = CollectionOfMeshes([open_cylinder, side, other_side], name=name)
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.heal_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.symmetric import TranslationalSymmetricMesh, ReflectionSymmetricMesh
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
- translation_symmetry=False, reflection_symmetry=False,
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 use the reflection symmetry of the mesh, "
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=(0.0, 0.0, 1.0),
79
- translation_symmetry=False, reflection_symmetry=False,
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=xOz_Plane, name=name)
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.heal_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, translation_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 use the reflection symmetry of the mesh, "
176
- "it should have an even number of panels in this direction.")
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, translation_symmetry=False,
159
+ reflection_symmetry=False,
183
160
  name=f"quarter_of_{name}"
184
161
  )
185
162
 
186
- half_mesh = ReflectionSymmetricMesh(quarter_mesh, plane=yOz_Plane, name=f"half_of_{name}")
187
- mesh = ReflectionSymmetricMesh(half_mesh, plane=xOz_Plane, name=f"{name}")
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 = CollectionOfMeshes(sides, name=name).merged()
199
+ mesh = Mesh.join_meshes(*sides, name=name)
257
200
 
258
- mesh.heal_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.geometry import Axis
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
- symmetry_axis = Axis(vector=[0, 0, 1], point=[0, 0, 0])
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.heal_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