physioblocks 1.0.3__tar.gz → 1.1.0__tar.gz

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 (221) hide show
  1. {physioblocks-1.0.3 → physioblocks-1.1.0}/PKG-INFO +1 -1
  2. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide/level_3/block_definition.rst +32 -106
  3. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/__init__.py +1 -1
  4. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/computing/models.py +313 -1
  5. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/blocks/capacitances.py +28 -80
  6. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/blocks/cavity.py +6 -24
  7. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/blocks/valves.py +10 -37
  8. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/model_components/active_law.py +37 -37
  9. physioblocks-1.1.0/tests/tests_computing/test_models.py +520 -0
  10. physioblocks-1.0.3/tests/tests_computing/test_models.py +0 -364
  11. {physioblocks-1.0.3 → physioblocks-1.1.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  12. {physioblocks-1.0.3 → physioblocks-1.1.0}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
  13. {physioblocks-1.0.3 → physioblocks-1.1.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  14. {physioblocks-1.0.3 → physioblocks-1.1.0}/.gitignore +0 -0
  15. {physioblocks-1.0.3 → physioblocks-1.1.0}/.gitlab/issue_templates/Bug.md +0 -0
  16. {physioblocks-1.0.3 → physioblocks-1.1.0}/.gitlab/issue_templates/Documentation.md +0 -0
  17. {physioblocks-1.0.3 → physioblocks-1.1.0}/.gitlab/issue_templates/Feature.md +0 -0
  18. {physioblocks-1.0.3 → physioblocks-1.1.0}/.gitlab-ci.yml +0 -0
  19. {physioblocks-1.0.3 → physioblocks-1.1.0}/README.md +0 -0
  20. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/.gitignore +0 -0
  21. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/Makefile +0 -0
  22. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/make.bat +0 -0
  23. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/api_reference/base.rst +0 -0
  24. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/api_reference/computing.rst +0 -0
  25. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/api_reference/configuration.rst +0 -0
  26. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/api_reference/description.rst +0 -0
  27. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/api_reference/io.rst +0 -0
  28. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/api_reference/registers.rst +0 -0
  29. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/api_reference/simulation.rst +0 -0
  30. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/api_reference/utils.rst +0 -0
  31. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/api_reference.rst +0 -0
  32. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/conf.py +0 -0
  33. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/index.rst +0 -0
  34. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/installation.rst +0 -0
  35. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/library/aliases/blocks.rst +0 -0
  36. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/library/aliases/model_components.rst +0 -0
  37. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/library/aliases/nets.rst +0 -0
  38. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/library/aliases/simulation.rst +0 -0
  39. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/library/aliases.rst +0 -0
  40. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/library/blocks.rst +0 -0
  41. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/library/configuration/functions.rst +0 -0
  42. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/library/configuration/net.rst +0 -0
  43. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/library/configuration/simulation.rst +0 -0
  44. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/library/configuration.rst +0 -0
  45. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/library/functions.rst +0 -0
  46. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/library/model_components.rst +0 -0
  47. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/library.rst +0 -0
  48. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/presentation.rst +0 -0
  49. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/schemes/assembling_example_scheme.tex +0 -0
  50. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/schemes/circulation_net_scheme.tex +0 -0
  51. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/schemes/circulation_net_scheme_heart.tex +0 -0
  52. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/schemes/model_heart_circulation_0D.tex +0 -0
  53. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/schemes/simple_circulation_model.tex +0 -0
  54. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/schemes/simple_circulation_model_heart.tex +0 -0
  55. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/schemes/spherical_heart_net_scheme.tex +0 -0
  56. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide/level_1/launch_simulation.rst +0 -0
  57. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide/level_1/launcher.rst +0 -0
  58. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide/level_1.rst +0 -0
  59. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide/level_2/aliases.rst +0 -0
  60. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide/level_2/create_net.rst +0 -0
  61. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide/level_2/create_simulation.rst +0 -0
  62. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide/level_2/overview.rst +0 -0
  63. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide/level_2.rst +0 -0
  64. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide/level_3/block_configuration.rst +0 -0
  65. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide/level_3/block_test.rst +0 -0
  66. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide/level_3/overview.rst +0 -0
  67. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide/level_3/specific_installations.rst +0 -0
  68. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide/level_3.rst +0 -0
  69. {physioblocks-1.0.3 → physioblocks-1.1.0}/doc/source/user_guide.rst +0 -0
  70. {physioblocks-1.0.3 → physioblocks-1.1.0}/docker/latex/Dockerfile +0 -0
  71. {physioblocks-1.0.3 → physioblocks-1.1.0}/docker/pyenv/Dockerfile +0 -0
  72. {physioblocks-1.0.3 → physioblocks-1.1.0}/licenses/GPL-3.0-only.txt +0 -0
  73. {physioblocks-1.0.3 → physioblocks-1.1.0}/licenses/LGPL-3.0-only.txt +0 -0
  74. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/base/__init__.py +0 -0
  75. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/base/operators.py +0 -0
  76. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/base/registers.py +0 -0
  77. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/computing/__init__.py +0 -0
  78. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/computing/assembling.py +0 -0
  79. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/computing/quantities.py +0 -0
  80. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/configuration/__init__.py +0 -0
  81. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/configuration/aliases.py +0 -0
  82. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/configuration/base.py +0 -0
  83. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/configuration/computing/__init__.py +0 -0
  84. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/configuration/computing/quantities.py +0 -0
  85. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/configuration/constants.py +0 -0
  86. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/configuration/description/__init__.py +0 -0
  87. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/configuration/description/blocks.py +0 -0
  88. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/configuration/description/nets.py +0 -0
  89. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/configuration/functions.py +0 -0
  90. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/configuration/simulation/__init__.py +0 -0
  91. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/configuration/simulation/simulations.py +0 -0
  92. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/description/__init__.py +0 -0
  93. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/description/blocks.py +0 -0
  94. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/description/flux.py +0 -0
  95. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/description/nets.py +0 -0
  96. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/io/__init__.py +0 -0
  97. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/io/aliases.py +0 -0
  98. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/io/configuration.py +0 -0
  99. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/launcher/__main__.py +0 -0
  100. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/launcher/configuration.py +0 -0
  101. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/launcher/configure/__main__.py +0 -0
  102. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/launcher/constants.py +0 -0
  103. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/launcher/files.py +0 -0
  104. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/launcher/series.py +0 -0
  105. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/__init__.py +0 -0
  106. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/blocks/c_block.json +0 -0
  107. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/blocks/rc_block.json +0 -0
  108. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/blocks/rcr_block.json +0 -0
  109. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/blocks/spherical_cavity_block.json +0 -0
  110. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/blocks/valve_rl_block.json +0 -0
  111. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/flux/heart_flux_dof_couples.jsonc +0 -0
  112. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/model_components/active_law_macro_huxley_two_moments.json +0 -0
  113. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/model_components/rheology_fiber_additive.json +0 -0
  114. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/model_components/spherical_dynamics.json +0 -0
  115. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/model_components/velocity_law_hht.json +0 -0
  116. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/nets/circulation_alone_net.json +0 -0
  117. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/nets/spherical_heart_net.json +0 -0
  118. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/simulations/circulation_alone_forward_simulation.jsonc +0 -0
  119. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/simulations/default_forward_simulation.jsonc +0 -0
  120. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/simulations/default_time.jsonc +0 -0
  121. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/simulations/newton_method_solver.json +0 -0
  122. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/simulations/spherical_heart_forward_simulation.jsonc +0 -0
  123. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/aliases/simulations/spherical_heart_with_respiration_forward_simulation.jsonc +0 -0
  124. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/blocks/__init__.py +0 -0
  125. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/functions/__init__.py +0 -0
  126. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/functions/base_operations.py +0 -0
  127. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/functions/first_order.py +0 -0
  128. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/functions/piecewise.py +0 -0
  129. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/functions/trigonometric.py +0 -0
  130. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/functions/watchers.py +0 -0
  131. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/model_components/__init__.py +0 -0
  132. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/model_components/dynamics.py +0 -0
  133. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/model_components/rheology.py +0 -0
  134. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/library/model_components/velocity_law.py +0 -0
  135. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/registers/__init__.py +0 -0
  136. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/registers/load_function_register.py +0 -0
  137. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/registers/save_function_register.py +0 -0
  138. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/registers/type_register.py +0 -0
  139. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/simulation/__init__.py +0 -0
  140. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/simulation/constants.py +0 -0
  141. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/simulation/functions.py +0 -0
  142. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/simulation/runtime.py +0 -0
  143. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/simulation/saved_quantities.py +0 -0
  144. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/simulation/setup.py +0 -0
  145. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/simulation/solvers.py +0 -0
  146. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/simulation/state.py +0 -0
  147. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/simulation/time_manager.py +0 -0
  148. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/utils/__init__.py +0 -0
  149. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/utils/dynamic_import_utils.py +0 -0
  150. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/utils/exceptions_utils.py +0 -0
  151. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/utils/gradient_test_utils.py +0 -0
  152. {physioblocks-1.0.3 → physioblocks-1.1.0}/physioblocks/utils/math_utils.py +0 -0
  153. {physioblocks-1.0.3 → physioblocks-1.1.0}/pyproject.toml +0 -0
  154. {physioblocks-1.0.3 → physioblocks-1.1.0}/references/circulation_alone_sim.jsonc +0 -0
  155. {physioblocks-1.0.3 → physioblocks-1.1.0}/references/spherical_heart_respiration_sim.jsonc +0 -0
  156. {physioblocks-1.0.3 → physioblocks-1.1.0}/references/spherical_heart_sim.jsonc +0 -0
  157. {physioblocks-1.0.3 → physioblocks-1.1.0}/ruff.toml +0 -0
  158. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/__init__.py +0 -0
  159. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/base/test_register.py +0 -0
  160. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/helpers/__init__.py +0 -0
  161. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/helpers/assertion_helpers.py +0 -0
  162. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/helpers/file_helpers.py +0 -0
  163. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_computing/test_assembling.py +0 -0
  164. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_computing/test_quantities.py +0 -0
  165. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_config/__init__.py +0 -0
  166. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_config/test_definitions.py +0 -0
  167. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_config/test_generic_save_load.py +0 -0
  168. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_config/tests_alias/test_alias.py +0 -0
  169. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_config/tests_description/__init__.py +0 -0
  170. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_config/tests_description/test_config_blocks.py +0 -0
  171. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_config/tests_description/test_config_boundary_condition.py +0 -0
  172. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_config/tests_description/test_config_nets.py +0 -0
  173. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_config/tests_simulation/__init__.py +0 -0
  174. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_config/tests_simulation/simulation_reference.json +0 -0
  175. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_config/tests_simulation/test_config_simulation.py +0 -0
  176. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_config/tests_simulation/test_config_solvers.py +0 -0
  177. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_config/tests_simulation/test_config_time.py +0 -0
  178. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_config/tests_simulation/test_functions.py +0 -0
  179. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_description/__init__.py +0 -0
  180. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_description/test_blocks.py +0 -0
  181. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_description/test_nets.py +0 -0
  182. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_description/test_relations.py +0 -0
  183. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_io/__init__.py +0 -0
  184. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_io/references/alt_config_file_path.json +0 -0
  185. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_io/references/commented_config_file_path.jsonc +0 -0
  186. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_io/references/configuration.json +0 -0
  187. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_io/test_aliases.py +0 -0
  188. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_io/test_configuration.py +0 -0
  189. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_library/tests_blocks/test_capacitances.py +0 -0
  190. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_library/tests_blocks/test_cavity.py +0 -0
  191. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_library/tests_blocks/test_valves.py +0 -0
  192. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_library/tests_functions/test_base_operations_functions.py +0 -0
  193. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_library/tests_functions/test_first_order_functions.py +0 -0
  194. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_library/tests_functions/test_piecewise_functions.py +0 -0
  195. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_library/tests_functions/test_trigonometric_functions.py +0 -0
  196. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_library/tests_functions/test_watch_functions.py +0 -0
  197. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_library/tests_model_components/test_active_law.py +0 -0
  198. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_library/tests_model_components/test_dynamics_block.py +0 -0
  199. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_library/tests_model_components/test_rheology.py +0 -0
  200. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_library/tests_model_components/test_velocity_law_hht.py +0 -0
  201. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_references/__init__.py +0 -0
  202. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_references/circulation_alone/circulation_alone_sim_gradient_test.json +0 -0
  203. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_references/circulation_alone/ref_circulation_alone_sim.csv +0 -0
  204. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_references/conftest.py +0 -0
  205. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_references/io.py +0 -0
  206. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_references/spherical_heart/ref_spherical_heart_respiration_sim.csv +0 -0
  207. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_references/spherical_heart/ref_spherical_heart_sim.csv +0 -0
  208. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_references/spherical_heart/spherical_heart_sim_gradient_test.json +0 -0
  209. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_references/test_circulation_alone.py +0 -0
  210. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_references/test_spherical_heart.py +0 -0
  211. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_registers/test_load_register.py +0 -0
  212. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_registers/test_save_register.py +0 -0
  213. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_registers/test_type_register.py +0 -0
  214. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_simulation/__init__.py +0 -0
  215. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_simulation/test_runtime.py +0 -0
  216. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_simulation/test_setup.py +0 -0
  217. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_simulation/test_solvers.py +0 -0
  218. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_simulation/test_state.py +0 -0
  219. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_simulation/test_time_manager.py +0 -0
  220. {physioblocks-1.0.3 → physioblocks-1.1.0}/tests/tests_utils/test_math_utils.py +0 -0
  221. {physioblocks-1.0.3 → physioblocks-1.1.0}/tox.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: physioblocks
3
- Version: 1.0.3
3
+ Version: 1.1.0
4
4
  Dynamic: Author
5
5
  Dynamic: Author-email
6
6
  Dynamic: License
@@ -185,10 +185,21 @@ Declare functions to compute the fluxes and the internal equations
185
185
 
186
186
  We define methods to compute the :class:`~physioblocks.computing.models.Block` relations as written above in the discretized form.
187
187
 
188
+ To make the methods available to build the residual matrix the methods are decorated to identify:
189
+
190
+ * **Fluxes** with :func:`~physioblocks.computing.models.declares_flux` decorator.
191
+ You will need to set the local node index where the flux is shared as well as the local name in the block of the dof at the node.
192
+ The default flux size is 1 but can be updated.
193
+ * **Internal equations** with :func:`~physioblocks.computing.models.declares_internal_equation` decorator.
194
+ You need to set at least the local name of the variable on which the equation provides a dynamic.
195
+ Default equation size is set to 1 and can be updated.
196
+
197
+
188
198
  .. code:: python
189
199
 
190
200
  # Flux definition
191
201
 
202
+ @declares_flux(1, "pressure_1")
192
203
  def flux_1(self):
193
204
  """
194
205
  Computes the flux at first node.
@@ -198,6 +209,7 @@ We define methods to compute the :class:`~physioblocks.computing.models.Block` r
198
209
 
199
210
  return (pressure_mid_discr - pressure_1_discr) / self.resistance_1.current
200
211
 
212
+ @declares_flux(2, "pressure_2")
201
213
  def flux_2(self):
202
214
  """
203
215
  Computes the flux at second node.
@@ -208,6 +220,7 @@ We define methods to compute the :class:`~physioblocks.computing.models.Block` r
208
220
  return (pressure_mid_discr - pressure_2_discr) / self.resistance_2.current
209
221
 
210
222
  # Internal Equation definition
223
+ @declares_internal_equation("pressure_mid")
211
224
  def residual_pressure_mid(self):
212
225
  """
213
226
  Computes the rcr block internal equation residual
@@ -222,7 +235,12 @@ We define methods to compute the :class:`~physioblocks.computing.models.Block` r
222
235
  - (pressure_2_discr - pressure_mid_discr) / self.resistance_2
223
236
  )
224
237
 
238
+ To be able to add output values that are not variables, we identify the saved quantities with :func:`~physioblocks.computing.models.declares_saved_quantity` decorator.
239
+
240
+ .. code:: python
241
+
225
242
  # Saved Quantity definition
243
+ @declares_saved_quantities("volume")
226
244
  def volume_stored(self):
227
245
  """
228
246
  Computes volume stored in the capacitance.
@@ -234,17 +252,21 @@ Declare all flux and internal equations partial derivatives
234
252
 
235
253
  We then have to declare functions to compute fluxes and internal equations partial derivatives.
236
254
 
237
- .. code:: python
255
+ To make the methods available to build the gradient matrix, the methods are decorated to identify function partial derivative with :func:`~physioblocks.computing.models.ExpressionDecorator.partial_derivative` decorator.
256
+ Each decorator associate the function with its the derivation variable local name.
238
257
 
239
- # Flux 0 partial derivatives
258
+ .. code:: python
240
259
 
260
+ # Flux 1 partial derivatives
261
+ @flux_1.partial_derivative("pressure_mid")
241
262
  def dflux_1_dpressure_mid(self):
242
263
  """
243
- Computes flux_1 partial derivative for pressure_1.
264
+ Computes flux_1 partial derivative for pressure_mid.
244
265
  """
245
266
 
246
267
  return 0.5 / self.resistance_1.current
247
268
 
269
+ @flux_1.partial_derivative("pressure_1")
248
270
  def dflux_1_dpressure_1(self):
249
271
  """
250
272
  Computes flux_1 partial derivative for pressure_1.
@@ -252,15 +274,17 @@ We then have to declare functions to compute fluxes and internal equations parti
252
274
 
253
275
  return - 0.5 / self.resistance_1.current
254
276
 
255
- # Flux 1 partial derivatives
277
+ # Flux 2 partial derivatives
256
278
 
279
+ @flux_2.partial_derivative("pressure_mid")
257
280
  def dflux_2_dpressure_mid(self):
258
281
  """
259
282
  Computes flux_2 partial derivative for pressure_mid.
260
283
  """
261
284
 
262
- return 0.5 / self.resistance_1.current
285
+ return 0.5 / self.resistance_2.current
263
286
 
287
+ @flux_2.partial_derivative("pressure_2")
264
288
  def dflux_2_dpressure_2(self):
265
289
  """
266
290
  Computes flux_2 partial derivative for pressure_2.
@@ -270,6 +294,7 @@ We then have to declare functions to compute fluxes and internal equations parti
270
294
 
271
295
  # Internal equation partial derivatives:
272
296
 
297
+ @residual_pressure_mid.partial_derivative("pressure_mid")
273
298
  def dresidual_pressure_mid_dpressure_mid(self):
274
299
  """
275
300
  Computes internal equation partial derivative for pressure_mid.
@@ -281,6 +306,7 @@ We then have to declare functions to compute fluxes and internal equations parti
281
306
  + 0.5 / self.resistance_2
282
307
  )
283
308
 
309
+ @residual_pressure_mid.partial_derivative("pressure_1")
284
310
  def dresidual_pressure_mid_dpressure_1(self):
285
311
  """
286
312
  Computes internal equation partial derivative for pressure_1.
@@ -289,6 +315,7 @@ We then have to declare functions to compute fluxes and internal equations parti
289
315
  - 0.5 / self.resistance_1
290
316
  )
291
317
 
318
+ @residual_pressure_mid.partial_derivative("pressure_2")
292
319
  def dresidual_pressure_mid_dpressure_2(self):
293
320
  """
294
321
  Computes internal equation partial derivative for pressure_2.
@@ -297,107 +324,6 @@ We then have to declare functions to compute fluxes and internal equations parti
297
324
  - 0.5 / self.resistance_2
298
325
  )
299
326
 
300
- Define the Block Expressions
301
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
302
-
303
- We defined every method to compute our blocks relations along with the needed quantities.
304
- But these methods are not yet available for the assembling process that builds the global system.
305
-
306
- We will now declare **Flux**, **Internal Equations** and **Saved Quantities** :class:`~physioblocks.computing.models.Expression` objects to assemble a residual and gradient matrix.
307
-
308
- This is performed on the **block type** directly, calling the created :class:`~physioblocks.library.blocks.capacitances.RCRBlock` class methods.
309
-
310
- But first, we have to instantiate the :class:`~physioblocks.computing.models.Expression` objects.
311
- They are composed of :
312
-
313
- 1. the **size** of the expression value
314
- 2. the **function** computing the expression value
315
- 3. a dictionary holding the **partial derivatives** for the function matched with the variable name.
316
-
317
- Here are all the expressions needed for our :class:`~physioblocks.computing.models.Block`.
318
-
319
- .. code:: python
320
-
321
- # Define the flux expression going in the input node for rcr block
322
- _rcr_block_flux_1_expr = Expression(
323
- 1, # flux 0 is size 1
324
- RCRBlock.flux_1, # the function to compute flux 0
325
- {
326
- # the partial derivative for pressure 0 for flux 0
327
- "pressure_1": RCRBlock.dflux_1_dpressure_1,
328
- # the partial derivative for pressure mid for flux 0
329
- "pressure_mid": RCRBlock.dflux_1_dpressure_mid,
330
- }
331
- )
332
-
333
- # The next expressions are built similarly:
334
- _rcr_block_flux_2_expr = Expression(
335
- 1,
336
- RCRBlock.flux_2,
337
- {
338
- # the partial derivative for pressure 0 for flux 0
339
- "pressure_2": RCRBlock.dflux_2_dpressure_2,
340
- # the partial derivative for pressure mid for flux 0
341
- "pressure_mid": RCRBlock.dflux_2_dpressure_mid,
342
- }
343
- )
344
-
345
- _rcr_block_residual_expr = Expression(
346
- 1,
347
- RCRBlock.residual_pressure_mid,
348
- {
349
- "pressure_mid": RCRBlock.dresidual_pressure_mid_dpressure_mid,
350
- "pressure_1": RCRBlock.dresidual_pressure_mid_dpressure_1,
351
- "pressure_2": RCRBlock.dresidual_pressure_mid_dpressure_2,
352
- },
353
- )
354
-
355
- # The volume stored do not need partial derivatives
356
- _rcr_block_volume_stored_expr = Expression(1, RCRBlock.volume_stored)
357
-
358
- Now we use the :class:`~physioblocks.library.blocks.capacitances.RCRBlock` class methods to register the expressions.
359
- To declare a flux expression for the block, we need:
360
-
361
- 1. the **index** of the local node sharing the flux.
362
- 2. the **variable local name** in the :class:`~physioblocks.computing.models.Block`.
363
- 3. the expression object
364
-
365
- .. code:: python
366
-
367
- RCRBlock.declares_flux_expression(
368
- 0,
369
- "pressure_1",
370
- _rcr_block_flux_1_expr
371
- )
372
- RCRBlock.declares_flux_expression(
373
- 1,
374
- "pressure_2",
375
- _rcr_block_flux_2_expr
376
- )
377
-
378
-
379
- To declare an internal equation expression for the block, we need:
380
-
381
- 1. the **internal variable local name** in the :class:`~physioblocks.computing.models.Block`
382
- 2. the expression object
383
-
384
- .. code:: python
385
-
386
- RCRBlock.declares_internal_expression(
387
- "pressure_mid",
388
- _rcr_block_residual_expr
389
- )
390
-
391
- Finally, to declare a **Saved Quantity** expression for the block, we need:
392
-
393
- 1. the saved quantity **local name**
394
- 2. the expression object
395
-
396
- .. code:: python
397
-
398
- RCRBlock.declares_saved_quantity_expression(
399
- "volume_stored", _rcr_block_volume_stored_expr
400
- )
401
327
 
402
328
  Now the :class:`~physioblocks.library.blocks.capacitances.RCRBlock` is completely defined and can be used in a net.
403
329
 
@@ -26,7 +26,7 @@
26
26
 
27
27
  """Physioblocks package definition"""
28
28
 
29
- __version__ = "1.0.3"
29
+ __version__ = "1.1.0"
30
30
  __copyright__ = "INRIA"
31
31
  __license__ = "LGPL-3.0-only"
32
32
  __authors__ = [
@@ -32,6 +32,7 @@ functions.
32
32
 
33
33
  from __future__ import annotations
34
34
 
35
+ import functools
35
36
  from collections.abc import Callable
36
37
  from dataclasses import dataclass, field
37
38
  from inspect import get_annotations
@@ -46,7 +47,7 @@ SystemFunction: TypeAlias = Callable[..., np.float64 | NDArray[np.float64]]
46
47
  """Type alias for functions composing the system"""
47
48
 
48
49
 
49
- @dataclass(frozen=True)
50
+ @dataclass
50
51
  class Expression:
51
52
  """Expression(size:int, expr_func: SystemFunction, expr_gradients: Mapping[str, SystemFunction] = {})
52
53
  Store function computing numerical values for terms in the models with the function
@@ -102,6 +103,223 @@ class Expression:
102
103
  )
