capytaine 2.2.1__cp312-cp312-win_amd64.whl → 2.3.1__cp312-cp312-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 (48) hide show
  1. capytaine/__about__.py +1 -1
  2. capytaine/__init__.py +5 -4
  3. capytaine/bem/airy_waves.py +7 -2
  4. capytaine/bem/problems_and_results.py +91 -39
  5. capytaine/bem/solver.py +128 -40
  6. capytaine/bodies/bodies.py +46 -18
  7. capytaine/bodies/predefined/rectangles.py +2 -0
  8. capytaine/green_functions/FinGreen3D/.gitignore +1 -0
  9. capytaine/green_functions/FinGreen3D/FinGreen3D.f90 +3589 -0
  10. capytaine/green_functions/FinGreen3D/LICENSE +165 -0
  11. capytaine/green_functions/FinGreen3D/Makefile +16 -0
  12. capytaine/green_functions/FinGreen3D/README.md +24 -0
  13. capytaine/green_functions/FinGreen3D/test_program.f90 +39 -0
  14. capytaine/green_functions/LiangWuNoblesse/.gitignore +1 -0
  15. capytaine/green_functions/LiangWuNoblesse/LICENSE +504 -0
  16. capytaine/green_functions/LiangWuNoblesse/LiangWuNoblesseWaveTerm.f90 +751 -0
  17. capytaine/green_functions/LiangWuNoblesse/Makefile +16 -0
  18. capytaine/green_functions/LiangWuNoblesse/README.md +2 -0
  19. capytaine/green_functions/LiangWuNoblesse/test_program.f90 +28 -0
  20. capytaine/green_functions/abstract_green_function.py +55 -3
  21. capytaine/green_functions/delhommeau.py +205 -130
  22. capytaine/green_functions/hams.py +204 -0
  23. capytaine/green_functions/libs/Delhommeau_float32.cp312-win_amd64.dll.a +0 -0
  24. capytaine/green_functions/libs/Delhommeau_float32.cp312-win_amd64.pyd +0 -0
  25. capytaine/green_functions/libs/Delhommeau_float64.cp312-win_amd64.dll.a +0 -0
  26. capytaine/green_functions/libs/Delhommeau_float64.cp312-win_amd64.pyd +0 -0
  27. capytaine/io/bemio.py +14 -2
  28. capytaine/io/mesh_loaders.py +1 -1
  29. capytaine/io/wamit.py +479 -0
  30. capytaine/io/xarray.py +261 -117
  31. capytaine/matrices/linear_solvers.py +1 -1
  32. capytaine/meshes/clipper.py +1 -0
  33. capytaine/meshes/collections.py +19 -1
  34. capytaine/meshes/mesh_like_protocol.py +37 -0
  35. capytaine/meshes/meshes.py +28 -8
  36. capytaine/meshes/symmetric.py +89 -10
  37. capytaine/post_pro/kochin.py +4 -4
  38. capytaine/tools/lists_of_points.py +3 -3
  39. capytaine/tools/prony_decomposition.py +60 -4
  40. capytaine/tools/symbolic_multiplication.py +30 -4
  41. capytaine/tools/timer.py +66 -0
  42. capytaine-2.3.1.dist-info/DELVEWHEEL +2 -0
  43. {capytaine-2.2.1.dist-info → capytaine-2.3.1.dist-info}/METADATA +6 -10
  44. {capytaine-2.2.1.dist-info → capytaine-2.3.1.dist-info}/RECORD +47 -31
  45. capytaine-2.2.1.dist-info/DELVEWHEEL +0 -2
  46. {capytaine-2.2.1.dist-info → capytaine-2.3.1.dist-info}/LICENSE +0 -0
  47. {capytaine-2.2.1.dist-info → capytaine-2.3.1.dist-info}/WHEEL +0 -0
  48. {capytaine-2.2.1.dist-info → capytaine-2.3.1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,204 @@
1
+ from importlib import import_module
2
+ from scipy.optimize import brentq
3
+ import numpy as np
4
+
5
+ from capytaine.green_functions.abstract_green_function import AbstractGreenFunction, GreenFunctionEvaluationError
6
+
7
+
8
+ class LiangWuNoblesseGF(AbstractGreenFunction):
9
+ """Wrapper for the Fortran implementation of the infinite depth Green function of [Liang, Wu, Noblesse, 2018].
10
+
11
+ Uses the same implementation as Delhommeau() for the Rankine and reflected Rankine terms.
12
+
13
+ """
14
+ floating_point_precision = "float64"
15
+
16
+ fortran_core = import_module("capytaine.green_functions.libs.Delhommeau_float64")
17
+ tabulation_grid_shape_index = fortran_core.constants.liang_wu_noblesse
18
+ exportable_settings = {'green_function': "LiangWuNoblesseGF"}
19
+
20
+ # Dummy arrays that won't actually be used by the fortran code.
21
+ prony_decomposition = np.zeros((1, 1))
22
+ dispersion_relation_roots = np.empty(1)
23
+ finite_depth_method_index = -9999
24
+ tabulation_nb_integration_points = 1
25
+ tabulated_r_range = np.empty(1)
26
+ tabulated_z_range = np.empty(1)
27
+ tabulated_integrals = np.empty(1)
28
+ dummy_param = -999
29
+
30
+ def __str__(self):
31
+ return "LiangWuNoblesseGF()"
32
+
33
+ def __repr__(self):
34
+ return "LiangWuNoblesseGF()"
35
+
36
+ def _repr_pretty_(self, p, cycle):
37
+ p.text(self.__repr__())
38
+
39
+ def evaluate(self,
40
+ mesh1, mesh2,
41
+ free_surface=0.0, water_depth=np.inf, wavenumber=1.0,
42
+ adjoint_double_layer=True, early_dot_product=True
43
+ ):
44
+
45
+ if free_surface == np.inf or water_depth < np.inf:
46
+ raise NotImplementedError("LiangWuNoblesseGF() is only implemented for infinite depth with a free surface")
47
+
48
+ if wavenumber == np.inf:
49
+ gf_singularities_index = self.fortran_core.constants.high_freq
50
+ else:
51
+ gf_singularities_index = self.fortran_core.constants.low_freq
52
+
53
+ collocation_points, early_dot_product_normals = \
54
+ self._get_colocation_points_and_normals(mesh1, mesh2, adjoint_double_layer)
55
+
56
+ S, K = self._init_matrices(
57
+ (collocation_points.shape[0], mesh2.nb_faces), early_dot_product=early_dot_product
58
+ )
59
+
60
+ self.fortran_core.matrices.build_matrices(
61
+ collocation_points, early_dot_product_normals,
62
+ mesh2.vertices, mesh2.faces + 1,
63
+ mesh2.faces_centers, mesh2.faces_normals,
64
+ mesh2.faces_areas, mesh2.faces_radiuses,
65
+ *mesh2.quadrature_points,
66
+ wavenumber, np.inf,
67
+ self.tabulation_nb_integration_points, self.tabulation_grid_shape_index,
68
+ self.tabulated_r_range, self.tabulated_z_range, self.tabulated_integrals,
69
+ self.dummy_param, self.prony_decomposition, self.dispersion_relation_roots,
70
+ gf_singularities_index, adjoint_double_layer,
71
+ S, K
72
+ )
73
+
74
+ if mesh1 is mesh2:
75
+ self.fortran_core.matrices.add_diagonal_term(
76
+ mesh2.faces_centers, early_dot_product_normals, free_surface, K,
77
+ )
78
+
79
+ if np.any(np.isnan(S)) or np.any(np.isnan(K)):
80
+ raise GreenFunctionEvaluationError(
81
+ "Green function returned a NaN in the interaction matrix.\n"
82
+ "It could be due to overlapping panels.")
83
+
84
+ if early_dot_product:
85
+ K = K.reshape((collocation_points.shape[0], mesh2.nb_faces))
86
+
87
+ return S, K
88
+
89
+
90
+ class FinGreen3D(AbstractGreenFunction):
91
+ """Wrapper for the Fortran implementation of the finite depth Green function of [Liu et al.].
92
+
93
+ Uses the same implementation as Delhommeau() for the Rankine and reflected Rankine terms.
94
+
95
+ """
96
+ floating_point_precision = "float64"
97
+
98
+ fortran_core = import_module("capytaine.green_functions.libs.Delhommeau_float64")
99
+ finite_depth_method_index = fortran_core.constants.fingreen3d_method
100
+ gf_singularities_index = fortran_core.constants.low_freq
101
+
102
+ # Dummy arrays that won't actually be used by the fortran code.
103
+ prony_decomposition = np.zeros((1, 1))
104
+ tabulation_nb_integration_points = 1
105
+ tabulated_r_range = np.empty(1)
106
+ tabulated_z_range = np.empty(1)
107
+ tabulated_integrals = np.empty(1)
108
+ dummy_param = -999
109
+
110
+ def __init__(self, *, nb_dispersion_roots=200):
111
+ self.nb_dispersion_roots = nb_dispersion_roots
112
+ self.exportable_settings = {
113
+ 'green_function': "FinGreen3D",
114
+ 'nb_dispersion_roots': nb_dispersion_roots
115
+ }
116
+
117
+ def __str__(self):
118
+ return f"FinGreen3D(nb_dispersion_roots={self.nb_dispersion_roots})"
119
+
120
+ def __repr__(self):
121
+ return f"FinGreen3D(nb_dispersion_roots={self.nb_dispersion_roots})"
122
+
123
+ def _repr_pretty_(self, p, cycle):
124
+ p.text(self.__repr__())
125
+
126
+ def compute_dispersion_relation_roots(self, nk, wavenumber, depth):
127
+ omega2_h_over_g = wavenumber*np.tanh(wavenumber*depth)*depth
128
+ def root(i_root):
129
+ return brentq(lambda y: omega2_h_over_g + y*np.tan(y), (2*i_root+1)*np.pi/2 + 1e-10, (2*i_root+2)*np.pi/2 - 1e-10)/depth
130
+ return np.array([wavenumber] + [root(i_root) for i_root in range(nk-1)])
131
+
132
+ def evaluate(self, mesh1, mesh2, free_surface, water_depth, wavenumber, adjoint_double_layer=True, early_dot_product=True):
133
+
134
+ if free_surface == np.inf or water_depth == np.inf:
135
+ raise NotImplementedError("FinGreen3D is only implemented for finite depth with a free surface.")
136
+ if wavenumber == 0.0 or wavenumber == np.inf:
137
+ raise NotImplementedError("FinGreen3D is only implemented for non-zero and non-infinite frequencies")
138
+
139
+ dispersion_relation_roots = self.compute_dispersion_relation_roots(
140
+ self.nb_dispersion_roots,
141
+ wavenumber,
142
+ water_depth
143
+ )
144
+
145
+ collocation_points, early_dot_product_normals = \
146
+ self._get_colocation_points_and_normals(mesh1, mesh2, adjoint_double_layer)
147
+
148
+ S, K = self._init_matrices(
149
+ (collocation_points.shape[0], mesh2.nb_faces), early_dot_product=early_dot_product
150
+ )
151
+
152
+ self.fortran_core.matrices.build_matrices(
153
+ collocation_points, early_dot_product_normals,
154
+ mesh2.vertices, mesh2.faces + 1,
155
+ mesh2.faces_centers, mesh2.faces_normals,
156
+ mesh2.faces_areas, mesh2.faces_radiuses,
157
+ *mesh2.quadrature_points,
158
+ wavenumber, water_depth,
159
+ self.tabulation_nb_integration_points, self.dummy_param,
160
+ self.tabulated_r_range, self.tabulated_z_range, self.tabulated_integrals,
161
+ self.finite_depth_method_index, self.prony_decomposition, dispersion_relation_roots,
162
+ self.gf_singularities_index, adjoint_double_layer,
163
+ S, K
164
+ )
165
+
166
+ if mesh1 is mesh2:
167
+ self.fortran_core.matrices.add_diagonal_term(
168
+ mesh2.faces_centers, early_dot_product_normals, free_surface, K,
169
+ )
170
+
171
+ if np.any(np.isnan(S)) or np.any(np.isnan(K)):
172
+ raise GreenFunctionEvaluationError(
173
+ "Green function returned a NaN in the interaction matrix.\n"
174
+ "It could be due to overlapping panels.")
175
+
176
+ if early_dot_product:
177
+ K = K.reshape((collocation_points.shape[0], mesh2.nb_faces))
178
+
179
+ return S, K
180
+
181
+
182
+ class HAMS_GF(AbstractGreenFunction):
183
+ floating_point_precision = "float64"
184
+
185
+ exportable_settings = {'green_function': "HAMS_GF"}
186
+
187
+ def __init__(self):
188
+ self.infinite_depth_gf = LiangWuNoblesseGF()
189
+ self.finite_depth_gf = FinGreen3D(nb_dispersion_roots=200)
190
+
191
+ def __str__(self):
192
+ return "HAMS_GF()"
193
+
194
+ def __repr__(self):
195
+ return "HAMS_GF()"
196
+
197
+ def _repr_pretty_(self, p, cycle):
198
+ p.text(self.__repr__())
199
+
200
+ def evaluate(self, mesh1, mesh2, free_surface, water_depth, wavenumber, adjoint_double_layer=True, early_dot_product=True):
201
+ if water_depth == np.inf:
202
+ return self.infinite_depth_gf.evaluate(mesh1, mesh2, free_surface, water_depth, wavenumber, adjoint_double_layer, early_dot_product)
203
+ else:
204
+ return self.finite_depth_gf.evaluate(mesh1, mesh2, free_surface, water_depth, wavenumber, adjoint_double_layer, early_dot_product)
capytaine/io/bemio.py CHANGED
@@ -37,8 +37,7 @@ def dataframe_from_bemio(bemio_obj, wavenumber, wavelength):
37
37
  if bemio_obj.body[i].water_depth == 'infinite':
38
38
  bemio_obj.body[i].water_depth = np.inf
39
39
 
40
- if bemio_obj.body[i].bem_code == 'WAMIT': # WAMIT coefficients need to be dimensionalized
41
- from_wamit = True
40
+ from_wamit = (bemio_obj.body[i].bem_code == 'WAMIT') # WAMIT coefficients need to be dimensionalized
42
41
 
43
42
  for omega_idx, omega in enumerate(np.sort(bemio_obj.body[i].w)):
44
43
 
@@ -48,10 +47,13 @@ def dataframe_from_bemio(bemio_obj, wavenumber, wavelength):
48
47
  temp_dict['body_name'] = bemio_obj.body[i].name
49
48
  temp_dict['water_depth'] = bemio_obj.body[i].water_depth
50
49
  temp_dict['omega'] = omega
50
+ temp_dict['freq'] = omega/(2*np.pi)
51
51
  temp_dict['period'] = 2*np.pi/omega
52
52
  temp_dict['rho'] = rho
53
53
  temp_dict['g'] = g
54
+ temp_dict['kind'] = "DiffractionResult"
54
55
  temp_dict['forward_speed'] = 0.0
56
+ temp_dict['free_surface'] = 0.0
55
57
  temp_dict['wave_direction'] = np.radians(dir)
56
58
  temp_dict['influenced_dof'] = dofs
57
59
 
@@ -102,8 +104,11 @@ def dataframe_from_bemio(bemio_obj, wavenumber, wavelength):
102
104
  temp_dict['body_name'] = bemio_obj.body[i].name
103
105
  temp_dict['water_depth'] = bemio_obj.body[i].water_depth
104
106
  temp_dict['omega'] = omega
107
+ temp_dict['freq'] = omega/(2*np.pi)
105
108
  temp_dict['rho'] = rho
106
109
  temp_dict['g'] = g
110
+ temp_dict['kind'] = "RadiationResult"
111
+ temp_dict['free_surface'] = 0.0
107
112
  temp_dict['forward_speed'] = 0.0
108
113
  temp_dict['wave_direction'] = 0.0
109
114
  temp_dict['influenced_dof'] = dofs
@@ -138,4 +143,11 @@ def dataframe_from_bemio(bemio_obj, wavenumber, wavelength):
138
143
  ])
139
144
  df = df.astype({'added_mass': np.float64, 'radiation_damping': np.float64, 'diffraction_force': np.complex128, 'Froude_Krylov_force': np.complex128})
140
145
 
146
+ all_dofs_in_order = ['Surge', 'Sway', 'Heave', 'Roll', 'Pitch', 'Yaw']
147
+ inf_dof_cat = pd.CategoricalDtype(categories=all_dofs_in_order)
148
+ df["influenced_dof"] = df["influenced_dof"].astype(inf_dof_cat)
149
+ if 'added_mass' in df.columns:
150
+ rad_dof_cat = pd.CategoricalDtype(categories=all_dofs_in_order)
151
+ df["radiating_dof"] = df["radiating_dof"].astype(rad_dof_cat)
152
+
141
153
  return df
@@ -914,7 +914,7 @@ def load_MED(filename, name=None):
914
914
  if nb_quadrangles == 0:
915
915
  quadrangles = np.zeros((0, 4), dtype=int)
916
916
 
917
- faces = np.row_stack([triangles, quadrangles])
917
+ faces = np.vstack([triangles, quadrangles])
918
918
 
919
919
  return Mesh(vertices, faces, name=name)
920
920