capytaine 3.0.0a1__cp314-cp314t-macosx_15_0_x86_64.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 (65) hide show
  1. capytaine/.dylibs/libgcc_s.1.1.dylib +0 -0
  2. capytaine/.dylibs/libgfortran.5.dylib +0 -0
  3. capytaine/.dylibs/libquadmath.0.dylib +0 -0
  4. capytaine/__about__.py +21 -0
  5. capytaine/__init__.py +32 -0
  6. capytaine/bem/__init__.py +0 -0
  7. capytaine/bem/airy_waves.py +111 -0
  8. capytaine/bem/engines.py +321 -0
  9. capytaine/bem/problems_and_results.py +601 -0
  10. capytaine/bem/solver.py +718 -0
  11. capytaine/bodies/__init__.py +4 -0
  12. capytaine/bodies/bodies.py +630 -0
  13. capytaine/bodies/dofs.py +146 -0
  14. capytaine/bodies/hydrostatics.py +540 -0
  15. capytaine/bodies/multibodies.py +216 -0
  16. capytaine/green_functions/Delhommeau_float32.cpython-314t-darwin.so +0 -0
  17. capytaine/green_functions/Delhommeau_float64.cpython-314t-darwin.so +0 -0
  18. capytaine/green_functions/__init__.py +2 -0
  19. capytaine/green_functions/abstract_green_function.py +64 -0
  20. capytaine/green_functions/delhommeau.py +522 -0
  21. capytaine/green_functions/hams.py +210 -0
  22. capytaine/io/__init__.py +0 -0
  23. capytaine/io/bemio.py +153 -0
  24. capytaine/io/legacy.py +228 -0
  25. capytaine/io/wamit.py +479 -0
  26. capytaine/io/xarray.py +673 -0
  27. capytaine/meshes/__init__.py +2 -0
  28. capytaine/meshes/abstract_meshes.py +375 -0
  29. capytaine/meshes/clean.py +302 -0
  30. capytaine/meshes/clip.py +347 -0
  31. capytaine/meshes/export.py +89 -0
  32. capytaine/meshes/geometry.py +259 -0
  33. capytaine/meshes/io.py +433 -0
  34. capytaine/meshes/meshes.py +826 -0
  35. capytaine/meshes/predefined/__init__.py +6 -0
  36. capytaine/meshes/predefined/cylinders.py +280 -0
  37. capytaine/meshes/predefined/rectangles.py +202 -0
  38. capytaine/meshes/predefined/spheres.py +55 -0
  39. capytaine/meshes/quality.py +159 -0
  40. capytaine/meshes/surface_integrals.py +82 -0
  41. capytaine/meshes/symmetric_meshes.py +641 -0
  42. capytaine/meshes/visualization.py +353 -0
  43. capytaine/post_pro/__init__.py +6 -0
  44. capytaine/post_pro/free_surfaces.py +85 -0
  45. capytaine/post_pro/impedance.py +92 -0
  46. capytaine/post_pro/kochin.py +54 -0
  47. capytaine/post_pro/rao.py +60 -0
  48. capytaine/tools/__init__.py +0 -0
  49. capytaine/tools/block_circulant_matrices.py +275 -0
  50. capytaine/tools/cache_on_disk.py +26 -0
  51. capytaine/tools/deprecation_handling.py +18 -0
  52. capytaine/tools/lists_of_points.py +52 -0
  53. capytaine/tools/memory_monitor.py +45 -0
  54. capytaine/tools/optional_imports.py +27 -0
  55. capytaine/tools/prony_decomposition.py +150 -0
  56. capytaine/tools/symbolic_multiplication.py +161 -0
  57. capytaine/tools/timer.py +90 -0
  58. capytaine/ui/__init__.py +0 -0
  59. capytaine/ui/cli.py +28 -0
  60. capytaine/ui/rich.py +5 -0
  61. capytaine-3.0.0a1.dist-info/LICENSE +674 -0
  62. capytaine-3.0.0a1.dist-info/METADATA +755 -0
  63. capytaine-3.0.0a1.dist-info/RECORD +65 -0
  64. capytaine-3.0.0a1.dist-info/WHEEL +6 -0
  65. capytaine-3.0.0a1.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,161 @@