103
104
 
104
105
 
106
+ class ExpressionDecorator:
107
+ """
108
+ Base class for expression decorators.
109
+
110
+ This is a helper that defines expressions decorating methods in a model or block
111
+ class.
112
+ """
113
+
114
+ expression: Expression
115
+ """The expression resulting from decorators declarations"""
116
+
117
+ def __init__(
118
+ self,
119
+ wrapped_function: Callable[..., Any],
120
+ ):
121
+ """
122
+ :param wrapped_function: The decorated expression function
123
+ :type wrapped_function: Callable
124
+ """
125
+ self.expression = Expression(0, wrapped_function)
126
+ self._terms: list[tuple[str, int, int]] = []
127
+ functools.update_wrapper(self, wrapped_function)
128
+
129
+ def register_term(
130
+ self,
131
+ term_name: str,
132
+ term_size: int,
133
+ term_index: int,
134
+ ) -> None:
135
+ """
136
+ Register a new term to the expression decorator
137
+
138
+ :param term_name: the term local name.
139
+ :type term_name: str
140
+
141
+ :param term_size: The size of the term
142
+ :type term_size: int
143
+
144
+ :param term_index: The start index of the term in the expression
145
+ :type term_index: int
146
+ """
147
+ self.expression.size += term_size
148
+ self._terms.append((term_name, term_size, term_index))
149
+
150
+ @property
151
+ def terms(self) -> list[tuple[str, int, int]]:
152
+ """
153
+ Get the terms described by the expression.
154
+
155
+ :return: list of terms description
156
+ :rtype: list[[tuple[str, int, int]]]
157
+ """
158
+ return self._terms.copy()
159
+
160
+ def __call__(self, *args: Any, **kwargs: Any) -> Any:
161
+ return self.expression.expr_func(*args, **kwargs)
162
+
163
+ def partial_derivative(
164
+ self, variable_name: str
165
+ ) -> Callable[..., Callable[..., Any]]:
166
+ """
167
+ Declares a flux partial derivative.
168
+
169
+ :param variable_name: the variable local name.
170
+ :type variable_name: str
171
+ """
172
+
173
+ def _register(wrapped: Callable[..., Any]) -> Callable[..., Any]:
174
+ self.expression.expr_gradients[variable_name] = wrapped
175
+ return wrapped
176
+
177
+ return _register
178
+
179
+
180
+ def _check_expression_decorator_type(
181
+ wrapped_function: Any, new_decorator_type: type[ExpressionDecorator]
182
+ ) -> None:
183
+ if (
184
+ isinstance(wrapped_function, ExpressionDecorator) is True
185
+ and isinstance(wrapped_function, new_decorator_type) is False
186
+ ):
187
+ raise ValueError(
188
+ str.format(
189
+ "Can not decorate a function of an other type. "
190
+ "Current type is {0}, new type is {1}.",
191
+ type(wrapped_function),
192
+ new_decorator_type,
193
+ )
194
+ )
195
+
196
+
197
+ class InternalEquationDecorator(ExpressionDecorator):
198
+ """
199
+ Define a decorator that identifies internal equation expressions.
200
+ """
201
+
202
+ pass
203
+
204
+
205
+ def declares_internal_equation(
206
+ variable_name: str, size: int = 1, starting_index: int = 0
207
+ ) -> Callable[..., InternalEquationDecorator]:
208
+ """
209
+ Declares a internal equation expression.
210
+
211
+ Once the internal equation function is declared, partial derivatives can be added
212
+ using the function name and the local variable name for the partial derivative.
213
+
214
+ :param variable_name: the variable name on which the expression provides a dynamic.
215
+ :type variable_name: str
216
+
217
+ :param size: the size of the equation. Default is 1
218
+ :type size: int
219
+
220
+ :param starting_index: the starting index of the equation line matching the
221
+ variable. Default is 0
222
+ :type starting_index: int
223
+
224
+ :raises ValueError: Raises a ValueError if the function is already decorated with
225
+ an expression decorator of an other type.
226
+
227
+ Example
228
+ ^^^^^^^
229
+
230
+ .. code:: python
231
+
232
+ @dataclass
233
+ class SimpleModel(ModelComponent):
234
+
235
+ x: Quantity
236
+ a: Quantity
237
+
238
+ @declares_internal_equation("x")
239
+ def residual(self):
240
+ return x.new**2 - a.current
241
+
242
+ @flux_1.partial_derivative("x")
243
+ def dresidual_dx(self):
244
+ return 2.0 * x.new
245
+ """
246
+
247
+ def _create_internal_equation_decorator(
248
+ wrapped: Callable[..., Any],
249
+ ) -> InternalEquationDecorator:
250
+ _check_expression_decorator_type(wrapped, InternalEquationDecorator)
251
+
252
+ decorated = (
253
+ wrapped
254
+ if isinstance(wrapped, InternalEquationDecorator)
255
+ else InternalEquationDecorator(wrapped)
256
+ )
257
+ decorated.register_term(variable_name, size, starting_index)
258
+ return decorated
259
+
260
+ return _create_internal_equation_decorator
261
+
262
+
263
+ class SavedQuantityDecorator(ExpressionDecorator):
264
+ """
265
+ Define a decorator that identifies saved quantities expressions.
266
+ """
267
+
268
+ pass
269
+
270
+
271
+ def declares_saved_quantity(
272
+ quantity_name: str, size: int = 1, starting_index: int = 0
273
+ ) -> Callable[..., SavedQuantityDecorator]:
274
+ """
275
+ Declares a saved quantity expression.
276
+
277
+ :param quantity_name: the local quantity name.
278
+ :type quantity_name: str
279
+
280
+ :param size: the size of the expression. Default is 1
281
+ :type size: int
282
+
283
+ :param starting_index: the starting index of the expression in the function.
284
+ Default is 0
285
+ :type starting_index: int
286
+
287
+ :raises ValueError: Raises a ValueError if the function is already decorated with
288
+ an expression decorator of an other type.
289
+
290
+ Example
291
+ ^^^^^^^
292
+
293
+ .. code:: python
294
+
295
+ @dataclass
296
+ class SimpleModel(ModelComponent):
297
+
298
+ a: Quantity
299
+ b: Quantity
300
+
301
+ @declares_saved_quantity("a + b")
302
+ def sum(self):
303
+ return a.current + b.current
304
+ """
305
+
306
+ def _create_saved_quantity_decorator(
307
+ wrapped: Callable[..., Any],
308
+ ) -> SavedQuantityDecorator:
309
+ _check_expression_decorator_type(wrapped, SavedQuantityDecorator)
310
+
311
+ decorator = (
312
+ wrapped
313
+ if isinstance(wrapped, SavedQuantityDecorator)
314
+ else SavedQuantityDecorator(wrapped)
315
+ )
316
+ decorator.register_term(quantity_name, size, starting_index)
317
+
318
+ return decorator
319
+
320
+ return _create_saved_quantity_decorator
321
+
322
+
105
323
  @dataclass(frozen=True)
