capytaine 2.2__cp311-cp311-win_amd64.whl → 2.3__cp311-cp311-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.
- capytaine/__about__.py +1 -1
- capytaine/__init__.py +6 -6
- capytaine/bem/airy_waves.py +7 -2
- capytaine/bem/engines.py +2 -2
- capytaine/bem/problems_and_results.py +82 -35
- capytaine/bem/solver.py +138 -41
- capytaine/bodies/bodies.py +40 -12
- capytaine/bodies/predefined/rectangles.py +2 -0
- capytaine/green_functions/FinGreen3D/.gitignore +1 -0
- capytaine/green_functions/FinGreen3D/FinGreen3D.f90 +3589 -0
- capytaine/green_functions/FinGreen3D/LICENSE +165 -0
- capytaine/green_functions/FinGreen3D/Makefile +16 -0
- capytaine/green_functions/FinGreen3D/README.md +24 -0
- capytaine/green_functions/FinGreen3D/test_program.f90 +39 -0
- capytaine/green_functions/LiangWuNoblesse/.gitignore +1 -0
- capytaine/green_functions/LiangWuNoblesse/LICENSE +504 -0
- capytaine/green_functions/LiangWuNoblesse/LiangWuNoblesseWaveTerm.f90 +751 -0
- capytaine/green_functions/LiangWuNoblesse/Makefile +18 -0
- capytaine/green_functions/LiangWuNoblesse/README.md +2 -0
- capytaine/green_functions/LiangWuNoblesse/test_program.f90 +28 -0
- capytaine/green_functions/abstract_green_function.py +55 -3
- capytaine/green_functions/delhommeau.py +186 -115
- capytaine/green_functions/hams.py +204 -0
- capytaine/green_functions/libs/Delhommeau_float32.cp311-win_amd64.dll.a +0 -0
- capytaine/green_functions/libs/Delhommeau_float32.cp311-win_amd64.pyd +0 -0
- capytaine/green_functions/libs/Delhommeau_float64.cp311-win_amd64.dll.a +0 -0
- capytaine/green_functions/libs/Delhommeau_float64.cp311-win_amd64.pyd +0 -0
- capytaine/io/bemio.py +14 -2
- capytaine/io/mesh_loaders.py +2 -1
- capytaine/io/wamit.py +479 -0
- capytaine/io/xarray.py +252 -100
- capytaine/matrices/block.py +4 -2
- capytaine/matrices/linear_solvers.py +1 -1
- capytaine/matrices/low_rank.py +3 -1
- capytaine/meshes/clipper.py +4 -3
- capytaine/meshes/collections.py +11 -1
- capytaine/meshes/mesh_like_protocol.py +37 -0
- capytaine/meshes/meshes.py +22 -9
- capytaine/meshes/properties.py +58 -24
- capytaine/meshes/symmetric.py +11 -2
- capytaine/post_pro/kochin.py +4 -4
- capytaine/tools/lists_of_points.py +3 -3
- capytaine/tools/prony_decomposition.py +60 -4
- capytaine/tools/symbolic_multiplication.py +30 -2
- capytaine/tools/timer.py +64 -0
- capytaine-2.3.dist-info/DELVEWHEEL +2 -0
- capytaine-2.3.dist-info/METADATA +761 -0
- capytaine-2.3.dist-info/RECORD +97 -0
- capytaine-2.2.dist-info/DELVEWHEEL +0 -2
- capytaine-2.2.dist-info/METADATA +0 -751
- capytaine-2.2.dist-info/RECORD +0 -81
- {capytaine-2.2.dist-info → capytaine-2.3.dist-info}/LICENSE +0 -0
- {capytaine-2.2.dist-info → capytaine-2.3.dist-info}/WHEEL +0 -0
- {capytaine-2.2.dist-info → capytaine-2.3.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)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
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
|
-
|
|
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
|
capytaine/io/mesh_loaders.py
CHANGED
|
@@ -721,6 +721,7 @@ def load_GDF(filename, name=None):
|
|
|
721
721
|
npan = int(gdf_file.readline().split()[0])
|
|
722
722
|
faces_vertices = np.genfromtxt(gdf_file)
|
|
723
723
|
|
|
724
|
+
faces_vertices = faces_vertices.reshape(-1, 3)
|
|
724
725
|
vertices, indices = np.unique(faces_vertices, axis=0, return_inverse=True)
|
|
725
726
|
faces = indices.reshape(-1, 4)
|
|
726
727
|
|
|
@@ -913,7 +914,7 @@ def load_MED(filename, name=None):
|
|
|
913
914
|
if nb_quadrangles == 0:
|
|
914
915
|
quadrangles = np.zeros((0, 4), dtype=int)
|
|
915
916
|
|
|
916
|
-
faces = np.
|
|
917
|
+
faces = np.vstack([triangles, quadrangles])
|
|
917
918
|
|
|
918
919
|
return Mesh(vertices, faces, name=name)
|
|
919
920
|
|