physioblocks 1.0.1__py3-none-any.whl → 1.0.3__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.
- physioblocks/__init__.py +1 -1
- physioblocks/configuration/constants.py +2 -5
- physioblocks/configuration/simulation/simulations.py +11 -7
- physioblocks/library/aliases/simulations/circulation_alone_forward_simulation.jsonc +1 -3
- physioblocks/library/model_components/dynamics.py +4 -6
- physioblocks/simulation/runtime.py +1 -35
- physioblocks/simulation/solvers.py +34 -34
- physioblocks/simulation/state.py +67 -4
- physioblocks/utils/gradient_test_utils.py +11 -31
- {physioblocks-1.0.1.dist-info → physioblocks-1.0.3.dist-info}/METADATA +5 -2
- {physioblocks-1.0.1.dist-info → physioblocks-1.0.3.dist-info}/RECORD +14 -14
- {physioblocks-1.0.1.dist-info → physioblocks-1.0.3.dist-info}/WHEEL +0 -0
- {physioblocks-1.0.1.dist-info → physioblocks-1.0.3.dist-info}/licenses/licenses/GPL-3.0-only.txt +0 -0
- {physioblocks-1.0.1.dist-info → physioblocks-1.0.3.dist-info}/licenses/licenses/LGPL-3.0-only.txt +0 -0
physioblocks/__init__.py
CHANGED
|
@@ -38,11 +38,8 @@ PARAMETERS_ID = "parameters"
|
|
|
38
38
|
# Definition of the flux-dof types couples
|
|
39
39
|
FLUX_DOF_DEFINITION_ID = "flux_dof_definitions"
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
# The variable magnitude item label in the configuration
|
|
45
|
-
MAGNITUDES = "magnitudes"
|
|
41
|
+
# Options label for specific simulation types
|
|
42
|
+
SIMULATION_OPTIONS = "simulation_options"
|
|
46
43
|
|
|
47
44
|
# The variable magnitude item label in the configuration
|
|
48
45
|
VARIABLES_MAGNITUDES = "variables_magnitudes"
|
|
@@ -35,10 +35,10 @@ from typing import Any
|
|
|
35
35
|
from physioblocks.configuration.base import Configuration, ConfigurationError
|
|
36
36
|
from physioblocks.configuration.constants import (
|
|
37
37
|
INIT_VARIABLES_ID,
|
|
38
|
-
MAGNITUDES,
|
|
39
38
|
NET_ID,
|
|
40
39
|
OUTPUTS_FUNCTIONS_ID,
|
|
41
40
|
PARAMETERS_ID,
|
|
41
|
+
SIMULATION_OPTIONS,
|
|
42
42
|
SOLVER_ID,
|
|
43
43
|
TIME_MANAGER_ID,
|
|
44
44
|
VARIABLES_MAGNITUDES,
|
|
@@ -86,16 +86,15 @@ def load_simulation_config(
|
|
|
86
86
|
if SOLVER_ID in config:
|
|
87
87
|
solver = load(config[SOLVER_ID])
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
magnitudes = load(config[VARIABLES_MAGNITUDES])
|
|
89
|
+
simulation_options = None
|
|
90
|
+
if SIMULATION_OPTIONS in config:
|
|
91
|
+
simulation_options = load(config[SIMULATION_OPTIONS])
|
|
93
92
|
|
|
94
93
|
sim_factory = SimulationFactory(
|
|
95
94
|
configuration_type,
|
|
96
95
|
solver,
|
|
97
96
|
net,
|
|
98
|
-
simulation_options=
|
|
97
|
+
simulation_options=simulation_options,
|
|
99
98
|
)
|
|
100
99
|
|
|
101
100
|
configuration_object = sim_factory.create_simulation()
|
|
@@ -147,7 +146,7 @@ def save_simulation_config(
|
|
|
147
146
|
type(variable_init_values).__name__,
|
|
148
147
|
)
|
|
149
148
|
)
|
|
150
|
-
sim_config[VARIABLES_MAGNITUDES] = save(simulation.magnitudes)
|
|
149
|
+
sim_config[VARIABLES_MAGNITUDES] = save(simulation.state.magnitudes)
|
|
151
150
|
|
|
152
151
|
# Parameters
|
|
153
152
|
# Get quantities
|
|
@@ -226,6 +225,11 @@ def _configure_simulation(
|
|
|
226
225
|
configuration_references=simulation.quantities,
|
|
227
226
|
)
|
|
228
227
|
|
|
228
|
+
# magnitudes
|
|
229
|
+
if VARIABLES_MAGNITUDES in config:
|
|
230
|
+
magnitudes = load(config[VARIABLES_MAGNITUDES])
|
|
231
|
+
simulation.state.set_variables_magnitudes(magnitudes)
|
|
232
|
+
|
|
229
233
|
references.update(simulation.quantities)
|
|
230
234
|
references.update(simulation.models)
|
|
231
235
|
|
|
@@ -902,7 +902,9 @@ class SphericalDynamicsModelComponent(ModelComponent):
|
|
|
902
902
|
eq_system = EqSystem(1)
|
|
903
903
|
|
|
904
904
|
state = State()
|
|
905
|
-
state.add_variable(
|
|
905
|
+
state.add_variable(
|
|
906
|
+
SPHERICAL_DYNAMICS_STATIC_DISP_LOCAL_ID, 1, _STATIC_PROBLEM_DISP_MAG
|
|
907
|
+
)
|
|
906
908
|
state[SPHERICAL_DYNAMICS_STATIC_DISP_LOCAL_ID].initialize(self.disp.current)
|
|
907
909
|
|
|
908
910
|
static_block = _SphericalDynamicsStaticModelComponent(
|
|
@@ -942,11 +944,7 @@ class SphericalDynamicsModelComponent(ModelComponent):
|
|
|
942
944
|
p_test <= static_block.pressure.current
|
|
943
945
|
and p_test > _STATIC_PROBLEM_MIN_PRESSURE_STEP
|
|
944
946
|
):
|
|
945
|
-
sol = solver.solve(
|
|
946
|
-
state,
|
|
947
|
-
eq_system,
|
|
948
|
-
{SPHERICAL_DYNAMICS_STATIC_DISP_LOCAL_ID: _STATIC_PROBLEM_DISP_MAG},
|
|
949
|
-
)
|
|
947
|
+
sol = solver.solve(state, eq_system)
|
|
950
948
|
|
|
951
949
|
if sol.converged is True:
|
|
952
950
|
state[SPHERICAL_DYNAMICS_STATIC_DISP_LOCAL_ID].initialize(sol.x[0])
|
|
@@ -96,9 +96,6 @@ class AbstractSimulation(ABC):
|
|
|
96
96
|
|
|
97
97
|
:param eq_system: the equation system to solve at each time step
|
|
98
98
|
:type eq_system: EqSystem
|
|
99
|
-
|
|
100
|
-
:param magnitudes: magnitude of the state variables
|
|
101
|
-
:type magnitudes: dict[str, float]
|
|
102
99
|
"""
|
|
103
100
|
|
|
104
101
|
def __init__(
|
|
@@ -111,7 +108,6 @@ class AbstractSimulation(ABC):
|
|
|
111
108
|
models: dict[str, ModelComponent],
|
|
112
109
|
solver: AbstractSolver,
|
|
113
110
|
eq_system: EqSystem,
|
|
114
|
-
magnitudes: dict[str, float] | None = None,
|
|
115
111
|
):
|
|
116
112
|
self.factory = factory
|
|
117
113
|
self.state = state
|
|
@@ -121,9 +117,6 @@ class AbstractSimulation(ABC):
|
|
|
121
117
|
self.time_manager = time_manager
|
|
122
118
|
self.solver = solver
|
|
123
119
|
self.eq_system = eq_system
|
|
124
|
-
if magnitudes is None:
|
|
125
|
-
magnitudes = {}
|
|
126
|
-
self.magnitudes = self._check_magnitudes(magnitudes, state)
|
|
127
120
|
self._timed_updates: dict[str, AbstractFunction] = {}
|
|
128
121
|
self._output_functions_updates: dict[str, AbstractFunction] = {}
|
|
129
122
|
|
|
@@ -272,33 +265,6 @@ class AbstractSimulation(ABC):
|
|
|
272
265
|
self.time_manager.time.initialize(self.time_manager.start)
|
|
273
266
|
self.state.set_state_vector(self._initial_state)
|
|
274
267
|
|
|
275
|
-
def _check_magnitudes(
|
|
276
|
-
self, magnitudes: dict[str, float], state: State
|
|
277
|
-
) -> dict[str, float]:
|
|
278
|
-
checked_magnitudes = {}
|
|
279
|
-
|
|
280
|
-
for variable_id in state:
|
|
281
|
-
if variable_id not in magnitudes:
|
|
282
|
-
message = str.format(
|
|
283
|
-
"No magnitude initialized for variable {0}. Magnitude set to 1.0",
|
|
284
|
-
variable_id,
|
|
285
|
-
)
|
|
286
|
-
_logger.warning(message)
|
|
287
|
-
checked_magnitudes[variable_id] = 1.0
|
|
288
|
-
|
|
289
|
-
elif magnitudes[variable_id] == 0.0:
|
|
290
|
-
message = str.format(
|
|
291
|
-
"Magnitude for variable {0} is initialized to 0.0. "
|
|
292
|
-
"Replacing with 1.0",
|
|
293
|
-
variable_id,
|
|
294
|
-
)
|
|
295
|
-
_logger.warning(message)
|
|
296
|
-
checked_magnitudes[variable_id] = 1.0
|
|
297
|
-
else:
|
|
298
|
-
checked_magnitudes[variable_id] = magnitudes[variable_id]
|
|
299
|
-
|
|
300
|
-
return checked_magnitudes
|
|
301
|
-
|
|
302
268
|
@abstractmethod
|
|
303
269
|
def run(self) -> Results:
|
|
304
270
|
"""
|
|
@@ -406,7 +372,7 @@ class ForwardSimulation(AbstractSimulation):
|
|
|
406
372
|
):
|
|
407
373
|
self.state.reset_state_vector()
|
|
408
374
|
|
|
409
|
-
sol = self.solver.solve(self.state, self.eq_system
|
|
375
|
+
sol = self.solver.solve(self.state, self.eq_system)
|
|
410
376
|
|
|
411
377
|
if sol.converged is False:
|
|
412
378
|
inter_time = 0.5 * self.time_manager.current_step_size
|
|
@@ -81,31 +81,8 @@ class AbstractSolver(ABC):
|
|
|
81
81
|
self.tolerance = tolerance
|
|
82
82
|
self.iteration_max = iteration_max
|
|
83
83
|
|
|
84
|
-
def _get_state_magnitude(
|
|
85
|
-
self, state: State, magnitudes: dict[str, float] | None = None
|
|
86
|
-
) -> NDArray[np.float64]:
|
|
87
|
-
if magnitudes is None:
|
|
88
|
-
return np.ones(
|
|
89
|
-
state.size,
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
mag_dict = {}
|
|
93
|
-
for var_mag_key, var_mag_value in magnitudes.items():
|
|
94
|
-
var_index = state.get_variable_index(var_mag_key)
|
|
95
|
-
mag_dict[var_index] = var_mag_value
|
|
96
|
-
sorted_mag = sorted(mag_dict.items())
|
|
97
|
-
state_mag_list = [x[1] for x in sorted_mag]
|
|
98
|
-
return np.array(
|
|
99
|
-
state_mag_list,
|
|
100
|
-
)
|
|
101
|
-
|
|
102
84
|
@abstractmethod
|
|
103
|
-
def solve(
|
|
104
|
-
self,
|
|
105
|
-
state: State,
|
|
106
|
-
system: EqSystem,
|
|
107
|
-
magnitudes: dict[str, float] | None = None,
|
|
108
|
-
) -> Solution:
|
|
85
|
+
def solve(self, state: State, system: EqSystem) -> Solution:
|
|
109
86
|
"""
|
|
110
87
|
Child classes have to override this method
|
|
111
88
|
|
|
@@ -114,6 +91,31 @@ class AbstractSolver(ABC):
|
|
|
114
91
|
"""
|
|
115
92
|
|
|
116
93
|
|
|
94
|
+
LINEAR_SOLVER = "linear_solver"
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@register_type(LINEAR_SOLVER)
|
|
98
|
+
class LinearSolver(AbstractSolver):
|
|
99
|
+
"""
|
|
100
|
+
Implementation of the :class:`~.AbstractSolver` class for linear problems.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
def solve(self, state: State, system: EqSystem) -> Solution:
|
|
104
|
+
"""
|
|
105
|
+
Solve the equation system directly
|
|
106
|
+
|
|
107
|
+
:return: the solution
|
|
108
|
+
:rtype: Solution
|
|
109
|
+
"""
|
|
110
|
+
res = system.compute_residual()
|
|
111
|
+
grad = system.compute_gradient()
|
|
112
|
+
|
|
113
|
+
xn = np.linalg.solve(grad, res)
|
|
114
|
+
x = state.state_vector - xn
|
|
115
|
+
|
|
116
|
+
return Solution(x, True)
|
|
117
|
+
|
|
118
|
+
|
|
117
119
|
# Type id for the Newton Solver
|
|
118
120
|
NEWTON_SOLVER_TYPE_ID = "newton_solver"
|
|
119
121
|
|
|
@@ -166,12 +168,7 @@ class NewtonSolver(AbstractSolver):
|
|
|
166
168
|
grad_rescaled = gradient * grad_mag_inv
|
|
167
169
|
return res_rescaled, grad_rescaled
|
|
168
170
|
|
|
169
|
-
def solve(
|
|
170
|
-
self,
|
|
171
|
-
state: State,
|
|
172
|
-
system: EqSystem,
|
|
173
|
-
magnitudes: dict[str, float] | None = None,
|
|
174
|
-
) -> Solution:
|
|
171
|
+
def solve(self, state: State, system: EqSystem) -> Solution:
|
|
175
172
|
"""
|
|
176
173
|
Solve the equation system using the Newton method.
|
|
177
174
|
|
|
@@ -183,15 +180,16 @@ class NewtonSolver(AbstractSolver):
|
|
|
183
180
|
try:
|
|
184
181
|
i = 0
|
|
185
182
|
# initialize residual and magnitude
|
|
186
|
-
state_mag = self._get_state_magnitude(state, magnitudes)
|
|
187
183
|
res = np.ones(state.state_vector.shape)
|
|
188
184
|
|
|
189
185
|
# step 0 outside ou the loop to compute the residual and gradient
|
|
190
186
|
# magnitude
|
|
191
187
|
res, grad = self._compute_residual_and_gradient(system)
|
|
192
|
-
res_mag_inv, grad_mag_inv = self._compute_res_grad_mag(
|
|
188
|
+
res_mag_inv, grad_mag_inv = self._compute_res_grad_mag(
|
|
189
|
+
grad, state.state_magnitudes
|
|
190
|
+
)
|
|
193
191
|
res, grad = self._rescale_res_grad(res, res_mag_inv, grad, grad_mag_inv)
|
|
194
|
-
x = self._compute_new_state(state, res, grad,
|
|
192
|
+
x = self._compute_new_state(state, res, grad, state.state_magnitudes)
|
|
195
193
|
state.update_state_vector(x)
|
|
196
194
|
|
|
197
195
|
# Begin loop at iteration 1 (0 already done)
|
|
@@ -204,7 +202,9 @@ class NewtonSolver(AbstractSolver):
|
|
|
204
202
|
res, grad = self._rescale_res_grad(
|
|
205
203
|
res, res_mag_inv, grad, grad_mag_inv
|
|
206
204
|
)
|
|
207
|
-
x = self._compute_new_state(
|
|
205
|
+
x = self._compute_new_state(
|
|
206
|
+
state, res, grad, state.state_magnitudes
|
|
207
|
+
)
|
|
208
208
|
state.update_state_vector(x)
|
|
209
209
|
i += 1
|
|
210
210
|
|
physioblocks/simulation/state.py
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
Define the **State** that holds simulation variables.
|
|
29
29
|
"""
|
|
30
30
|
|
|
31
|
-
from collections.abc import Callable, Generator, Mapping
|
|
31
|
+
from collections.abc import Callable, Generator, Mapping, Sized
|
|
32
32
|
from pprint import pformat
|
|
33
33
|
from typing import Any
|
|
34
34
|
|
|
@@ -53,8 +53,12 @@ class State:
|
|
|
53
53
|
_variables: dict[str, Quantity[Any]]
|
|
54
54
|
"""The variables ids and quantities values"""
|
|
55
55
|
|
|
56
|
+
_magnitudes: dict[str, Any]
|
|
57
|
+
"""The variables magnitudes"""
|
|
58
|
+
|
|
56
59
|
def __init__(self) -> None:
|
|
57
60
|
self._variables = {}
|
|
61
|
+
self._magnitudes = {}
|
|
58
62
|
|
|
59
63
|
@property
|
|
60
64
|
def size(self) -> int:
|
|
@@ -76,6 +80,16 @@ class State:
|
|
|
76
80
|
"""
|
|
77
81
|
return self._variables.copy()
|
|
78
82
|
|
|
83
|
+
@property
|
|
84
|
+
def magnitudes(self) -> dict[str, Any]:
|
|
85
|
+
"""
|
|
86
|
+
Get a mapping of variables names and magnitudes.
|
|
87
|
+
|
|
88
|
+
:return: the variables names and magnitudes.
|
|
89
|
+
:rtype: dict[str, Quantity]
|
|
90
|
+
"""
|
|
91
|
+
return self._magnitudes.copy()
|
|
92
|
+
|
|
79
93
|
@property
|
|
80
94
|
def state_vector(self) -> NDArray[np.float64]:
|
|
81
95
|
"""
|
|
@@ -91,8 +105,23 @@ class State:
|
|
|
91
105
|
else:
|
|
92
106
|
return np.array([])
|
|
93
107
|
|
|
94
|
-
|
|
95
|
-
|
|
108
|
+
@property
|
|
109
|
+
def state_magnitudes(self) -> NDArray[np.float64]:
|
|
110
|
+
"""
|
|
111
|
+
Get the state variables magnitudes.
|
|
112
|
+
|
|
113
|
+
:return: the state variables magnitudes
|
|
114
|
+
:rtype: NDArray[np.float64]
|
|
115
|
+
"""
|
|
116
|
+
if len(self._variables) > 0:
|
|
117
|
+
return np.concatenate(
|
|
118
|
+
[self._magnitudes[var_id] for var_id in self._variables], axis=None
|
|
119
|
+
)
|
|
120
|
+
else:
|
|
121
|
+
return np.array([])
|
|
122
|
+
|
|
123
|
+
def __array__(self, *args: Any, **kwargs: Any) -> NDArray[Any]:
|
|
124
|
+
return np.array(self.state_vector, *args, **kwargs)
|
|
96
125
|
|
|
97
126
|
def __getitem__(self, var_id: str) -> Quantity[Any]:
|
|
98
127
|
"""
|
|
@@ -311,7 +340,7 @@ class State:
|
|
|
311
340
|
quantity_part = x[var_index : var_index + quantity.size]
|
|
312
341
|
func(quantity, quantity_part)
|
|
313
342
|
|
|
314
|
-
def add_variable(self, var_id: str, var_value: Any) -> None:
|
|
343
|
+
def add_variable(self, var_id: str, var_value: Any, magnitude: Any = None) -> None:
|
|
315
344
|
"""
|
|
316
345
|
Add a variable to the state.
|
|
317
346
|
|
|
@@ -328,6 +357,21 @@ class State:
|
|
|
328
357
|
quantity = var_value if isinstance(var_value, Quantity) else Quantity(var_value)
|
|
329
358
|
self._variables[var_id] = quantity
|
|
330
359
|
|
|
360
|
+
if magnitude is not None:
|
|
361
|
+
if quantity.size == 1 and isinstance(magnitude, float):
|
|
362
|
+
self._magnitudes[var_id] = magnitude
|
|
363
|
+
elif isinstance(magnitude, float):
|
|
364
|
+
self._magnitudes[var_id] = [magnitude] * quantity.size
|
|
365
|
+
elif isinstance(magnitude, Sized) and len(magnitude) == quantity.size:
|
|
366
|
+
self._magnitudes[var_id] = magnitude
|
|
367
|
+
else:
|
|
368
|
+
raise ValueError("Variable and magnitude sizes mismatch")
|
|
369
|
+
else:
|
|
370
|
+
if quantity.size == 1:
|
|
371
|
+
self._magnitudes[var_id] = 1.0
|
|
372
|
+
else:
|
|
373
|
+
self._magnitudes[var_id] = [1.0] * quantity.size
|
|
374
|
+
|
|
331
375
|
def remove_variable(self, var_id: str) -> None:
|
|
332
376
|
"""
|
|
333
377
|
Remove a variable from the state
|
|
@@ -338,3 +382,22 @@ class State:
|
|
|
338
382
|
# remove the variable
|
|
339
383
|
if var_id in self._variables:
|
|
340
384
|
self._variables.pop(var_id)
|
|
385
|
+
|
|
386
|
+
if var_id in self._magnitudes:
|
|
387
|
+
self._magnitudes.pop(var_id)
|
|
388
|
+
|
|
389
|
+
def set_variables_magnitudes(self, magnitudes: dict[str, Any]) -> None:
|
|
390
|
+
"""
|
|
391
|
+
Update all the state variables magnitudes.
|
|
392
|
+
|
|
393
|
+
:param magnitudes: the state variables magnitudes
|
|
394
|
+
:type magnitudes: dict[str, Any]
|
|
395
|
+
|
|
396
|
+
:raise KeyError: Raise a KeyError if one or more of the magnitude parameters key
|
|
397
|
+
is not in the state.
|
|
398
|
+
"""
|
|
399
|
+
|
|
400
|
+
if set(magnitudes.keys()).issubset(self._variables.keys()) is False:
|
|
401
|
+
difference = set(magnitudes.keys()).difference(self._variables.keys())
|
|
402
|
+
raise KeyError(str.format("State has no variables named {0}.", difference))
|
|
403
|
+
self._magnitudes.update(magnitudes)
|
|
@@ -77,22 +77,16 @@ def gradient_test_from_file(config_file_path: str) -> bool:
|
|
|
77
77
|
:param config_file_path: the file path to the simulation configuration file.
|
|
78
78
|
:type config_file_path: str
|
|
79
79
|
|
|
80
|
-
:return: True if the gradient test is
|
|
80
|
+
:return: True if the gradient test is successful, false otherwise.
|
|
81
81
|
"""
|
|
82
82
|
configuration = read_json(config_file_path)
|
|
83
83
|
configuration = unwrap_aliases(configuration)
|
|
84
84
|
sim: AbstractSimulation = load(configuration)
|
|
85
85
|
sim._initialize() # noqa SLF001
|
|
86
|
-
return gradient_test(
|
|
87
|
-
sim.eq_system,
|
|
88
|
-
sim.state,
|
|
89
|
-
sim.solver._get_state_magnitude(sim.state, sim.magnitudes), # noqa: SLF001
|
|
90
|
-
)
|
|
86
|
+
return gradient_test(sim.eq_system, sim.state)
|
|
91
87
|
|
|
92
88
|
|
|
93
|
-
def gradient_test_from_model(
|
|
94
|
-
model: ModelComponent, state: State, state_magnitude: NDArray[np.float64]
|
|
95
|
-
) -> bool:
|
|
89
|
+
def gradient_test_from_model(model: ModelComponent, state: State) -> bool:
|
|
96
90
|
"""
|
|
97
91
|
Create an equation system for the given block only and perform a gradient test.
|
|
98
92
|
|
|
@@ -106,10 +100,7 @@ def gradient_test_from_model(
|
|
|
106
100
|
:param state: the state used to determine the variables in the model.
|
|
107
101
|
:type state: str
|
|
108
102
|
|
|
109
|
-
:
|
|
110
|
-
:type state_magnitude: str
|
|
111
|
-
|
|
112
|
-
:return: True if the gradient test is successfull, false otherwise.
|
|
103
|
+
:return: True if the gradient test is successful, false otherwise.
|
|
113
104
|
"""
|
|
114
105
|
line_index = 0
|
|
115
106
|
expressions = setup.SystemExpressions()
|
|
@@ -124,14 +115,11 @@ def gradient_test_from_model(
|
|
|
124
115
|
|
|
125
116
|
eq_system = setup.build_eq_system(expressions, state)
|
|
126
117
|
model.initialize()
|
|
127
|
-
return gradient_test(eq_system, state
|
|
118
|
+
return gradient_test(eq_system, state)
|
|
128
119
|
|
|
129
120
|
|
|
130
121
|
def gradient_test_from_expression(
|
|
131
|
-
expr: Expression,
|
|
132
|
-
expr_params: Any,
|
|
133
|
-
state: State,
|
|
134
|
-
state_magnitude: NDArray[np.float64],
|
|
122
|
+
expr: Expression, expr_params: Any, state: State
|
|
135
123
|
) -> bool:
|
|
136
124
|
"""
|
|
137
125
|
Create an equation system for the given expression only and perform a gradient test.
|
|
@@ -145,20 +133,15 @@ def gradient_test_from_expression(
|
|
|
145
133
|
:param state: the state used to determine the variables in the expression.
|
|
146
134
|
:type state: str
|
|
147
135
|
|
|
148
|
-
:
|
|
149
|
-
:type state_magnitude: str
|
|
150
|
-
|
|
151
|
-
:return: True if the gradient test is successfull, false otherwise.
|
|
136
|
+
:return: True if the gradient test is successful, false otherwise.
|
|
152
137
|
:rtype: bool
|
|
153
138
|
"""
|
|
154
139
|
|
|
155
140
|
eq_system = setup.build_eq_system([(0, expr, expr_params)], state)
|
|
156
|
-
return gradient_test(eq_system, state
|
|
141
|
+
return gradient_test(eq_system, state)
|
|
157
142
|
|
|
158
143
|
|
|
159
|
-
def gradient_test(
|
|
160
|
-
eq_system: EqSystem, state: State, state_magnitude: NDArray[np.float64]
|
|
161
|
-
) -> bool:
|
|
144
|
+
def gradient_test(eq_system: EqSystem, state: State) -> bool:
|
|
162
145
|
"""
|
|
163
146
|
Test the computed gradient for the equation system by comparing it to
|
|
164
147
|
a gradient estimated with finite differences.
|
|
@@ -170,9 +153,6 @@ def gradient_test(
|
|
|
170
153
|
:param state: system state
|
|
171
154
|
:type state: State
|
|
172
155
|
|
|
173
|
-
:param state_magnitude: the state variables magnitudes
|
|
174
|
-
:type state_magnitude: str
|
|
175
|
-
|
|
176
156
|
:return: True if the estimated and computed gradient meet tolerance,
|
|
177
157
|
False otherwise.
|
|
178
158
|
"""
|
|
@@ -180,9 +160,9 @@ def gradient_test(
|
|
|
180
160
|
_logger.info(str.format("State:{0}{1}", linesep, state))
|
|
181
161
|
_logger.info(str.format("System:{0}{1}", linesep, eq_system))
|
|
182
162
|
|
|
183
|
-
new_state = state.state_vector + _NEW_STATE_SHIFT_FACTOR *
|
|
163
|
+
new_state = state.state_vector + _NEW_STATE_SHIFT_FACTOR * state.state_magnitudes
|
|
184
164
|
|
|
185
|
-
shift_1 = _SHIFT_FACTOR *
|
|
165
|
+
shift_1 = _SHIFT_FACTOR * state.state_magnitudes
|
|
186
166
|
state.update_state_vector(new_state)
|
|
187
167
|
|
|
188
168
|
res = eq_system.compute_residual()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: physioblocks
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
4
4
|
Dynamic: Author
|
|
5
5
|
Dynamic: Author-email
|
|
6
6
|
Dynamic: License
|
|
@@ -124,4 +124,7 @@ python -m physioblocks.launcher references/spherical_heart_sim.jsonc -v -t -s Qu
|
|
|
124
124
|
```
|
|
125
125
|
|
|
126
126
|
|
|
127
|
-
Results will be available in the `$LAUNCHER_FOLDER_PATH$/simulations/QuickStart` series folder
|
|
127
|
+
Results will be available in the `$LAUNCHER_FOLDER_PATH$/simulations/QuickStart` series folder:
|
|
128
|
+
* the csv file contains the simulation results.
|
|
129
|
+
* the html allows you to visualize the results.
|
|
130
|
+
* the log and json files are here for debug purposes.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
physioblocks/__init__.py,sha256=
|
|
1
|
+
physioblocks/__init__.py,sha256=cISNrgJhzM89OfbdFh9adOQcp0TvpiqizNJtm-sBWEE,1169
|
|
2
2
|
physioblocks/base/__init__.py,sha256=2h6bk0fe8pwQvJ15Buytg4SZzYOH-Ep7WqoD6pd1eOQ,986
|
|
3
3
|
physioblocks/base/operators.py,sha256=uUfswQZsaMNd2bd7wsaxSGFIYLAr1hQCQ6SQfYawdBc,5689
|
|
4
4
|
physioblocks/base/registers.py,sha256=Cd0hmy1XqojjPQgb_jn4mGeAMTyWWgDkl3qJHCVjCRU,3119
|
|
@@ -9,7 +9,7 @@ physioblocks/computing/quantities.py,sha256=f2wU0VDylJ8nuUtOsV0FsA1mJnqNy1AvoK6-
|
|
|
9
9
|
physioblocks/configuration/__init__.py,sha256=XNeIev97Fc9DAy_mA3CAZ0kMif7Nkop9sCI38ZZ2wgM,1454
|
|
10
10
|
physioblocks/configuration/aliases.py,sha256=o7E54IYeW0NfmCX_r3zLKURVHsQoCmTlLD5085kY0eg,6302
|
|
11
11
|
physioblocks/configuration/base.py,sha256=eLxZXZdc4QkSsA7TOA0-E5ckfMZZkdgPJ6JVrFwM4nY,3627
|
|
12
|
-
physioblocks/configuration/constants.py,sha256=
|
|
12
|
+
physioblocks/configuration/constants.py,sha256=R72050sju7X_2kRtxY9mhyZ0btYLj8RaMeOsDoZT9DY,3046
|
|
13
13
|
physioblocks/configuration/functions.py,sha256=pJl5BkSwRoIydH3bSMNilu0wj7yOVJ_BVAPNS-yMl8k,23520
|
|
14
14
|
physioblocks/configuration/computing/__init__.py,sha256=duNJXdaHTZ9_V9XScNXjJgPsKSc6FbHGrwNDLrcYDg8,1012
|
|
15
15
|
physioblocks/configuration/computing/quantities.py,sha256=fM5L4YeeM1NQQjhbdU4e50yxZ9B2ogF0WzDIYqFDbgg,1721
|
|
@@ -17,7 +17,7 @@ physioblocks/configuration/description/__init__.py,sha256=-KyjKPheXzgKiVZ0jL-nl8
|
|
|
17
17
|
physioblocks/configuration/description/blocks.py,sha256=FGYFR5S15jGlZnIIfvZLdMr33bXabXMi9Vj9jETLeeM,8003
|
|
18
18
|
physioblocks/configuration/description/nets.py,sha256=wKAH1Qq_tQ65-bn17qV6c_n0dt__PtY9r8TnYtZsPTY,5124
|
|
19
19
|
physioblocks/configuration/simulation/__init__.py,sha256=RuRdBDvwqBcyghwh1D0ud3qwdUEcw2vgHPoB8drXp6w,1126
|
|
20
|
-
physioblocks/configuration/simulation/simulations.py,sha256=
|
|
20
|
+
physioblocks/configuration/simulation/simulations.py,sha256=bOf2a7rlYcw00XsoPspL2LBSTfAgl0HC7xCeMJiQ-Zs,8969
|
|
21
21
|
physioblocks/description/__init__.py,sha256=o6G4LgLuSKSXOF6Uex-nua-8MyWsiwBd_G4dQLJsA6Y,1200
|
|
22
22
|
physioblocks/description/blocks.py,sha256=y0qLvdE4VBmdDmOeHFaRFsmPRg-7_JVSGs2thAAUzHc,13542
|
|
23
23
|
physioblocks/description/flux.py,sha256=aKs31bO1KyfAlHhmWUP9ZS7V7SryyVe_6MZG_Sp9jCQ,4858
|
|
@@ -44,7 +44,7 @@ physioblocks/library/aliases/model_components/spherical_dynamics.json,sha256=Tcd
|
|
|
44
44
|
physioblocks/library/aliases/model_components/velocity_law_hht.json,sha256=HKbc5_2hGuOiQKUvLGto6tBQI_Z5AbbhXp8Itwmo2ag,93
|
|
45
45
|
physioblocks/library/aliases/nets/circulation_alone_net.json,sha256=M3TiXIXgaXCsdwfyA5cm3fqspViiIl0Kyb6NKMiFsQ8,874
|
|
46
46
|
physioblocks/library/aliases/nets/spherical_heart_net.json,sha256=UnOSQslMJuvbT6dXXPWj-HEvqe6U4fG1CK17_sKTxM8,3057
|
|
47
|
-
physioblocks/library/aliases/simulations/circulation_alone_forward_simulation.jsonc,sha256=
|
|
47
|
+
physioblocks/library/aliases/simulations/circulation_alone_forward_simulation.jsonc,sha256=F5MIEC-OI-VUcAhYU8SLesbZPAiy3Us1f4VuDd0TEiI,1948
|
|
48
48
|
physioblocks/library/aliases/simulations/default_forward_simulation.jsonc,sha256=TE_82KWUYAQdMX4MpDGY-Hi_djpwYAhSB5uzYtzYqcA,136
|
|
49
49
|
physioblocks/library/aliases/simulations/default_time.jsonc,sha256=LM2_EU-GvOeGXJMvXXyJeWEOv-cfy25luhcaSMj5hkw,165
|
|
50
50
|
physioblocks/library/aliases/simulations/newton_method_solver.json,sha256=p0jgVCpySTR0Npo5iFZrUUys3SRcy4j_EesQw9SvoyA,79
|
|
@@ -62,7 +62,7 @@ physioblocks/library/functions/trigonometric.py,sha256=Y5UolXZTASEi4EH_GpLpUIxMZ
|
|
|
62
62
|
physioblocks/library/functions/watchers.py,sha256=fY1SSPn-7R9cix0VMFP69H5-pmJzl4OXs1tgvjCetvM,3212
|
|
63
63
|
physioblocks/library/model_components/__init__.py,sha256=JcDL2PaPTrT9mTlDUbPjUsyFfsiGh5GgroJ7J3g2uwE,998
|
|
64
64
|
physioblocks/library/model_components/active_law.py,sha256=97D3fC7Dmzw8jLqDALxUJgl48EZYOx39SYjZgGJx-Eo,11634
|
|
65
|
-
physioblocks/library/model_components/dynamics.py,sha256=
|
|
65
|
+
physioblocks/library/model_components/dynamics.py,sha256=T-ZmfhTgtr1Tj6434GDYU-5XSztHx-dd6sf228c4cyo,35198
|
|
66
66
|
physioblocks/library/model_components/rheology.py,sha256=7x5RrB_0DXMWlm0mIrTxdLlsjXVa1WPuFYYifW4fKeg,4724
|
|
67
67
|
physioblocks/library/model_components/velocity_law.py,sha256=UYr9MywlLkRw0LszK0u_AamwThjobDMV9jYbaSbdDkU,5047
|
|
68
68
|
physioblocks/registers/__init__.py,sha256=trxT3MHDFX8cJ-IBX2cEIm8-uZBnfs2UkV8QDclq9so,1081
|
|
@@ -72,22 +72,22 @@ physioblocks/registers/type_register.py,sha256=JUlrPfP-X_TjIOHewSTkzf7Ck3L0ivVoH
|
|
|
72
72
|
physioblocks/simulation/__init__.py,sha256=wqKVI3OLLVWuQoUcWwKSs5ibdkTP3Da_5DOe36v1up4,1504
|
|
73
73
|
physioblocks/simulation/constants.py,sha256=w9CsB4V7YtvcdW4N1p7Iu6MeV4i-kazcEPAygE7mSx0,1075
|
|
74
74
|
physioblocks/simulation/functions.py,sha256=c6HFwXK8IAzH7gSkz9aMiXLqnWXn_4_9WsX4jrGN9pY,2307
|
|
75
|
-
physioblocks/simulation/runtime.py,sha256=
|
|
75
|
+
physioblocks/simulation/runtime.py,sha256=JDRBoN5lSDUmEKohXIWPadxjO6JcFHd7JYzUlkFrzxE,15498
|
|
76
76
|
physioblocks/simulation/saved_quantities.py,sha256=fKWr1wScqxHPhuCE7aDNs8lpm9oWfyLN8NZDus2knPM,4111
|
|
77
77
|
physioblocks/simulation/setup.py,sha256=UmIklaHmfkxi_BIdYKOhorLoC9QT9D4oEXwC-Xfd6v0,18109
|
|
78
|
-
physioblocks/simulation/solvers.py,sha256=
|
|
79
|
-
physioblocks/simulation/state.py,sha256=
|
|
78
|
+
physioblocks/simulation/solvers.py,sha256=xztL-QboEO2mgtws13QE0-wHJ22vjQQzAQahYfxXVBQ,7226
|
|
79
|
+
physioblocks/simulation/state.py,sha256=YOWqJSSHgTzMZEmaR4SX4qsckFZ_UQVfJ-jQ5niAUPc,12628
|
|
80
80
|
physioblocks/simulation/time_manager.py,sha256=AbP_Y8mcG7-6x-3rGY5CHFQwKMqksO4HvdCJ-mU03d4,9381
|
|
81
81
|
physioblocks/utils/__init__.py,sha256=EMwPHVznBryA1uOEFfY_11L9Sd9bdCU_x_huNgIaZtQ,988
|
|
82
82
|
physioblocks/utils/dynamic_import_utils.py,sha256=AvGFRYPQcI2JSVpScXCgnYJDgF2uh8QI7xBewoe_9Ks,4862
|
|
83
83
|
physioblocks/utils/exceptions_utils.py,sha256=2w2q1XP-UDnxCXFu4XI2k1-jLUub24oYuwdUfd6tOkE,3421
|
|
84
|
-
physioblocks/utils/gradient_test_utils.py,sha256=
|
|
84
|
+
physioblocks/utils/gradient_test_utils.py,sha256=ISvkFk-HPbBafwmi9Zqimo6Dpb6yJpcLyyAoTge63RA,10666
|
|
85
85
|
physioblocks/utils/math_utils.py,sha256=w5MDs4cP5WiTPHe8WofFuNZZ20WDNLT0XmFGlbisJJ0,2881
|
|
86
86
|
physioblocks/references/circulation_alone_sim.jsonc,sha256=qv27nzmK7jennhtCJ7wQ_f83mt9_YJSOTABjGCYMcZw,736
|
|
87
87
|
physioblocks/references/spherical_heart_respiration_sim.jsonc,sha256=kKq5xf94r90O1KpkCHk1qwgy6DJ37ePo3-8buEtcu5Y,1397
|
|
88
88
|
physioblocks/references/spherical_heart_sim.jsonc,sha256=kGGBqxY8dnmGKmpMv216kbneyJRGz_3VkcYn1OWavIA,1151
|
|
89
|
-
physioblocks-1.0.
|
|
90
|
-
physioblocks-1.0.
|
|
91
|
-
physioblocks-1.0.
|
|
92
|
-
physioblocks-1.0.
|
|
93
|
-
physioblocks-1.0.
|
|
89
|
+
physioblocks-1.0.3.dist-info/METADATA,sha256=-_Pm7SVFyAzY4eHI79u3CGR93C-Yo5iWGwUJzDtM6gM,4708
|
|
90
|
+
physioblocks-1.0.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
91
|
+
physioblocks-1.0.3.dist-info/licenses/licenses/GPL-3.0-only.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
92
|
+
physioblocks-1.0.3.dist-info/licenses/licenses/LGPL-3.0-only.txt,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
|
|
93
|
+
physioblocks-1.0.3.dist-info/RECORD,,
|
|
File without changes
|
{physioblocks-1.0.1.dist-info → physioblocks-1.0.3.dist-info}/licenses/licenses/GPL-3.0-only.txt
RENAMED
|
File without changes
|
{physioblocks-1.0.1.dist-info → physioblocks-1.0.3.dist-info}/licenses/licenses/LGPL-3.0-only.txt
RENAMED
|
File without changes
|