106
324
  class TermDefinition:
107
325
  """Describe Terms defined in an :class:`~physioblocks.computing.models.Expression`.
@@ -303,6 +521,23 @@ class ModelComponentMetaClass(type):
303
521
  cls.__INTERNAL_EXPRESSION_KEY: [],
304
522
  cls.__SAVED_QUANTITIES_EXPRESSION_KEY: [],
305
523
  }
524
+ for attr in cls.__dict__.values():
525
+ if isinstance(attr, InternalEquationDecorator):
526
+ for term_name, term_size, term_index in attr.terms:
527
+ cls.declares_internal_expression(
528
+ term_name,
529
+ attr.expression,
530
+ term_size,
531
+ term_index,
532
+ )
533
+ elif isinstance(attr, SavedQuantityDecorator):
534
+ for term_name, term_size, term_index in attr.terms:
535
+ cls.declares_saved_quantity_expression(
536
+ term_name,
537
+ attr.expression,
538
+ term_size,
539
+ term_index,
540
+ )
306
541
 
307
542
  @staticmethod
308
543
  def __is_quantity_type(type_to_test: Any) -> bool:
@@ -481,6 +716,7 @@ class ModelComponentMetaClass(type):
481
716
 
482
717
  # Add the term definition to the expression definition
483
718
  expression_def.terms.append(TermDefinition(term_id, size, index))
719
+ expression_def.terms.sort(key=lambda term: term.index)
484
720
 
485
721
  def declares_internal_expression(
486
722
  cls,
@@ -690,6 +926,78 @@ class ModelComponent(metaclass=ModelComponentMetaClass):
690
926
  """Override this method to define specific for model initialization."""
691
927
 
692
928
 
929
+ class FluxDecorator(ExpressionDecorator):
930
+ """
931
+ Define a decorator that identifies flux functions
932
+ """
933
+
934
+ pass
935
+
936
+
937
+ def declares_flux(
938
+ index: int, dof_name: str, size: int = 1
939
+ ) -> Callable[..., FluxDecorator]:
940
+ """
941
+ Declares a flux function.
942
+
943
+ Once the flux expression is declared, partial derivatives can be added using the
944
+ flux function name and the local variable name for the partial derivative.
945
+
946
+ :param index: the index of the flux in the block.
947
+ :type index: int
948
+
949
+ :param dof_name: the matching dof local name
950
+ :type dof_name: str
951
+
952
+ :param size: the size of the flux returned by the function
953
+ :type size: int
954
+
955
+ :raises ValueError: Raises a ValueError if the function is already decorated with
956
+ an expression decorator of an other type.
957
+
958
+
959
+ Example
960
+ ^^^^^^^
961
+
962
+ .. code:: python
963
+
964
+ @dataclass
965
+ class SimpleBlock(Block):
966
+
967
+ q_1: Quantity
968
+
969
+ # declares a flux shared at local node 1, where the associated dof has the
970
+ # local name "potential_1"
971
+ @declares_flux(1, "potential_1")
972
+ def flux_1(self):
973
+ return q_1.new
974
+
975
+ # associate the following function as the partial derivative of "flux_1" for
976
+ # variable "q_1"
977
+ @flux_1.partial_derivative("q_1")
978
+ def dflux_1_dq_1(self):
979
+ return 1.0
980
+
981
+ """
982
+
983
+ def _create_flux_decorator(wrapped: Callable[..., Any]) -> FluxDecorator:
984
+ if isinstance(wrapped, ExpressionDecorator) is True:
985
+ raise ValueError(
986
+ str.format(
987
+ "Function already declares an expression, it can not be a flux."
988
+ )
989
+ )
990
+
991
+ decorator = (
992
+ wrapped if isinstance(wrapped, FluxDecorator) else FluxDecorator(wrapped)
993
+ )
994
+ decorator.register_term(dof_name, size, index)
995
+
996
+ return decorator
997
+
998
+ return _create_flux_decorator
999
+
1000
+
693
1001
  class BlockMetaClass(ModelComponentMetaClass):
694
1002
  """Meta-class for :class:`~physioblocks.computing.models.Block`.
695
1003
 
@@ -711,6 +1019,10 @@ class BlockMetaClass(ModelComponentMetaClass):
711
1019
  def __init__(cls, *args: Any, **kwargs: Any) -> None:
712
1020
  super().__init__(*args, **kwargs)
713
1021
  cls._fluxes = {}
1022
+ for attr in cls.__dict__.values():
1023
+ if isinstance(attr, FluxDecorator):
1024
+ for term_name, _term_size, term_index in attr.terms:
1025
+ cls.declares_flux_expression(term_index, term_name, attr.expression)
714
1026
 
715
1027
  def declares_flux_expression(
716
1028
  cls, node_index: int, variable_id: str, expr: Expression