metablate 0.1.0__py3-none-any.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.
metablate/ode.py ADDED
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env python
2
+
3
+ """A type of ablation models that can be solved as IVP ODE's
4
+
5
+ """
6
+
7
+ from abc import abstractmethod
8
+ import logging
9
+
10
+ from scipy.integrate import solve_ivp
11
+ from .ablation_model import AblationModel
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class ScipyODESolve(AblationModel):
17
+ """A template class for a type of ablation model that can be solved as an IVP ODE
18
+ using `scipy.integrate.solve_ivp`. Implements the 'integrate` method that can be
19
+ called when constructing the `run` method. The integrate method uses the `rhs`
20
+ method to define the right-hand-side of the differential equation system.
21
+
22
+ Notes
23
+ -----
24
+ The integrate method uses an scipy "event" that detects low mass and prevents
25
+ overshooting of the ablation model, this event detection mass is the
26
+ `minimum_mass` config variable.
27
+ """
28
+
29
+ DEFAULT_CONFIG = {
30
+ "integrate": {
31
+ "minimum_mass_kg": 1e-11,
32
+ "max_step_size_sec": 1e-1,
33
+ "max_time_sec": 100.0,
34
+ "method": "RK45",
35
+ },
36
+ "method_options": {},
37
+ }
38
+
39
+ def integrate(self, state, *args, **kwargs):
40
+
41
+ def _low_mass(t, y):
42
+ res = y[0] / self.config.getfloat("integrate", "minimum_mass_kg") - 1
43
+ # logger.debug(
44
+ # f'Stopping @ {t:<1.4e} s = {res}: {np.log10(y[0]):1.4e} log10(kg) | {y[0]:1.4e} kg'
45
+ # )
46
+ return res
47
+
48
+ _low_mass.terminal = True
49
+ _low_mass.direction = -1
50
+
51
+ events = [_low_mass]
52
+
53
+ method = self.config.get("integrate", "method")
54
+ method_options = {key: val for key, val in self.config.items("method_options")}
55
+
56
+ logger.debug(
57
+ f"{self.__class__} integrating IVP:\n- method: "
58
+ f"{method}\n- method-options: {method_options}"
59
+ )
60
+ logger.debug(
61
+ "Config-integrate:\n"
62
+ "\n-- ".join([f"{key}: {val}" for key, val in self.config.items("integrate")])
63
+ )
64
+
65
+ ivp_result = solve_ivp(
66
+ fun=lambda t, y: self.rhs(t, y[0], y[1:], *args, **kwargs),
67
+ t_span=(0, self.config.getfloat("integrate", "max_time_sec")),
68
+ y0=state,
69
+ method=method,
70
+ max_step=self.config.getfloat("integrate", "max_step_size_sec"),
71
+ dense_output=False,
72
+ events=events,
73
+ **method_options,
74
+ )
75
+
76
+ logger.debug(f"{self.__class__} IVP integration complete")
77
+
78
+ return ivp_result
79
+
80
+ @abstractmethod
81
+ def rhs(self, t, m, y, *args, **kwargs):
82
+ pass
@@ -0,0 +1,5 @@
1
+ from . import alpha_beta
2
+ from . import luminosity
3
+ from . import sputtering
4
+ from . import thermal_ablation
5
+ from . import ballistic