1
+ """This module is used for the handling of zero and infinite frequencies.
2
+ In this cases, the magnitudes that the solver has to manipulate are in the form of ω times a non-zero term.
3
+ Instead of evaluating this multiplication as zero of infinity, we keep it symbolic using the class defined here.
4
+
5
+ The frequency can be provided to the solver as something like
6
+ `SymbolicMultiplication("0", 1.0)` (that is zero) and the solver will return an
7
+ output of the form `SymbolicMultiplication("0", np.array(...))`
8
+ (that is also actually zero, except we may be intested in the non-zero array).
9
+ """
10
+
11
+ import numpy as np
12
+ from functools import wraps, total_ordering
13
+
14
+ class SymbolicMultiplication:
15
+ def __init__(self, symbol, value=1.0):
16
+ self.symbol = symbol
17
+ self.value = value
18
+ if hasattr(value, "shape"):
19
+ self.shape = value.shape # When wrapping Numpy arrays
20
+
21
+ def __format__(self, format_spec):
22
+ return f"{self.symbol}×{self.value.__format__(format_spec)}"
23
+
24
+ __array_priority__ = 1.0
25
+
26
+ def __array_function__(self, func, types, *args, **kwargs):
27
+ actual_args = args[0] # args = (actual_args, kwargs) for some reason
28
+ if func in {np.real, np.imag, np.sum} and len(actual_args) == 1 and len(kwargs) == 0:
29
+ return SymbolicMultiplication(self.symbol, func(self.value))
30
+ elif (
31
+ func in {np.einsum} and
32
+ len([a for a in actual_args if isinstance(a, SymbolicMultiplication)]) == 1 and
33
+ "out" not in kwargs
34
+ ):
35
+ # Einsum with one of the array being wrapped in SymbolicMultiplication
36
+ unwrapped = [a.value if isinstance(a, SymbolicMultiplication) else a for a in actual_args]
37
+ return SymbolicMultiplication(self.symbol, func(*unwrapped, **kwargs))
38
+ else:
39
+ return NotImplemented
40
+
41
+ def astype(self, proper_type):
42
+ return SymbolicMultiplication(self.symbol, proper_type(self.value))
43
+
44
+ def __str__(self):
45
+ return f"{self.symbol}×{self.value}"
46
+
47
+ def __repr__(self):
48
+ return f"SymbolicMultiplication(\"{self.symbol}\", {repr(self.value)})"
49
+
50
+ def __add__(self, x):
51
+ return self._concretize() + x
52
+
53
+ def __radd__(self, x):
54
+ return x + self._concretize()
55
+
56
+ def __neg__(self):
57
+ return SymbolicMultiplication(self.symbol, -self.value)
58
+
59
+ def __mul__(self, x):
60
+ return SymbolicMultiplication(self.symbol, self.value * x)
61
+
62
+ def __rmul__(self, x):
63
+ return SymbolicMultiplication(self.symbol, x * self.value)
64
+
65
+ def __pow__(self, n):
66
+ if n == 2:
67
+ return self * self
68
+ else:
69
+ raise NotImplementedError
70
+
71
+ def __truediv__(self, x):
72
+ if hasattr(x, 'symbol') and self.symbol == x.symbol:
73
+ return self.value / x.value
74
+ else:
75
+ return SymbolicMultiplication(self.symbol, self.value / x)
76
+
77
+ def __rtruediv__(self, x):
78
+ if hasattr(x, 'symbol') and self.symbol == x.symbol:
79
+ return x.value / self.value
80
+ elif self.symbol == "0":
81
+ return SymbolicMultiplication("∞", x/self.value)
82
+ elif self.symbol == "∞":
83
+ return SymbolicMultiplication("0", x/self.value)
84
+ else:
85
+ raise NotImplementedError
86
+
87
+ def __matmul__(self, x):
88
+ return SymbolicMultiplication(self.symbol, self.value @ x)
89
+
90
+ def __rmatmul__(self, x):
91
+ return SymbolicMultiplication(self.symbol, x @ self.value)
92
+
93
+ def __getitem__(self, item):
94
+ return SymbolicMultiplication(self.symbol, self.value[item])
95
+
96
+ def __setitem__(self, item, val):
97
+ if isinstance(val, SymbolicMultiplication) and self.symbol == val.symbol:
98
+ self.value.__setitem__(item, val.value)
99
+ else:
100
+ raise NotImplementedError
101
+
102
+ def __lt__(self, x):
103
+ return self._concretize() < x
104
+
105
+ def __le__(self, x):
106
+ return self._concretize() <= x
107
+
108
+ def __eq__(self, x):
109
+ return self._concretize() == x
110
+
111
+ def __ge__(self, x):
112
+ return self._concretize() >= x
113
+
114
+ def __gt__(self, x):
115
+ return self._concretize() > x
116
+
117
+ def __hash__(self):
118
+ return hash((self.symbol, self.value))
119
+
120
+ def _concretize(self):
121
+ if isinstance(self.value, np.ndarray):
122
+ if self.symbol == "0":
123
+ return np.zeros_like(self.value)
124
+ elif self.symbol == "∞":
125
+ return np.full_like(self.value, np.inf)
126
+ else:
127
+ return float(self)
128
+
129
+ def __float__(self):
130
+ if self.symbol == "0":
131
+ return 0.0 * float(self.value)
132
+ elif self.symbol == "∞":
133
+ return np.inf * float(self.value)
134
+ else:
135
+ raise NotImplementedError
136
+
137
+ def reshape(self, *args):
138
+ return SymbolicMultiplication(self.symbol, self.value.reshape(*args))
139
+
140
+ def sum(self, *args, **kwargs):
141
+ return SymbolicMultiplication(self.symbol, self.value.sum(*args, **kwargs))
142
+
143
+ @property
144
+ def T(self):
145
+ return SymbolicMultiplication(self.symbol, self.value.T)
146
+
147
+
148
+ def supporting_symbolic_multiplication(f):
149
+ """
150
+ When this decorator is applied to a function, this function can now take
151
+ as input a `SymbolicMultiplication` object. The function is applied on the
152
+ `value` part of the `SymbolicMultiplication` without modifying the
153
+ `symbol`.
154
+ """
155
+ @wraps(f)
156
+ def wrapped_f(a, x):
157
+ if hasattr(x, 'symbol'):
158
+ return SymbolicMultiplication(x.symbol, f(a, x.value))
159
+ else:
160
+ return f(a, x)
161
+ return wrapped_f
@@ -0,0 +1,90 @@
1
+ """A simple timer class used to measure the time spent in various parts of the BEM solver."""
2
+
3
+ from functools import wraps
4
+ import time
5
+ import contextlib
6
+
7
+ import pandas as pd
8
+
9
+ class Timer:
10
+ """A timer class that can be used as context manager or as decorator using `wraps_function` method.
11
+ Several timing measurement can be nested.
12
+
13
+ Attributes
14
+ ----------
15
+ timings: List[Dict]]
16
+ List of records of each timing measurement.
17
+ The record is a dict with a 'timing' key and any number of other metadata keys.
18
+ default_tags: Optional[Dict]
19
+ Tags added to all the timing measurements.
20
+ _start_times: List[float]
21
+ Start times of the ongoing timing measurements.
22
+
23
+ Example
24
+ -------
25
+ ::
26
+ from time import sleep # For testing
27
+
28
+ timer = Timer()
29
+
30
+ with timer(tag="run 1"):
31
+ sleep(1.0)
32
+
33
+ print(timer.total) # 1.0...
34
+
35
+ @timer.wraps_function(tag="run function")
36
+ def my_function():
37
+ sleep(0.5)
38
+
39
+ my_function()
40
+ print(timer.total) # 1.5...
41
+ my_function()
42
+ print(timer.total) # 2.0...
43
+
44
+ with timer(tag="outer"):
45
+ sleep(0.3)
46
+ with timer(tag="inner"):
47
+ sleep(0.3)
48
+ sleep(0.3)
49
+ """
50
+ def __init__(self, *, default_tags=None):
51
+ self.timings = []
52
+ if default_tags is None:
53
+ default_tags = {}
54
+ self.default_tags = default_tags
55
+ self._start_times = [] # Starting time of ongoing sub-timers
56
+
57
+ def __repr__(self):
58
+ return f"Timer({self.timings})"
59
+
60
+ def add_data_from_other_timer(self, other, **supplementary_tags):
61
+ self.timings.extend([{**t, **supplementary_tags} for t in other.timings])
62
+
63
+ @contextlib.contextmanager
64
+ def __call__(self, **tags):
65
+ self._start_times.append(time.perf_counter())
66
+ try:
67
+ yield
68
+ finally:
69
+ timing = time.perf_counter() - self._start_times.pop()
70
+ self.timings.append({'timing': timing, **tags, **self.default_tags})
71
+
72
+ def wraps_function(self, **tags):
73
+ def wrapper(f):
74
+ @wraps(f)
75
+ def wrapped_f(*args, **kwargs):
76
+ with self(**tags):
77
+ out = f(*args, **kwargs)
78
+ return out
79
+ return wrapped_f
80
+ return wrapper
81
+
82
+ def as_dataframe(self):
83
+ if len(self.timings) == 0:
84
+ return pd.DataFrame([{'timing': 0.0}])
85
+ else:
86
+ return pd.DataFrame(self.timings)
87
+
88
+ @property
89
+ def total(self):
90
+ return self.as_dataframe()['timing'].sum()
File without changes
capytaine/ui/cli.py ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env python
2
+ # coding: utf-8
3
+ """Experimental command-line interface for Capytaine."""
4
+ # Copyright (C) 2017-2023 Matthieu Ancellin
5
+ # See LICENSE file at <https://github.com/capytaine/capytaine>
6
+
7
+ import argparse
8
+
9
+ import capytaine as cpt
10
+ from capytaine.io.legacy import run_cal_file
11
+
12
+ cpt.set_logging()
13
+
14
+ parser = argparse.ArgumentParser(description="Command-line interface for Capytaine taking Nemoh.cal files as input and returning Tecplots files.")
15
+ parser.add_argument('paramfiles',
16
+ default=['./Nemoh.cal'],
17
+ nargs='*',
18
+ help='path of parameters files (default: ./Nemoh.cal)')
19
+
20
+
21
+ def main():
22
+ args = parser.parse_args()
23
+ for paramfile in args.paramfiles:
24
+ run_cal_file(paramfile)
25
+
26
+
27
+ if __name__ == '__main__':
28
+ main()
capytaine/ui/rich.py ADDED
@@ -0,0 +1,5 @@
1
+ import logging
2
+ from rich.logging import RichHandler
3
+
4
+ def set_logging(level="INFO"):
5
+ logging.basicConfig(level=level, format="%(message)s", handlers=[RichHandler(level=level, log_time_format="[%X]", show_path=False)], force=True)