scikit-complexity 0.2.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.
Files changed (1748) hide show
  1. scikit_complexity-0.2.0.dist-info/METADATA +317 -0
  2. scikit_complexity-0.2.0.dist-info/RECORD +1748 -0
  3. scikit_complexity-0.2.0.dist-info/WHEEL +4 -0
  4. scikit_complexity-0.2.0.dist-info/entry_points.txt +4 -0
  5. scikit_complexity-0.2.0.dist-info/licenses/LICENSE +21 -0
  6. skcomplex/__init__.py +1 -0
  7. skcomplex/analysis/__init__.py +101 -0
  8. skcomplex/analysis/_alignment.py +263 -0
  9. skcomplex/analysis/_automata.py +658 -0
  10. skcomplex/analysis/_base.py +841 -0
  11. skcomplex/analysis/_clusters.py +298 -0
  12. skcomplex/analysis/_coarse_grain.py +183 -0
  13. skcomplex/analysis/_collapse.py +318 -0
  14. skcomplex/analysis/_complexity.py +129 -0
  15. skcomplex/analysis/_computational_mechanics.py +220 -0
  16. skcomplex/analysis/_correlation.py +364 -0
  17. skcomplex/analysis/_defects.py +111 -0
  18. skcomplex/analysis/_discovery.py +101 -0
  19. skcomplex/analysis/_displacement.py +135 -0
  20. skcomplex/analysis/_distribution.py +327 -0
  21. skcomplex/analysis/_domains.py +220 -0
  22. skcomplex/analysis/_embedding.py +235 -0
  23. skcomplex/analysis/_emergence.py +503 -0
  24. skcomplex/analysis/_entropy.py +425 -0
  25. skcomplex/analysis/_ergodicity.py +228 -0
  26. skcomplex/analysis/_events.py +301 -0
  27. skcomplex/analysis/_fit.py +368 -0
  28. skcomplex/analysis/_groups.py +205 -0
  29. skcomplex/analysis/_information.py +488 -0
  30. skcomplex/analysis/_invariants.py +409 -0
  31. skcomplex/analysis/_irreversibility.py +421 -0
  32. skcomplex/analysis/_kramers_moyal.py +104 -0
  33. skcomplex/analysis/_large_deviations.py +378 -0
  34. skcomplex/analysis/_linearization.py +231 -0
  35. skcomplex/analysis/_local_information.py +166 -0
  36. skcomplex/analysis/_loops.py +394 -0
  37. skcomplex/analysis/_lyapunov.py +342 -0
  38. skcomplex/analysis/_markov.py +303 -0
  39. skcomplex/analysis/_mode_decomposition.py +209 -0
  40. skcomplex/analysis/_motifs.py +239 -0
  41. skcomplex/analysis/_neighbors.py +303 -0
  42. skcomplex/analysis/_networks.py +286 -0
  43. skcomplex/analysis/_operator.py +312 -0
  44. skcomplex/analysis/_partial_information.py +118 -0
  45. skcomplex/analysis/_passage.py +244 -0
  46. skcomplex/analysis/_recurrence.py +202 -0
  47. skcomplex/analysis/_reservoirs.py +387 -0
  48. skcomplex/analysis/_rolling.py +168 -0
  49. skcomplex/analysis/_scaling.py +370 -0
  50. skcomplex/analysis/_sections.py +225 -0
  51. skcomplex/analysis/_signatures.py +250 -0
  52. skcomplex/analysis/_sparse_identification.py +398 -0
  53. skcomplex/analysis/_spectrum.py +164 -0
  54. skcomplex/analysis/_stability.py +547 -0
  55. skcomplex/analysis/_surrogates.py +127 -0
  56. skcomplex/analysis/_symbolic.py +639 -0
  57. skcomplex/analysis/types.py +43 -0
  58. skcomplex/base.py +159 -0
  59. skcomplex/core/__init__.py +1 -0
  60. skcomplex/core/base.py +150 -0
  61. skcomplex/core/elements/__init__.py +21 -0
  62. skcomplex/core/elements/_base.py +84 -0
  63. skcomplex/core/elements/_compartment.py +52 -0
  64. skcomplex/core/elements/_density.py +52 -0
  65. skcomplex/core/elements/_element.py +80 -0
  66. skcomplex/core/elements/_field.py +192 -0
  67. skcomplex/core/elements/_group.py +241 -0
  68. skcomplex/core/elements/_lattice.py +115 -0
  69. skcomplex/core/elements/_point.py +66 -0
  70. skcomplex/core/interactions/__init__.py +89 -0
  71. skcomplex/core/interactions/_advection.py +134 -0
  72. skcomplex/core/interactions/_base.py +361 -0
  73. skcomplex/core/interactions/_cascade.py +195 -0
  74. skcomplex/core/interactions/_choice.py +320 -0
  75. skcomplex/core/interactions/_conservation.py +164 -0
  76. skcomplex/core/interactions/_coupling.py +741 -0
  77. skcomplex/core/interactions/_crossing.py +136 -0
  78. skcomplex/core/interactions/_diffusion.py +99 -0
  79. skcomplex/core/interactions/_encounter.py +201 -0
  80. skcomplex/core/interactions/_euler_lagrange.py +183 -0
  81. skcomplex/core/interactions/_evolution.py +520 -0
  82. skcomplex/core/interactions/_feedback.py +79 -0
  83. skcomplex/core/interactions/_gradient.py +293 -0
  84. skcomplex/core/interactions/_grouping.py +399 -0
  85. skcomplex/core/interactions/_hamiltonian.py +191 -0
  86. skcomplex/core/interactions/_hyperedge.py +96 -0
  87. skcomplex/core/interactions/_imitation.py +357 -0
  88. skcomplex/core/interactions/_impulse.py +133 -0
  89. skcomplex/core/interactions/_interaction.py +58 -0
  90. skcomplex/core/interactions/_jump.py +201 -0
  91. skcomplex/core/interactions/_life_cycle.py +424 -0
  92. skcomplex/core/interactions/_local_rule.py +134 -0
  93. skcomplex/core/interactions/_map.py +239 -0
  94. skcomplex/core/interactions/_matching.py +701 -0
  95. skcomplex/core/interactions/_movement.py +377 -0
  96. skcomplex/core/interactions/_neighbor.py +88 -0
  97. skcomplex/core/interactions/_optimization.py +206 -0
  98. skcomplex/core/interactions/_pair.py +82 -0
  99. skcomplex/core/interactions/_pair_coupling.py +169 -0
  100. skcomplex/core/interactions/_rate.py +240 -0
  101. skcomplex/core/interactions/_reaction.py +466 -0
  102. skcomplex/core/interactions/_reinforcement.py +226 -0
  103. skcomplex/core/interactions/_relaxation.py +103 -0
  104. skcomplex/core/interactions/_sampling.py +177 -0
  105. skcomplex/core/interactions/_satisfiability.py +145 -0
  106. skcomplex/core/interactions/_sign_adjustment.py +222 -0
  107. skcomplex/core/interactions/_topology.py +215 -0
  108. skcomplex/core/interactions/_training.py +184 -0
  109. skcomplex/core/interactions/_transfer.py +669 -0
  110. skcomplex/core/interactions/_transition.py +427 -0
  111. skcomplex/core/laws/__init__.py +60 -0
  112. skcomplex/core/laws/_base.py +194 -0
  113. skcomplex/core/laws/_bilinear.py +91 -0
  114. skcomplex/core/laws/_boundary.py +59 -0
  115. skcomplex/core/laws/_cascade.py +79 -0
  116. skcomplex/core/laws/_crossing.py +87 -0
  117. skcomplex/core/laws/_dissipator.py +79 -0
  118. skcomplex/core/laws/_drive.py +56 -0
  119. skcomplex/core/laws/_emission.py +81 -0
  120. skcomplex/core/laws/_encounter.py +96 -0
  121. skcomplex/core/laws/_equation.py +105 -0
  122. skcomplex/core/laws/_extremal.py +94 -0
  123. skcomplex/core/laws/_flux.py +108 -0
  124. skcomplex/core/laws/_fractional_noise.py +65 -0
  125. skcomplex/core/laws/_generator.py +66 -0
  126. skcomplex/core/laws/_gradient_step.py +89 -0
  127. skcomplex/core/laws/_jump.py +137 -0
  128. skcomplex/core/laws/_local_rule.py +92 -0
  129. skcomplex/core/laws/_match.py +321 -0
  130. skcomplex/core/laws/_noise.py +125 -0
  131. skcomplex/core/laws/_rate.py +82 -0
  132. skcomplex/core/laws/_rule.py +82 -0
  133. skcomplex/core/laws/_sample.py +65 -0
  134. skcomplex/core/laws/_transfer.py +165 -0
  135. skcomplex/core/laws/_transition.py +77 -0
  136. skcomplex/core/laws/_update.py +121 -0
  137. skcomplex/core/laws/utils/__init__.py +142 -0
  138. skcomplex/core/laws/utils/_agents.py +127 -0
  139. skcomplex/core/laws/utils/_components.py +63 -0
  140. skcomplex/core/laws/utils/_conditions.py +198 -0
  141. skcomplex/core/laws/utils/_contractions.py +74 -0
  142. skcomplex/core/laws/utils/_delays.py +170 -0
  143. skcomplex/core/laws/utils/_history.py +167 -0
  144. skcomplex/core/laws/utils/_local_operators.py +68 -0
  145. skcomplex/core/laws/utils/_lookups.py +40 -0
  146. skcomplex/core/laws/utils/_moments.py +122 -0
  147. skcomplex/core/laws/utils/_operators.py +237 -0
  148. skcomplex/core/laws/utils/_phase.py +126 -0
  149. skcomplex/core/laws/utils/_pointwise.py +160 -0
  150. skcomplex/core/laws/utils/_reductions.py +942 -0
  151. skcomplex/core/laws/utils/_signals.py +214 -0
  152. skcomplex/core/laws/utils/_tables.py +4 -0
  153. skcomplex/core/laws/utils/_tensors.py +235 -0
  154. skcomplex/core/spaces/__init__.py +52 -0
  155. skcomplex/core/spaces/_adjacency.py +34 -0
  156. skcomplex/core/spaces/_base.py +218 -0
  157. skcomplex/core/spaces/_box.py +41 -0
  158. skcomplex/core/spaces/_cayley.py +352 -0
  159. skcomplex/core/spaces/_cone.py +65 -0
  160. skcomplex/core/spaces/_continuous.py +93 -0
  161. skcomplex/core/spaces/_continuous_time.py +27 -0
  162. skcomplex/core/spaces/_discrete_time.py +53 -0
  163. skcomplex/core/spaces/_generator.py +51 -0
  164. skcomplex/core/spaces/_lattice.py +194 -0
  165. skcomplex/core/spaces/_lattice_neighborhood.py +50 -0
  166. skcomplex/core/spaces/_memory.py +45 -0
  167. skcomplex/core/spaces/_mesh.py +71 -0
  168. skcomplex/core/spaces/_moore.py +49 -0
  169. skcomplex/core/spaces/_nearest.py +41 -0
  170. skcomplex/core/spaces/_network.py +256 -0
  171. skcomplex/core/spaces/_phase.py +136 -0
  172. skcomplex/core/spaces/_radius.py +40 -0
  173. skcomplex/core/spaces/_static_time.py +34 -0
  174. skcomplex/core/spaces/_triangular.py +37 -0
  175. skcomplex/core/spaces/_von_neumann.py +51 -0
  176. skcomplex/core/specs/__init__.py +25 -0
  177. skcomplex/core/specs/_census_record_spec.py +72 -0
  178. skcomplex/core/specs/_census_spec.py +40 -0
  179. skcomplex/core/specs/_compiled_agents_spec.py +62 -0
  180. skcomplex/core/specs/_compiled_element_spec.py +59 -0
  181. skcomplex/core/specs/_compiled_interaction_spec.py +33 -0
  182. skcomplex/core/specs/_lattice_context_spec.py +40 -0
  183. skcomplex/core/specs/_lattice_state_spec.py +49 -0
  184. skcomplex/core/specs/_node_spec.py +64 -0
  185. skcomplex/core/specs/_operator_view_spec.py +135 -0
  186. skcomplex/core/specs/_scenario_spec.py +45 -0
  187. skcomplex/core/specs/_subsystem_spec.py +24 -0
  188. skcomplex/core/system.py +140 -0
  189. skcomplex/core/types.py +249 -0
  190. skcomplex/engine/__init__.py +5 -0
  191. skcomplex/engine/_utils.py +278 -0
  192. skcomplex/engine/backends/__init__.py +13 -0
  193. skcomplex/engine/backends/_base.py +329 -0
  194. skcomplex/engine/backends/_jax.py +285 -0
  195. skcomplex/engine/backends/_numba.py +601 -0
  196. skcomplex/engine/backends/_numba_components.py +67 -0
  197. skcomplex/engine/backends/_numba_loops.py +163 -0
  198. skcomplex/engine/backends/_numba_neighbours.py +435 -0
  199. skcomplex/engine/backends/_numba_printer.py +1023 -0
  200. skcomplex/engine/backends/_numba_stencils.py +66 -0
  201. skcomplex/engine/backends/_numpy.py +215 -0
  202. skcomplex/engine/compile/__init__.py +27 -0
  203. skcomplex/engine/compile/_base.py +582 -0
  204. skcomplex/engine/compile/_bound_renewal_spec.py +47 -0
  205. skcomplex/engine/compile/_compilation.py +351 -0
  206. skcomplex/engine/compile/_compile.py +100 -0
  207. skcomplex/engine/compile/_complex.py +216 -0
  208. skcomplex/engine/compile/_draw_lowering.py +373 -0
  209. skcomplex/engine/compile/_field_lowering.py +1668 -0
  210. skcomplex/engine/compile/_flows.py +691 -0
  211. skcomplex/engine/compile/_forms.py +48 -0
  212. skcomplex/engine/compile/_laws.py +42 -0
  213. skcomplex/engine/compile/_learning_compiler.py +481 -0
  214. skcomplex/engine/compile/_member_reductions.py +206 -0
  215. skcomplex/engine/compile/_members.py +244 -0
  216. skcomplex/engine/compile/_observables.py +940 -0
  217. skcomplex/engine/compile/_observer.py +185 -0
  218. skcomplex/engine/compile/_pass_compiler.py +1534 -0
  219. skcomplex/engine/compile/_probe.py +78 -0
  220. skcomplex/engine/compile/_renewal_law.py +70 -0
  221. skcomplex/engine/compile/passes/__init__.py +34 -0
  222. skcomplex/engine/compile/passes/_agents.py +111 -0
  223. skcomplex/engine/compile/passes/_agents_problem.py +143 -0
  224. skcomplex/engine/compile/passes/_census.py +808 -0
  225. skcomplex/engine/compile/passes/_check_fractional_noise.py +107 -0
  226. skcomplex/engine/compile/passes/_collect.py +31 -0
  227. skcomplex/engine/compile/passes/_compile_encounters.py +301 -0
  228. skcomplex/engine/compile/passes/_complex.py +198 -0
  229. skcomplex/engine/compile/passes/_conserved_noise.py +224 -0
  230. skcomplex/engine/compile/passes/_core.py +116 -0
  231. skcomplex/engine/compile/passes/_declare_renewals.py +84 -0
  232. skcomplex/engine/compile/passes/_draws.py +29 -0
  233. skcomplex/engine/compile/passes/_encounter_functions.py +60 -0
  234. skcomplex/engine/compile/passes/_encounter_jacobian.py +25 -0
  235. skcomplex/engine/compile/passes/_encounter_problem.py +32 -0
  236. skcomplex/engine/compile/passes/_events.py +204 -0
  237. skcomplex/engine/compile/passes/_expand_flows.py +32 -0
  238. skcomplex/engine/compile/passes/_field_functions.py +647 -0
  239. skcomplex/engine/compile/passes/_field_jacobian.py +38 -0
  240. skcomplex/engine/compile/passes/_field_problem.py +106 -0
  241. skcomplex/engine/compile/passes/_flatten.py +339 -0
  242. skcomplex/engine/compile/passes/_flows_problem.py +29 -0
  243. skcomplex/engine/compile/passes/_form.py +82 -0
  244. skcomplex/engine/compile/passes/_fractional_form.py +172 -0
  245. skcomplex/engine/compile/passes/_fractional_problem.py +91 -0
  246. skcomplex/engine/compile/passes/_functions.py +485 -0
  247. skcomplex/engine/compile/passes/_hilbert_space_error.py +10 -0
  248. skcomplex/engine/compile/passes/_hyperedges.py +598 -0
  249. skcomplex/engine/compile/passes/_jacobian.py +38 -0
  250. skcomplex/engine/compile/passes/_kernels.py +407 -0
  251. skcomplex/engine/compile/passes/_lattices.py +818 -0
  252. skcomplex/engine/compile/passes/_layout.py +667 -0
  253. skcomplex/engine/compile/passes/_lower_fields.py +225 -0
  254. skcomplex/engine/compile/passes/_lower_flows.py +28 -0
  255. skcomplex/engine/compile/passes/_markov.py +329 -0
  256. skcomplex/engine/compile/passes/_mask_requests.py +121 -0
  257. skcomplex/engine/compile/passes/_members.py +30 -0
  258. skcomplex/engine/compile/passes/_noise.py +196 -0
  259. skcomplex/engine/compile/passes/_operator_compiler.py +843 -0
  260. skcomplex/engine/compile/passes/_orders.py +409 -0
  261. skcomplex/engine/compile/passes/_owners.py +90 -0
  262. skcomplex/engine/compile/passes/_particles.py +69 -0
  263. skcomplex/engine/compile/passes/_plan.py +130 -0
  264. skcomplex/engine/compile/passes/_problem.py +802 -0
  265. skcomplex/engine/compile/passes/_reduction_lowering.py +1193 -0
  266. skcomplex/engine/compile/passes/_reductions.py +84 -0
  267. skcomplex/engine/compile/passes/_renewal_problem.py +357 -0
  268. skcomplex/engine/compile/passes/_request_jumps.py +51 -0
  269. skcomplex/engine/compile/passes/_residences.py +140 -0
  270. skcomplex/engine/compile/passes/_rows.py +162 -0
  271. skcomplex/engine/compile/passes/_set_renewals_apart.py +29 -0
  272. skcomplex/engine/compile/passes/_set_rules_apart.py +28 -0
  273. skcomplex/engine/compile/passes/_specs.py +1317 -0
  274. skcomplex/engine/compile/passes/_split_requests.py +44 -0
  275. skcomplex/engine/compile/passes/_topology_functions.py +265 -0
  276. skcomplex/engine/compile/passes/_topology_problem.py +27 -0
  277. skcomplex/engine/compile/passes/_towards.py +66 -0
  278. skcomplex/engine/compile/passes/_unpack_matches.py +29 -0
  279. skcomplex/engine/compile/passes/_unpack_renewals.py +41 -0
  280. skcomplex/engine/problems/__init__.py +61 -0
  281. skcomplex/engine/problems/_base.py +150 -0
  282. skcomplex/engine/problems/_base_problem_spec.py +153 -0
  283. skcomplex/engine/problems/_block_spec.py +48 -0
  284. skcomplex/engine/problems/_born_spec.py +24 -0
  285. skcomplex/engine/problems/_cascade_kernel.py +134 -0
  286. skcomplex/engine/problems/_collision_kernel.py +147 -0
  287. skcomplex/engine/problems/_compiled_delay_spec.py +21 -0
  288. skcomplex/engine/problems/_compiled_request_spec.py +46 -0
  289. skcomplex/engine/problems/_control_problem_spec.py +90 -0
  290. skcomplex/engine/problems/_declarations_spec.py +126 -0
  291. skcomplex/engine/problems/_delayed_state_spec.py +50 -0
  292. skcomplex/engine/problems/_diffusive_limit_spec.py +50 -0
  293. skcomplex/engine/problems/_draw_kernel.py +128 -0
  294. skcomplex/engine/problems/_drive_kernel.py +65 -0
  295. skcomplex/engine/problems/_dynamics_spec.py +28 -0
  296. skcomplex/engine/problems/_edge_row_search.py +78 -0
  297. skcomplex/engine/problems/_edge_search.py +64 -0
  298. skcomplex/engine/problems/_encounter_kernel.py +200 -0
  299. skcomplex/engine/problems/_event_kernel.py +70 -0
  300. skcomplex/engine/problems/_expression_printer.py +410 -0
  301. skcomplex/engine/problems/_extremal_kernel.py +125 -0
  302. skcomplex/engine/problems/_field_operator_kernel.py +105 -0
  303. skcomplex/engine/problems/_finite_volume_kernel.py +423 -0
  304. skcomplex/engine/problems/_flow_term_spec.py +45 -0
  305. skcomplex/engine/problems/_frame_spec.py +105 -0
  306. skcomplex/engine/problems/_jacobian_kernel.py +575 -0
  307. skcomplex/engine/problems/_kernel_spec.py +130 -0
  308. skcomplex/engine/problems/_kinetic_problem_spec.py +23 -0
  309. skcomplex/engine/problems/_law_kernel.py +604 -0
  310. skcomplex/engine/problems/_learning_problem_spec.py +67 -0
  311. skcomplex/engine/problems/_linear_term_spec.py +50 -0
  312. skcomplex/engine/problems/_loop_term_spec.py +44 -0
  313. skcomplex/engine/problems/_lowered_kernels_spec.py +59 -0
  314. skcomplex/engine/problems/_markov_kernel.py +68 -0
  315. skcomplex/engine/problems/_metric_search.py +155 -0
  316. skcomplex/engine/problems/_monte_carlo_kernel.py +213 -0
  317. skcomplex/engine/problems/_neighborhood_kernel.py +594 -0
  318. skcomplex/engine/problems/_noise_term_spec.py +26 -0
  319. skcomplex/engine/problems/_observed_spec.py +22 -0
  320. skcomplex/engine/problems/_operator_kernel.py +102 -0
  321. skcomplex/engine/problems/_operator_lowering.py +323 -0
  322. skcomplex/engine/problems/_operator_problem_spec.py +138 -0
  323. skcomplex/engine/problems/_output_spec.py +78 -0
  324. skcomplex/engine/problems/_pair_search.py +86 -0
  325. skcomplex/engine/problems/_partials_spec.py +27 -0
  326. skcomplex/engine/problems/_partition_spec.py +39 -0
  327. skcomplex/engine/problems/_printed_spec.py +24 -0
  328. skcomplex/engine/problems/_problem_functions_spec.py +102 -0
  329. skcomplex/engine/problems/_problem_spec.py +365 -0
  330. skcomplex/engine/problems/_random_stream.py +49 -0
  331. skcomplex/engine/problems/_record_spec.py +22 -0
  332. skcomplex/engine/problems/_recorded_spec.py +21 -0
  333. skcomplex/engine/problems/_reduction_kernel.py +254 -0
  334. skcomplex/engine/problems/_reduction_schedule_spec.py +97 -0
  335. skcomplex/engine/problems/_reference_spec.py +114 -0
  336. skcomplex/engine/problems/_relation_spec.py +29 -0
  337. skcomplex/engine/problems/_renewal_kernel.py +250 -0
  338. skcomplex/engine/problems/_request_spec.py +27 -0
  339. skcomplex/engine/problems/_rule_kernel.py +227 -0
  340. skcomplex/engine/problems/_set_symbol_spec.py +28 -0
  341. skcomplex/engine/problems/_source_loader.py +113 -0
  342. skcomplex/engine/problems/_static_search.py +42 -0
  343. skcomplex/engine/problems/_steps.py +39 -0
  344. skcomplex/engine/problems/_sweep_spec.py +26 -0
  345. skcomplex/engine/problems/_symmetry_spec.py +29 -0
  346. skcomplex/engine/problems/_too_dense.py +8 -0
  347. skcomplex/engine/problems/_topology_kernel.py +589 -0
  348. skcomplex/engine/problems/_transfer_network.py +4 -0
  349. skcomplex/engine/problems/_transfer_network_spec.py +50 -0
  350. skcomplex/engine/problems/_transfer_state_spec.py +68 -0
  351. skcomplex/engine/runtime/__init__.py +22 -0
  352. skcomplex/engine/runtime/_as_fast_as_possible.py +17 -0
  353. skcomplex/engine/runtime/_base.py +137 -0
  354. skcomplex/engine/runtime/_conservation.py +125 -0
  355. skcomplex/engine/runtime/_invariants.py +100 -0
  356. skcomplex/engine/runtime/_real_time.py +55 -0
  357. skcomplex/engine/runtime/_recorder.py +84 -0
  358. skcomplex/engine/runtime/_simulations.py +665 -0
  359. skcomplex/engine/runtime/_trajectories.py +314 -0
  360. skcomplex/engine/solvers/__init__.py +95 -0
  361. skcomplex/engine/solvers/_base.py +372 -0
  362. skcomplex/engine/solvers/_caputo.py +194 -0
  363. skcomplex/engine/solvers/_collocation.py +334 -0
  364. skcomplex/engine/solvers/_convolution.py +155 -0
  365. skcomplex/engine/solvers/_cosimulation.py +400 -0
  366. skcomplex/engine/solvers/_crank_nicolson.py +32 -0
  367. skcomplex/engine/solvers/_defaults.py +34 -0
  368. skcomplex/engine/solvers/_etdrk4.py +86 -0
  369. skcomplex/engine/solvers/_euler_maruyama.py +161 -0
  370. skcomplex/engine/solvers/_event_locator.py +249 -0
  371. skcomplex/engine/solvers/_external.py +94 -0
  372. skcomplex/engine/solvers/_fractional_abm.py +126 -0
  373. skcomplex/engine/solvers/_fractional_euler_maruyama.py +322 -0
  374. skcomplex/engine/solvers/_gillespie.py +135 -0
  375. skcomplex/engine/solvers/_gradient_descent.py +353 -0
  376. skcomplex/engine/solvers/_grunwald_letnikov.py +83 -0
  377. skcomplex/engine/solvers/_heun.py +89 -0
  378. skcomplex/engine/solvers/_history.py +184 -0
  379. skcomplex/engine/solvers/_horizon_error.py +10 -0
  380. skcomplex/engine/solvers/_imex2.py +40 -0
  381. skcomplex/engine/solvers/_imex_euler.py +35 -0
  382. skcomplex/engine/solvers/_jump_trajectories.py +98 -0
  383. skcomplex/engine/solvers/_kinetics.py +242 -0
  384. skcomplex/engine/solvers/_l1.py +91 -0
  385. skcomplex/engine/solvers/_lammps.py +745 -0
  386. skcomplex/engine/solvers/_lammps_fix_spec.py +41 -0
  387. skcomplex/engine/solvers/_lattice.py +79 -0
  388. skcomplex/engine/solvers/_lindblad.py +70 -0
  389. skcomplex/engine/solvers/_maps.py +105 -0
  390. skcomplex/engine/solvers/_mesa.py +1624 -0
  391. skcomplex/engine/solvers/_milstein.py +93 -0
  392. skcomplex/engine/solvers/_monte_carlo.py +43 -0
  393. skcomplex/engine/solvers/_operator.py +212 -0
  394. skcomplex/engine/solvers/_optimal_control.py +368 -0
  395. skcomplex/engine/solvers/_pontryagin.py +298 -0
  396. skcomplex/engine/solvers/_renewal.py +90 -0
  397. skcomplex/engine/solvers/_renewals.py +190 -0
  398. skcomplex/engine/solvers/_rk4.py +263 -0
  399. skcomplex/engine/solvers/_root.py +176 -0
  400. skcomplex/engine/solvers/_rows.py +49 -0
  401. skcomplex/engine/solvers/_scipy_ode.py +602 -0
  402. skcomplex/engine/solvers/_sde.py +164 -0
  403. skcomplex/engine/solvers/_semi_lagrangian.py +213 -0
  404. skcomplex/engine/solvers/_solver.py +159 -0
  405. skcomplex/engine/solvers/_split.py +394 -0
  406. skcomplex/engine/solvers/_ssprk.py +147 -0
  407. skcomplex/engine/solvers/_strang_splitting.py +178 -0
  408. skcomplex/engine/solvers/_unitary.py +68 -0
  409. skcomplex/engine/solvers/_velocity_verlet.py +171 -0
  410. skcomplex/engine/solvers/_yoshida4.py +242 -0
  411. skcomplex/engine/types.py +90 -0
  412. skcomplex/engine/viz/__init__.py +35 -0
  413. skcomplex/engine/viz/_agents.py +223 -0
  414. skcomplex/engine/viz/_axes.py +146 -0
  415. skcomplex/engine/viz/_base.py +365 -0
  416. skcomplex/engine/viz/_bodies.py +334 -0
  417. skcomplex/engine/viz/_cayley.py +133 -0
  418. skcomplex/engine/viz/_expectation.py +208 -0
  419. skcomplex/engine/viz/_histograms.py +218 -0
  420. skcomplex/engine/viz/_images.py +307 -0
  421. skcomplex/engine/viz/_matrices.py +141 -0
  422. skcomplex/engine/viz/_meshes.py +149 -0
  423. skcomplex/engine/viz/_points.py +238 -0
  424. skcomplex/engine/viz/_rerun.py +527 -0
  425. skcomplex/engine/viz/_rings.py +127 -0
  426. skcomplex/engine/viz/_scalars.py +129 -0
  427. skcomplex/engine/viz/_sites.py +228 -0
  428. skcomplex/errors.py +112 -0
  429. skcomplex/experiments/__init__.py +36 -0
  430. skcomplex/experiments/_base.py +373 -0
  431. skcomplex/experiments/_basin_stability.py +153 -0
  432. skcomplex/experiments/_calibration.py +194 -0
  433. skcomplex/experiments/_experiment.py +327 -0
  434. skcomplex/experiments/_grid.py +36 -0
  435. skcomplex/experiments/_latin_hypercube.py +44 -0
  436. skcomplex/experiments/_morris.py +50 -0
  437. skcomplex/experiments/_one_at_a_time.py +28 -0
  438. skcomplex/experiments/_orbit_diagram.py +146 -0
  439. skcomplex/experiments/_random.py +44 -0
  440. skcomplex/experiments/_results.py +148 -0
  441. skcomplex/experiments/_rows.py +45 -0
  442. skcomplex/experiments/_saltelli.py +50 -0
  443. skcomplex/experiments/_sensitivity.py +122 -0
  444. skcomplex/experiments/_sobol.py +43 -0
  445. skcomplex/experiments/specs/__init__.py +1 -0
  446. skcomplex/experiments/specs/_task_spec.py +78 -0
  447. skcomplex/experiments/types.py +14 -0
  448. skcomplex/models/__init__.py +18 -0
  449. skcomplex/models/_catalog.py +243 -0
  450. skcomplex/models/_model_catalog.py +270 -0
  451. skcomplex/models/_model_entry.py +170 -0
  452. skcomplex/models/_model_listing.py +38 -0
  453. skcomplex/models/biology/__init__.py +1 -0
  454. skcomplex/models/biology/collective_behaviour/__init__.py +48 -0
  455. skcomplex/models/biology/collective_behaviour/_alarm.py +99 -0
  456. skcomplex/models/biology/collective_behaviour/_ant.py +101 -0
  457. skcomplex/models/biology/collective_behaviour/_ant_view.py +24 -0
  458. skcomplex/models/biology/collective_behaviour/_boid.py +104 -0
  459. skcomplex/models/biology/collective_behaviour/_boid_view.py +25 -0
  460. skcomplex/models/biology/collective_behaviour/_branch.py +41 -0
  461. skcomplex/models/biology/collective_behaviour/_decisions.py +149 -0
  462. skcomplex/models/biology/collective_behaviour/_flight.py +52 -0
  463. skcomplex/models/biology/collective_behaviour/_flocking.py +75 -0
  464. skcomplex/models/biology/collective_behaviour/_flocks.py +169 -0
  465. skcomplex/models/biology/collective_behaviour/_foraging.py +232 -0
  466. skcomplex/models/biology/collective_behaviour/_ground.py +67 -0
  467. skcomplex/models/biology/collective_behaviour/_leadership.py +207 -0
  468. skcomplex/models/biology/collective_behaviour/_morse_potential.py +87 -0
  469. skcomplex/models/biology/collective_behaviour/_pheromone.py +55 -0
  470. skcomplex/models/biology/collective_behaviour/_rats.py +41 -0
  471. skcomplex/models/biology/collective_behaviour/_schooling.py +102 -0
  472. skcomplex/models/biology/collective_behaviour/_self_propulsion.py +64 -0
  473. skcomplex/models/biology/collective_behaviour/_shoal_member_view.py +25 -0
  474. skcomplex/models/biology/collective_behaviour/_swimming.py +66 -0
  475. skcomplex/models/biology/collective_behaviour/_trail_choice.py +105 -0
  476. skcomplex/models/biology/collective_behaviour/_trails.py +245 -0
  477. skcomplex/models/biology/collective_behaviour/_walker.py +97 -0
  478. skcomplex/models/biology/collective_behaviour/_walker_view.py +23 -0
  479. skcomplex/models/biology/common/__init__.py +3 -0
  480. skcomplex/models/biology/common/excitable/__init__.py +7 -0
  481. skcomplex/models/biology/common/excitable/_fitzhugh_nagumo.py +121 -0
  482. skcomplex/models/biology/common/kinetics/__init__.py +7 -0
  483. skcomplex/models/biology/common/kinetics/_michaelis_menten.py +137 -0
  484. skcomplex/models/biology/common/networks/__init__.py +9 -0
  485. skcomplex/models/biology/common/networks/_edge_draw.py +95 -0
  486. skcomplex/models/biology/common/networks/_weighted_edge.py +48 -0
  487. skcomplex/models/biology/common/pharmacokinetics/__init__.py +7 -0
  488. skcomplex/models/biology/common/pharmacokinetics/_dosing.py +125 -0
  489. skcomplex/models/biology/common/populations/__init__.py +19 -0
  490. skcomplex/models/biology/common/populations/_exponential_growth.py +66 -0
  491. skcomplex/models/biology/common/populations/_gompertz_growth.py +75 -0
  492. skcomplex/models/biology/common/populations/_growth.py +176 -0
  493. skcomplex/models/biology/common/populations/_logistic_growth.py +92 -0
  494. skcomplex/models/biology/common/populations/_mortality.py +69 -0
  495. skcomplex/models/biology/common/populations/_population.py +41 -0
  496. skcomplex/models/biology/common/populations/_power_law_growth.py +71 -0
  497. skcomplex/models/biology/common/stigmergy/__init__.py +7 -0
  498. skcomplex/models/biology/common/stigmergy/_evaporation.py +95 -0
  499. skcomplex/models/biology/ecology/__init__.py +128 -0
  500. skcomplex/models/biology/ecology/_abundance.py +52 -0
  501. skcomplex/models/biology/ecology/_agent_predation.py +170 -0
  502. skcomplex/models/biology/ecology/_cell_quota.py +163 -0
  503. skcomplex/models/biology/ecology/_clustering.py +96 -0
  504. skcomplex/models/biology/ecology/_communities.py +234 -0
  505. skcomplex/models/biology/ecology/_competition.py +95 -0
  506. skcomplex/models/biology/ecology/_cow.py +49 -0
  507. skcomplex/models/biology/ecology/_cow_view.py +15 -0
  508. skcomplex/models/biology/ecology/_emotion_marks.py +65 -0
  509. skcomplex/models/biology/ecology/_factories.py +322 -0
  510. skcomplex/models/biology/ecology/_forager.py +116 -0
  511. skcomplex/models/biology/ecology/_forager_view.py +25 -0
  512. skcomplex/models/biology/ecology/_fronts.py +128 -0
  513. skcomplex/models/biology/ecology/_generalized_lotka_volterra.py +66 -0
  514. skcomplex/models/biology/ecology/_grass.py +96 -0
  515. skcomplex/models/biology/ecology/_grass_view.py +17 -0
  516. skcomplex/models/biology/ecology/_grazing.py +66 -0
  517. skcomplex/models/biology/ecology/_habitat_patch.py +49 -0
  518. skcomplex/models/biology/ecology/_herding.py +84 -0
  519. skcomplex/models/biology/ecology/_higher_order.py +102 -0
  520. skcomplex/models/biology/ecology/_hopping.py +68 -0
  521. skcomplex/models/biology/ecology/_instability.py +180 -0
  522. skcomplex/models/biology/ecology/_linear_growth.py +70 -0
  523. skcomplex/models/biology/ecology/_meadow.py +102 -0
  524. skcomplex/models/biology/ecology/_microbe.py +47 -0
  525. skcomplex/models/biology/ecology/_microbial_communities.py +90 -0
  526. skcomplex/models/biology/ecology/_mutualism.py +81 -0
  527. skcomplex/models/biology/ecology/_neutral.py +144 -0
  528. skcomplex/models/biology/ecology/_neutral_replacement.py +54 -0
  529. skcomplex/models/biology/ecology/_organism.py +63 -0
  530. skcomplex/models/biology/ecology/_organism_view.py +15 -0
  531. skcomplex/models/biology/ecology/_parasitism.py +78 -0
  532. skcomplex/models/biology/ecology/_pasture.py +83 -0
  533. skcomplex/models/biology/ecology/_pasture_view.py +16 -0
  534. skcomplex/models/biology/ecology/_pioneer_growth.py +101 -0
  535. skcomplex/models/biology/ecology/_plant.py +56 -0
  536. skcomplex/models/biology/ecology/_plant_view.py +16 -0
  537. skcomplex/models/biology/ecology/_predation.py +290 -0
  538. skcomplex/models/biology/ecology/_predation_interaction.py +71 -0
  539. skcomplex/models/biology/ecology/_predator.py +63 -0
  540. skcomplex/models/biology/ecology/_predator_prey_events.py +120 -0
  541. skcomplex/models/biology/ecology/_predator_view.py +17 -0
  542. skcomplex/models/biology/ecology/_prey.py +52 -0
  543. skcomplex/models/biology/ecology/_prey_view.py +15 -0
  544. skcomplex/models/biology/ecology/_rosenzweig_macarthur.py +91 -0
  545. skcomplex/models/biology/ecology/_seasonal_logistic_growth.py +71 -0
  546. skcomplex/models/biology/ecology/_sequential.py +114 -0
  547. skcomplex/models/biology/ecology/_sheep.py +63 -0
  548. skcomplex/models/biology/ecology/_sheep_view.py +17 -0
  549. skcomplex/models/biology/ecology/_speciation.py +71 -0
  550. skcomplex/models/biology/ecology/_stand.py +47 -0
  551. skcomplex/models/biology/ecology/_stigmergic_predator.py +98 -0
  552. skcomplex/models/biology/ecology/_stigmergic_prey.py +54 -0
  553. skcomplex/models/biology/ecology/_stigmergy.py +413 -0
  554. skcomplex/models/biology/ecology/_succession.py +92 -0
  555. skcomplex/models/biology/ecology/_successional_growth.py +88 -0
  556. skcomplex/models/biology/ecology/_triplet.py +55 -0
  557. skcomplex/models/biology/ecology/_wolf.py +63 -0
  558. skcomplex/models/biology/ecology/_wolf_sheep.py +156 -0
  559. skcomplex/models/biology/ecology/_wolf_view.py +17 -0
  560. skcomplex/models/biology/epidemiology/__init__.py +53 -0
  561. skcomplex/models/biology/epidemiology/_active_host.py +61 -0
  562. skcomplex/models/biology/epidemiology/_adaptive.py +316 -0
  563. skcomplex/models/biology/epidemiology/_agents.py +484 -0
  564. skcomplex/models/biology/epidemiology/_carrier.py +66 -0
  565. skcomplex/models/biology/epidemiology/_degree_class.py +65 -0
  566. skcomplex/models/biology/epidemiology/_factories.py +186 -0
  567. skcomplex/models/biology/epidemiology/_host.py +49 -0
  568. skcomplex/models/biology/epidemiology/_immunity_loss.py +84 -0
  569. skcomplex/models/biology/epidemiology/_infection.py +93 -0
  570. skcomplex/models/biology/epidemiology/_networks.py +170 -0
  571. skcomplex/models/biology/epidemiology/_outbreaks.py +216 -0
  572. skcomplex/models/biology/epidemiology/_person.py +103 -0
  573. skcomplex/models/biology/epidemiology/_person_view.py +23 -0
  574. skcomplex/models/biology/epidemiology/_recovery.py +92 -0
  575. skcomplex/models/biology/epidemiology/_recurrent.py +149 -0
  576. skcomplex/models/biology/epidemiology/_spreading.py +144 -0
  577. skcomplex/models/biology/epidemiology/_subpopulation.py +92 -0
  578. skcomplex/models/biology/epidemiology/_traveller.py +65 -0
  579. skcomplex/models/biology/epidemiology/_traveller_view.py +17 -0
  580. skcomplex/models/biology/epidemiology/_vaccination.py +184 -0
  581. skcomplex/models/biology/epidemiology/_walker.py +66 -0
  582. skcomplex/models/biology/epidemiology/_walker_view.py +17 -0
  583. skcomplex/models/biology/evolution/__init__.py +60 -0
  584. skcomplex/models/biology/evolution/_adaptive_climbing.py +106 -0
  585. skcomplex/models/biology/evolution/_catalysis.py +76 -0
  586. skcomplex/models/biology/evolution/_catalytic_link.py +21 -0
  587. skcomplex/models/biology/evolution/_chemical.py +111 -0
  588. skcomplex/models/biology/evolution/_climber.py +125 -0
  589. skcomplex/models/biology/evolution/_climber_view.py +19 -0
  590. skcomplex/models/biology/evolution/_coevolution.py +148 -0
  591. skcomplex/models/biology/evolution/_cyclic_species.py +44 -0
  592. skcomplex/models/biology/evolution/_dependency_field.py +56 -0
  593. skcomplex/models/biology/evolution/_finite_populations.py +287 -0
  594. skcomplex/models/biology/evolution/_games.py +143 -0
  595. skcomplex/models/biology/evolution/_genotype_class.py +42 -0
  596. skcomplex/models/biology/evolution/_individual.py +54 -0
  597. skcomplex/models/biology/evolution/_individual_view.py +16 -0
  598. skcomplex/models/biology/evolution/_locus.py +47 -0
  599. skcomplex/models/biology/evolution/_master_sequence.py +55 -0
  600. skcomplex/models/biology/evolution/_molecule.py +47 -0
  601. skcomplex/models/biology/evolution/_moran_step.py +83 -0
  602. skcomplex/models/biology/evolution/_networks.py +194 -0
  603. skcomplex/models/biology/evolution/_prebiotic.py +169 -0
  604. skcomplex/models/biology/evolution/_replicator.py +109 -0
  605. skcomplex/models/biology/evolution/_strategy.py +42 -0
  606. skcomplex/models/biology/evolution/_substitution.py +113 -0
  607. skcomplex/models/biology/evolution/_substitutions.py +126 -0
  608. skcomplex/models/biology/evolution/_tangled_nature_life_cycle.py +159 -0
  609. skcomplex/models/biology/evolution/_taxon.py +49 -0
  610. skcomplex/models/biology/neuroscience/__init__.py +63 -0
  611. skcomplex/models/biology/neuroscience/_conductances.py +193 -0
  612. skcomplex/models/biology/neuroscience/_delayed_synapse.py +70 -0
  613. skcomplex/models/biology/neuroscience/_excitable.py +178 -0
  614. skcomplex/models/biology/neuroscience/_fitz_hugh_nagumo_neuron.py +46 -0
  615. skcomplex/models/biology/neuroscience/_global_inhibition.py +71 -0
  616. skcomplex/models/biology/neuroscience/_hodgkin_huxley.py +103 -0
  617. skcomplex/models/biology/neuroscience/_inhibitor.py +62 -0
  618. skcomplex/models/biology/neuroscience/_inhibitor_drive.py +61 -0
  619. skcomplex/models/biology/neuroscience/_izhikevich.py +77 -0
  620. skcomplex/models/biology/neuroscience/_leaky_integrate_and_fire.py +80 -0
  621. skcomplex/models/biology/neuroscience/_mutual_inhibition.py +55 -0
  622. skcomplex/models/biology/neuroscience/_networks.py +235 -0
  623. skcomplex/models/biology/neuroscience/_neural_field_site.py +66 -0
  624. skcomplex/models/biology/neuroscience/_neural_fields.py +94 -0
  625. skcomplex/models/biology/neuroscience/_neurons.py +129 -0
  626. skcomplex/models/biology/neuroscience/_polyhomeostatic_neuron.py +93 -0
  627. skcomplex/models/biology/neuroscience/_populations.py +333 -0
  628. skcomplex/models/biology/neuroscience/_pulse_coupling.py +71 -0
  629. skcomplex/models/biology/neuroscience/_rate_unit.py +67 -0
  630. skcomplex/models/biology/neuroscience/_spike_reset.py +95 -0
  631. skcomplex/models/biology/neuroscience/_spiking_neuron.py +67 -0
  632. skcomplex/models/biology/neuroscience/_synapses.py +226 -0
  633. skcomplex/models/biology/neuroscience/_terman_wang.py +113 -0
  634. skcomplex/models/biology/neuroscience/_theta_neuron.py +66 -0
  635. skcomplex/models/biology/neuroscience/_wilson_cowan.py +122 -0
  636. skcomplex/models/biology/neuroscience/types.py +8 -0
  637. skcomplex/models/biology/oncology/__init__.py +212 -0
  638. skcomplex/models/biology/oncology/_androgen_receptor_prostate.py +240 -0
  639. skcomplex/models/biology/oncology/_androgen_suppression.py +109 -0
  640. skcomplex/models/biology/oncology/_angiogenesis.py +306 -0
  641. skcomplex/models/biology/oncology/_angiogenesis_immunotherapy_tumour.py +247 -0
  642. skcomplex/models/biology/oncology/_angiogenic_tumour.py +110 -0
  643. skcomplex/models/biology/oncology/_antiangiogenic.py +227 -0
  644. skcomplex/models/biology/oncology/_bone_marrow_blood.py +196 -0
  645. skcomplex/models/biology/oncology/_cell_cycle.py +85 -0
  646. skcomplex/models/biology/oncology/_cell_kinetics.py +285 -0
  647. skcomplex/models/biology/oncology/_cell_quota_prostate.py +207 -0
  648. skcomplex/models/biology/oncology/_cell_survival.py +72 -0
  649. skcomplex/models/biology/oncology/_checkpoint_tumour.py +161 -0
  650. skcomplex/models/biology/oncology/_chemoimmunotherapy_tumour.py +251 -0
  651. skcomplex/models/biology/oncology/_chemotherapy.py +565 -0
  652. skcomplex/models/biology/oncology/_chemovirotherapy_tumour.py +139 -0
  653. skcomplex/models/biology/oncology/_clonal_tumour.py +134 -0
  654. skcomplex/models/biology/oncology/_combination_therapy.py +989 -0
  655. skcomplex/models/biology/oncology/_delayed_vaccinated_tumour.py +341 -0
  656. skcomplex/models/biology/oncology/_dormant_cell_cycle.py +95 -0
  657. skcomplex/models/biology/oncology/_erythropoiesis.py +129 -0
  658. skcomplex/models/biology/oncology/_exponential_linear_growth.py +66 -0
  659. skcomplex/models/biology/oncology/_gene_viral_therapy.py +480 -0
  660. skcomplex/models/biology/oncology/_glioma_brain.py +165 -0
  661. skcomplex/models/biology/oncology/_growth.py +378 -0
  662. skcomplex/models/biology/oncology/_her2_tumour.py +156 -0
  663. skcomplex/models/biology/oncology/_hormone_therapy.py +985 -0
  664. skcomplex/models/biology/oncology/_immune_competition.py +241 -0
  665. skcomplex/models/biology/oncology/_immunotherapy.py +1001 -0
  666. skcomplex/models/biology/oncology/_intermittent_suppression.py +130 -0
  667. skcomplex/models/biology/oncology/_irradiated_tumour.py +105 -0
  668. skcomplex/models/biology/oncology/_irradiation.py +97 -0
  669. skcomplex/models/biology/oncology/_kirschner_panetta_tumour.py +132 -0
  670. skcomplex/models/biology/oncology/_leukaemia_stem_cells.py +150 -0
  671. skcomplex/models/biology/oncology/_linear_quadratic_survival.py +112 -0
  672. skcomplex/models/biology/oncology/_log_kill.py +81 -0
  673. skcomplex/models/biology/oncology/_metastasis_chemotherapy.py +211 -0
  674. skcomplex/models/biology/oncology/_multidrug_resistance.py +201 -0
  675. skcomplex/models/biology/oncology/_oncolytic_virus.py +68 -0
  676. skcomplex/models/biology/oncology/_oncolytic_virus_dendritic.py +155 -0
  677. skcomplex/models/biology/oncology/_optimal_chemotherapy.py +157 -0
  678. skcomplex/models/biology/oncology/_optimal_immunotherapy.py +137 -0
  679. skcomplex/models/biology/oncology/_optimal_therapy.py +208 -0
  680. skcomplex/models/biology/oncology/_piecewise_linear_prostate.py +147 -0
  681. skcomplex/models/biology/oncology/_radiation_competition.py +104 -0
  682. skcomplex/models/biology/oncology/_radiotherapy.py +311 -0
  683. skcomplex/models/biology/oncology/_resistance_switching.py +148 -0
  684. skcomplex/models/biology/oncology/_resting_hunting_chemotherapy.py +136 -0
  685. skcomplex/models/biology/oncology/_sirna_tgf_beta.py +189 -0
  686. skcomplex/models/biology/oncology/_sprout.py +65 -0
  687. skcomplex/models/biology/oncology/_sprout_view.py +17 -0
  688. skcomplex/models/biology/oncology/_stem_cell_differentiation.py +262 -0
  689. skcomplex/models/biology/oncology/_stem_cells.py +548 -0
  690. skcomplex/models/biology/oncology/_suppressed_tumour.py +338 -0
  691. skcomplex/models/biology/oncology/_tamoxifen_tumour.py +172 -0
  692. skcomplex/models/biology/oncology/_tcr_gene_therapy.py +98 -0
  693. skcomplex/models/biology/oncology/_therapy_switch.py +86 -0
  694. skcomplex/models/biology/oncology/_tissue.py +71 -0
  695. skcomplex/models/biology/oncology/_tumour_cell.py +85 -0
  696. skcomplex/models/biology/oncology/_tumour_cell_view.py +21 -0
  697. skcomplex/models/biology/oncology/_tumour_immune_chemotherapy.py +169 -0
  698. skcomplex/models/biology/oncology/_vaccinated_tumour.py +180 -0
  699. skcomplex/models/biology/oncology/_vascular_support.py +71 -0
  700. skcomplex/models/biology/oncology/_vascularized_spheroid.py +264 -0
  701. skcomplex/models/biology/oncology/_vasculature.py +42 -0
  702. skcomplex/models/biology/oncology/_vessel.py +49 -0
  703. skcomplex/models/biology/oncology/_vessel_view.py +15 -0
  704. skcomplex/models/biology/physiology/__init__.py +46 -0
  705. skcomplex/models/biology/physiology/_adaptivity.py +277 -0
  706. skcomplex/models/biology/physiology/_cardiac.py +167 -0
  707. skcomplex/models/biology/physiology/_chamber.py +71 -0
  708. skcomplex/models/biology/physiology/_circulation.py +97 -0
  709. skcomplex/models/biology/physiology/_coagulation.py +130 -0
  710. skcomplex/models/biology/physiology/_contour_cell.py +61 -0
  711. skcomplex/models/biology/physiology/_contour_uptake.py +61 -0
  712. skcomplex/models/biology/physiology/_exchange.py +165 -0
  713. skcomplex/models/biology/physiology/_exchanging_cell.py +83 -0
  714. skcomplex/models/biology/physiology/_fitz_hugh_nagumo.py +46 -0
  715. skcomplex/models/biology/physiology/_glucose_control.py +136 -0
  716. skcomplex/models/biology/physiology/_mackey_glass.py +81 -0
  717. skcomplex/models/biology/physiology/_pharmacokinetics.py +104 -0
  718. skcomplex/models/biology/physiology/_physiology.py +118 -0
  719. skcomplex/models/biology/physiology/_regulation.py +251 -0
  720. skcomplex/models/biology/physiology/_resistive_flow.py +67 -0
  721. skcomplex/models/biology/physiology/_toxicity.py +164 -0
  722. skcomplex/models/biology/systems_biology/__init__.py +52 -0
  723. skcomplex/models/biology/systems_biology/_boolean.py +141 -0
  724. skcomplex/models/biology/systems_biology/_boolean_function.py +84 -0
  725. skcomplex/models/biology/systems_biology/_boolean_models.py +206 -0
  726. skcomplex/models/biology/systems_biology/_boolean_node.py +41 -0
  727. skcomplex/models/biology/systems_biology/_cascades.py +178 -0
  728. skcomplex/models/biology/systems_biology/_clocks.py +274 -0
  729. skcomplex/models/biology/systems_biology/_generalized_mass_action.py +123 -0
  730. skcomplex/models/biology/systems_biology/_genes.py +296 -0
  731. skcomplex/models/biology/systems_biology/_min_proteins.py +230 -0
  732. skcomplex/models/biology/systems_biology/_networks.py +359 -0
  733. skcomplex/models/biology/systems_biology/_phosphorylation_loop.py +121 -0
  734. skcomplex/models/biology/systems_biology/_probabilistic.py +75 -0
  735. skcomplex/models/biology/systems_biology/_probabilistic_function.py +127 -0
  736. skcomplex/models/biology/systems_biology/_probabilistic_node.py +47 -0
  737. skcomplex/models/biology/systems_biology/_repression.py +104 -0
  738. skcomplex/models/biology/systems_biology/_s_system.py +88 -0
  739. skcomplex/models/biology/systems_biology/_species.py +44 -0
  740. skcomplex/models/biology/systems_biology/_threshold_function.py +63 -0
  741. skcomplex/models/biology/systems_biology/types.py +9 -0
  742. skcomplex/models/chemistry/__init__.py +1 -0
  743. skcomplex/models/chemistry/common/__init__.py +3 -0
  744. skcomplex/models/chemistry/common/kinetics/__init__.py +9 -0
  745. skcomplex/models/chemistry/common/kinetics/_brusselator.py +61 -0
  746. skcomplex/models/chemistry/common/kinetics/_cubic_autocatalysis.py +80 -0
  747. skcomplex/models/chemistry/kinetics/__init__.py +38 -0
  748. skcomplex/models/chemistry/kinetics/_catalyst_pellet.py +60 -0
  749. skcomplex/models/chemistry/kinetics/_cubic_autocatalysis.py +60 -0
  750. skcomplex/models/chemistry/kinetics/_cyclic.py +130 -0
  751. skcomplex/models/chemistry/kinetics/_hodgepodge.py +157 -0
  752. skcomplex/models/chemistry/kinetics/_nanoparticles.py +103 -0
  753. skcomplex/models/chemistry/kinetics/_oregonator.py +76 -0
  754. skcomplex/models/chemistry/kinetics/_oscillators.py +244 -0
  755. skcomplex/models/chemistry/kinetics/_pulsed_electrode.py +107 -0
  756. skcomplex/models/chemistry/kinetics/_reactions.py +332 -0
  757. skcomplex/models/chemistry/kinetics/_reactors.py +144 -0
  758. skcomplex/models/chemistry/pattern_formation/__init__.py +15 -0
  759. skcomplex/models/chemistry/pattern_formation/_brusselator.py +62 -0
  760. skcomplex/models/chemistry/pattern_formation/_gray_scott.py +68 -0
  761. skcomplex/models/chemistry/pattern_formation/_reaction_diffusion.py +268 -0
  762. skcomplex/models/chemistry/pattern_formation/_schnakenberg.py +67 -0
  763. skcomplex/models/computer_science/__init__.py +1 -0
  764. skcomplex/models/computer_science/automata/__init__.py +56 -0
  765. skcomplex/models/computer_science/automata/_automata.py +229 -0
  766. skcomplex/models/computer_science/automata/_automaton.py +202 -0
  767. skcomplex/models/computer_science/automata/_binary_cell.py +41 -0
  768. skcomplex/models/computer_science/automata/_codes.py +73 -0
  769. skcomplex/models/computer_science/automata/_diffusion_cell.py +47 -0
  770. skcomplex/models/computer_science/automata/_group_automata.py +449 -0
  771. skcomplex/models/computer_science/automata/_groups.py +132 -0
  772. skcomplex/models/computer_science/automata/_linear_automaton.py +128 -0
  773. skcomplex/models/computer_science/automata/_noisy_elementary_cell.py +46 -0
  774. skcomplex/models/computer_science/automata/_pascal_cell.py +41 -0
  775. skcomplex/models/computer_science/automata/_subshift.py +192 -0
  776. skcomplex/models/computer_science/automata/_variants.py +292 -0
  777. skcomplex/models/computer_science/evolutionary_computation/__init__.py +27 -0
  778. skcomplex/models/computer_science/evolutionary_computation/_annealed_candidate.py +39 -0
  779. skcomplex/models/computer_science/evolutionary_computation/_bit_string.py +55 -0
  780. skcomplex/models/computer_science/evolutionary_computation/_bit_string_view.py +13 -0
  781. skcomplex/models/computer_science/evolutionary_computation/_genetic_algorithms.py +92 -0
  782. skcomplex/models/computer_science/evolutionary_computation/_landscapes.py +82 -0
  783. skcomplex/models/computer_science/evolutionary_computation/_optimisers.py +217 -0
  784. skcomplex/models/computer_science/evolutionary_computation/_reproduction.py +129 -0
  785. skcomplex/models/computer_science/evolutionary_computation/_room_cleaning.py +170 -0
  786. skcomplex/models/computer_science/evolutionary_computation/_running_best.py +30 -0
  787. skcomplex/models/computer_science/evolutionary_computation/_running_best_update.py +58 -0
  788. skcomplex/models/computer_science/evolutionary_computation/_search_candidate.py +32 -0
  789. skcomplex/models/computer_science/evolutionary_computation/_strategy.py +54 -0
  790. skcomplex/models/computer_science/evolutionary_computation/_strategy_view.py +14 -0
  791. skcomplex/models/computer_science/neural_networks/__init__.py +34 -0
  792. skcomplex/models/computer_science/neural_networks/_binary_weight.py +32 -0
  793. skcomplex/models/computer_science/neural_networks/_diluted.py +159 -0
  794. skcomplex/models/computer_science/neural_networks/_echo_state.py +173 -0
  795. skcomplex/models/computer_science/neural_networks/_elman.py +160 -0
  796. skcomplex/models/computer_science/neural_networks/_hidden_unit.py +51 -0
  797. skcomplex/models/computer_science/neural_networks/_hopfield.py +134 -0
  798. skcomplex/models/computer_science/neural_networks/_hopfield_update.py +51 -0
  799. skcomplex/models/computer_science/neural_networks/_input_coupling.py +63 -0
  800. skcomplex/models/computer_science/neural_networks/_input_unit.py +39 -0
  801. skcomplex/models/computer_science/neural_networks/_neuron_view.py +14 -0
  802. skcomplex/models/computer_science/neural_networks/_output_unit.py +51 -0
  803. skcomplex/models/computer_science/neural_networks/_perceptron.py +72 -0
  804. skcomplex/models/computer_science/neural_networks/_readout_coupling.py +69 -0
  805. skcomplex/models/computer_science/neural_networks/_recurrence_coupling.py +66 -0
  806. skcomplex/models/economics/__init__.py +1 -0
  807. skcomplex/models/economics/common/__init__.py +3 -0
  808. skcomplex/models/economics/common/forecasting/__init__.py +7 -0
  809. skcomplex/models/economics/common/forecasting/_heuristics.py +51 -0
  810. skcomplex/models/economics/common/resources/__init__.py +7 -0
  811. skcomplex/models/economics/common/resources/_regrowth.py +70 -0
  812. skcomplex/models/economics/econophysics/__init__.py +58 -0
  813. skcomplex/models/economics/econophysics/_crowd_avoidance.py +80 -0
  814. skcomplex/models/economics/econophysics/_debt_exchange.py +74 -0
  815. skcomplex/models/economics/econophysics/_diner.py +59 -0
  816. skcomplex/models/economics/econophysics/_diner_view.py +17 -0
  817. skcomplex/models/economics/econophysics/_el_farol.py +114 -0
  818. skcomplex/models/economics/econophysics/_exchange.py +82 -0
  819. skcomplex/models/economics/econophysics/_game_state_spec.py +26 -0
  820. skcomplex/models/economics/econophysics/_kinetic.py +80 -0
  821. skcomplex/models/economics/econophysics/_kolkata.py +87 -0
  822. skcomplex/models/economics/econophysics/_minority.py +123 -0
  823. skcomplex/models/economics/econophysics/_minority_game.py +161 -0
  824. skcomplex/models/economics/econophysics/_minority_player.py +79 -0
  825. skcomplex/models/economics/econophysics/_minority_player_view.py +22 -0
  826. skcomplex/models/economics/econophysics/_patron.py +105 -0
  827. skcomplex/models/economics/econophysics/_patron_view.py +18 -0
  828. skcomplex/models/economics/econophysics/_predictor_pool.py +181 -0
  829. skcomplex/models/economics/econophysics/_predictor_pool_view.py +14 -0
  830. skcomplex/models/economics/econophysics/_restaurants.py +93 -0
  831. skcomplex/models/economics/econophysics/_saving_exchange.py +73 -0
  832. skcomplex/models/economics/econophysics/_saving_trader.py +47 -0
  833. skcomplex/models/economics/econophysics/_saving_trader_view.py +12 -0
  834. skcomplex/models/economics/econophysics/_wealth_exchange.py +114 -0
  835. skcomplex/models/economics/econophysics/_welfare.py +210 -0
  836. skcomplex/models/economics/econophysics/_welfare_policy.py +99 -0
  837. skcomplex/models/economics/finance/__init__.py +41 -0
  838. skcomplex/models/economics/finance/_arbitrage.py +139 -0
  839. skcomplex/models/economics/finance/_asset.py +42 -0
  840. skcomplex/models/economics/finance/_assets.py +44 -0
  841. skcomplex/models/economics/finance/_book.py +115 -0
  842. skcomplex/models/economics/finance/_contagion.py +116 -0
  843. skcomplex/models/economics/finance/_correlated_assets.py +69 -0
  844. skcomplex/models/economics/finance/_debt_rank_cascade.py +86 -0
  845. skcomplex/models/economics/finance/_geometric_brownian_motion.py +89 -0
  846. skcomplex/models/economics/finance/_gibrat_firm.py +82 -0
  847. skcomplex/models/economics/finance/_gibrat_firm_view.py +18 -0
  848. skcomplex/models/economics/finance/_growth_processes.py +195 -0
  849. skcomplex/models/economics/finance/_interbank.py +76 -0
  850. skcomplex/models/economics/finance/_interbank_view.py +14 -0
  851. skcomplex/models/economics/finance/_kesten_firm.py +88 -0
  852. skcomplex/models/economics/finance/_kesten_firm_view.py +16 -0
  853. skcomplex/models/economics/finance/_order_book.py +164 -0
  854. skcomplex/models/economics/finance/_reflecting_floor.py +66 -0
  855. skcomplex/models/economics/finance/_stock_trader.py +205 -0
  856. skcomplex/models/economics/finance/_stock_trader_view.py +24 -0
  857. skcomplex/models/economics/finance/_wealth.py +143 -0
  858. skcomplex/models/economics/innovation/__init__.py +23 -0
  859. skcomplex/models/economics/innovation/_adoption.py +233 -0
  860. skcomplex/models/economics/innovation/_bass.py +124 -0
  861. skcomplex/models/economics/innovation/_diversity.py +104 -0
  862. skcomplex/models/economics/innovation/_household_view.py +20 -0
  863. skcomplex/models/economics/innovation/_invention.py +140 -0
  864. skcomplex/models/economics/innovation/_part.py +64 -0
  865. skcomplex/models/economics/innovation/_part_view.py +12 -0
  866. skcomplex/models/economics/innovation/_redesign.py +88 -0
  867. skcomplex/models/economics/innovation/_technology.py +203 -0
  868. skcomplex/models/economics/innovation/_technology_view.py +14 -0
  869. skcomplex/models/economics/macroeconomics/__init__.py +70 -0
  870. skcomplex/models/economics/macroeconomics/_banking.py +148 -0
  871. skcomplex/models/economics/macroeconomics/_business.py +221 -0
  872. skcomplex/models/economics/macroeconomics/_business_view.py +24 -0
  873. skcomplex/models/economics/macroeconomics/_capital.py +122 -0
  874. skcomplex/models/economics/macroeconomics/_central_bank.py +80 -0
  875. skcomplex/models/economics/macroeconomics/_central_bank_view.py +13 -0
  876. skcomplex/models/economics/macroeconomics/_circuit.py +93 -0
  877. skcomplex/models/economics/macroeconomics/_commons.py +77 -0
  878. skcomplex/models/economics/macroeconomics/_credit.py +219 -0
  879. skcomplex/models/economics/macroeconomics/_credit_market.py +83 -0
  880. skcomplex/models/economics/macroeconomics/_depositor.py +114 -0
  881. skcomplex/models/economics/macroeconomics/_depositor_view.py +19 -0
  882. skcomplex/models/economics/macroeconomics/_economy.py +42 -0
  883. skcomplex/models/economics/macroeconomics/_estate.py +88 -0
  884. skcomplex/models/economics/macroeconomics/_firm.py +184 -0
  885. skcomplex/models/economics/macroeconomics/_firm_view.py +27 -0
  886. skcomplex/models/economics/macroeconomics/_firms.py +208 -0
  887. skcomplex/models/economics/macroeconomics/_firms_element.py +67 -0
  888. skcomplex/models/economics/macroeconomics/_food_market.py +84 -0
  889. skcomplex/models/economics/macroeconomics/_growth.py +109 -0
  890. skcomplex/models/economics/macroeconomics/_households.py +52 -0
  891. skcomplex/models/economics/macroeconomics/_income.py +59 -0
  892. skcomplex/models/economics/macroeconomics/_investing_firm_view.py +21 -0
  893. skcomplex/models/economics/macroeconomics/_labour_market.py +73 -0
  894. skcomplex/models/economics/macroeconomics/_lender.py +160 -0
  895. skcomplex/models/economics/macroeconomics/_lender_view.py +18 -0
  896. skcomplex/models/economics/macroeconomics/_metaphoria.py +257 -0
  897. skcomplex/models/economics/macroeconomics/_monetary.py +140 -0
  898. skcomplex/models/economics/macroeconomics/_monetary_bank.py +57 -0
  899. skcomplex/models/economics/macroeconomics/_optimal_growth.py +173 -0
  900. skcomplex/models/economics/macroeconomics/_people_spec.py +26 -0
  901. skcomplex/models/economics/macroeconomics/_plot.py +69 -0
  902. skcomplex/models/economics/macroeconomics/_plot_view.py +15 -0
  903. skcomplex/models/economics/macroeconomics/_policy_switch.py +78 -0
  904. skcomplex/models/economics/macroeconomics/_reserve_bank.py +118 -0
  905. skcomplex/models/economics/macroeconomics/_reserve_bank_view.py +14 -0
  906. skcomplex/models/economics/macroeconomics/_settler.py +291 -0
  907. skcomplex/models/economics/macroeconomics/_settler_view.py +56 -0
  908. skcomplex/models/economics/macroeconomics/_solow_growth.py +70 -0
  909. skcomplex/models/economics/macroeconomics/_trade.py +289 -0
  910. skcomplex/models/economics/markets/__init__.py +128 -0
  911. skcomplex/models/economics/markets/_auction_ledger.py +81 -0
  912. skcomplex/models/economics/markets/_barter.py +232 -0
  913. skcomplex/models/economics/markets/_barter_networks.py +169 -0
  914. skcomplex/models/economics/markets/_barter_trader.py +136 -0
  915. skcomplex/models/economics/markets/_barter_trader_view.py +16 -0
  916. skcomplex/models/economics/markets/_bilateral_barter.py +150 -0
  917. skcomplex/models/economics/markets/_brewery.py +67 -0
  918. skcomplex/models/economics/markets/_brock_hommes.py +115 -0
  919. skcomplex/models/economics/markets/_car.py +75 -0
  920. skcomplex/models/economics/markets/_car_view.py +14 -0
  921. skcomplex/models/economics/markets/_car_wash_operation.py +141 -0
  922. skcomplex/models/economics/markets/_cobweb.py +109 -0
  923. skcomplex/models/economics/markets/_commodities.py +286 -0
  924. skcomplex/models/economics/markets/_consumer_view.py +22 -0
  925. skcomplex/models/economics/markets/_cournot_adjustment.py +65 -0
  926. skcomplex/models/economics/markets/_cournot_best_response.py +88 -0
  927. skcomplex/models/economics/markets/_customer.py +147 -0
  928. skcomplex/models/economics/markets/_customer_view.py +16 -0
  929. skcomplex/models/economics/markets/_double_auction.py +141 -0
  930. skcomplex/models/economics/markets/_duopolist.py +54 -0
  931. skcomplex/models/economics/markets/_duopolist_view.py +13 -0
  932. skcomplex/models/economics/markets/_duopoly.py +85 -0
  933. skcomplex/models/economics/markets/_echelon.py +132 -0
  934. skcomplex/models/economics/markets/_employer.py +102 -0
  935. skcomplex/models/economics/markets/_employer_view.py +20 -0
  936. skcomplex/models/economics/markets/_exchange.py +171 -0
  937. skcomplex/models/economics/markets/_exchange_interaction.py +134 -0
  938. skcomplex/models/economics/markets/_factory.py +105 -0
  939. skcomplex/models/economics/markets/_fair_food.py +205 -0
  940. skcomplex/models/economics/markets/_forager.py +64 -0
  941. skcomplex/models/economics/markets/_forager_view.py +14 -0
  942. skcomplex/models/economics/markets/_goods_trader.py +68 -0
  943. skcomplex/models/economics/markets/_goods_traders.py +139 -0
  944. skcomplex/models/economics/markets/_heuristic_pricing.py +122 -0
  945. skcomplex/models/economics/markets/_heuristic_trader.py +108 -0
  946. skcomplex/models/economics/markets/_heuristic_trader_view.py +14 -0
  947. skcomplex/models/economics/markets/_inventory.py +212 -0
  948. skcomplex/models/economics/markets/_jobseeker.py +144 -0
  949. skcomplex/models/economics/markets/_jobseeker_view.py +26 -0
  950. skcomplex/models/economics/markets/_labour.py +188 -0
  951. skcomplex/models/economics/markets/_market.py +39 -0
  952. skcomplex/models/economics/markets/_market_state_spec.py +25 -0
  953. skcomplex/models/economics/markets/_oligopoly.py +167 -0
  954. skcomplex/models/economics/markets/_patch_map_spec.py +22 -0
  955. skcomplex/models/economics/markets/_perishables.py +150 -0
  956. skcomplex/models/economics/markets/_price_point.py +95 -0
  957. skcomplex/models/economics/markets/_prices.py +151 -0
  958. skcomplex/models/economics/markets/_pricing_firm.py +48 -0
  959. skcomplex/models/economics/markets/_pricing_firm_view.py +14 -0
  960. skcomplex/models/economics/markets/_pricing_game_spec.py +81 -0
  961. skcomplex/models/economics/markets/_produce.py +94 -0
  962. skcomplex/models/economics/markets/_product.py +97 -0
  963. skcomplex/models/economics/markets/_product_view.py +13 -0
  964. skcomplex/models/economics/markets/_queues.py +101 -0
  965. skcomplex/models/economics/markets/_resident.py +119 -0
  966. skcomplex/models/economics/markets/_resident_view.py +20 -0
  967. skcomplex/models/economics/markets/_retail_demand.py +52 -0
  968. skcomplex/models/economics/markets/_retailer.py +115 -0
  969. skcomplex/models/economics/markets/_shopper.py +115 -0
  970. skcomplex/models/economics/markets/_shopper_view.py +15 -0
  971. skcomplex/models/economics/markets/_shops.py +199 -0
  972. skcomplex/models/economics/markets/_stall.py +74 -0
  973. skcomplex/models/economics/markets/_stall_view.py +14 -0
  974. skcomplex/models/economics/markets/_store.py +171 -0
  975. skcomplex/models/economics/markets/_store_view.py +27 -0
  976. skcomplex/models/economics/markets/_sugar_patch.py +61 -0
  977. skcomplex/models/economics/markets/_sugar_patch_view.py +14 -0
  978. skcomplex/models/economics/markets/_sugarscape.py +250 -0
  979. skcomplex/models/economics/markets/_supply_chains.py +217 -0
  980. skcomplex/models/economics/markets/_supply_link.py +74 -0
  981. skcomplex/models/economics/markets/_till.py +79 -0
  982. skcomplex/models/economics/markets/_till_view.py +15 -0
  983. skcomplex/models/economics/markets/_washer.py +78 -0
  984. skcomplex/models/economics/markets/_zero_intelligence_buyer.py +99 -0
  985. skcomplex/models/economics/markets/_zero_intelligence_buyer_view.py +20 -0
  986. skcomplex/models/economics/markets/_zero_intelligence_seller.py +100 -0
  987. skcomplex/models/economics/markets/_zero_intelligence_seller_view.py +20 -0
  988. skcomplex/models/economics/resources/__init__.py +50 -0
  989. skcomplex/models/economics/resources/_bid_rent.py +104 -0
  990. skcomplex/models/economics/resources/_commons.py +218 -0
  991. skcomplex/models/economics/resources/_cow.py +69 -0
  992. skcomplex/models/economics/resources/_cow_view.py +13 -0
  993. skcomplex/models/economics/resources/_extraction.py +230 -0
  994. skcomplex/models/economics/resources/_farmer.py +93 -0
  995. skcomplex/models/economics/resources/_farmer_view.py +12 -0
  996. skcomplex/models/economics/resources/_fisheries.py +384 -0
  997. skcomplex/models/economics/resources/_fishery.py +91 -0
  998. skcomplex/models/economics/resources/_food.py +370 -0
  999. skcomplex/models/economics/resources/_grazing.py +148 -0
  1000. skcomplex/models/economics/resources/_harvest.py +69 -0
  1001. skcomplex/models/economics/resources/_harvesting.py +51 -0
  1002. skcomplex/models/economics/resources/_herder.py +78 -0
  1003. skcomplex/models/economics/resources/_herder_view.py +19 -0
  1004. skcomplex/models/economics/resources/_land_cell.py +39 -0
  1005. skcomplex/models/economics/resources/_land_use.py +73 -0
  1006. skcomplex/models/economics/resources/_oil_economy.py +85 -0
  1007. skcomplex/models/economics/resources/_optimal_harvesting.py +180 -0
  1008. skcomplex/models/economics/resources/_pasture.py +98 -0
  1009. skcomplex/models/economics/resources/_pasture_view.py +15 -0
  1010. skcomplex/models/economics/resources/_plantations.py +359 -0
  1011. skcomplex/models/economics/resources/_quota_regulator.py +84 -0
  1012. skcomplex/models/economics/resources/_stock.py +67 -0
  1013. skcomplex/models/engineering/__init__.py +1 -0
  1014. skcomplex/models/engineering/circuits/__init__.py +23 -0
  1015. skcomplex/models/engineering/circuits/_chua_circuit.py +48 -0
  1016. skcomplex/models/engineering/circuits/_circuit.py +47 -0
  1017. skcomplex/models/engineering/circuits/_circuits.py +387 -0
  1018. skcomplex/models/engineering/circuits/_harvesters.py +150 -0
  1019. skcomplex/models/engineering/circuits/_kicked_circuit.py +43 -0
  1020. skcomplex/models/engineering/circuits/_memristor_circuit.py +48 -0
  1021. skcomplex/models/engineering/circuits/_mixed_mode_chua_circuit.py +54 -0
  1022. skcomplex/models/engineering/circuits/_multiscroll_chua_circuit.py +58 -0
  1023. skcomplex/models/engineering/circuits/_tunnel_diode_circuit.py +45 -0
  1024. skcomplex/models/engineering/common/__init__.py +6 -0
  1025. skcomplex/models/engineering/common/mechanics/__init__.py +7 -0
  1026. skcomplex/models/engineering/common/mechanics/_spring_damper.py +121 -0
  1027. skcomplex/models/engineering/control/__init__.py +23 -0
  1028. skcomplex/models/engineering/control/_cart_pendulum.py +119 -0
  1029. skcomplex/models/engineering/control/_control.py +266 -0
  1030. skcomplex/models/engineering/control/_controlled_process.py +72 -0
  1031. skcomplex/models/engineering/control/_driven_oscillator.py +79 -0
  1032. skcomplex/models/engineering/control/_integrator.py +39 -0
  1033. skcomplex/models/engineering/control/_pid.py +106 -0
  1034. skcomplex/models/engineering/control/_regulation.py +170 -0
  1035. skcomplex/models/engineering/control/_room.py +51 -0
  1036. skcomplex/models/engineering/control/_satellite.py +56 -0
  1037. skcomplex/models/engineering/control/_state_feedback.py +82 -0
  1038. skcomplex/models/engineering/control/_swinging_pendulum.py +60 -0
  1039. skcomplex/models/engineering/power_systems/__init__.py +11 -0
  1040. skcomplex/models/engineering/power_systems/_electromechanics.py +224 -0
  1041. skcomplex/models/engineering/power_systems/_faraday_disk.py +93 -0
  1042. skcomplex/models/engineering/power_systems/_grid_node.py +39 -0
  1043. skcomplex/models/engineering/power_systems/_grids.py +89 -0
  1044. skcomplex/models/engineering/power_systems/_rail_segment.py +80 -0
  1045. skcomplex/models/engineering/power_systems/_regenerative_car.py +55 -0
  1046. skcomplex/models/engineering/power_systems/_transmission_line.py +48 -0
  1047. skcomplex/models/engineering/processes/__init__.py +13 -0
  1048. skcomplex/models/engineering/processes/_irrigation_scheme.py +112 -0
  1049. skcomplex/models/engineering/processes/_processes.py +115 -0
  1050. skcomplex/models/engineering/processes/_relief_pipeline.py +79 -0
  1051. skcomplex/models/engineering/processes/_rice_mill.py +112 -0
  1052. skcomplex/models/engineering/processes/_stage.py +34 -0
  1053. skcomplex/models/engineering/processes/_systems.py +316 -0
  1054. skcomplex/models/engineering/processes/_tub.py +42 -0
  1055. skcomplex/models/engineering/processes/_waste_system.py +101 -0
  1056. skcomplex/models/engineering/robotics/__init__.py +12 -0
  1057. skcomplex/models/engineering/robotics/_light_sensitive_robot.py +125 -0
  1058. skcomplex/models/engineering/robotics/_robots.py +177 -0
  1059. skcomplex/models/engineering/robotics/_swarm_robot.py +211 -0
  1060. skcomplex/models/engineering/robotics/_swarm_robot_view.py +23 -0
  1061. skcomplex/models/engineering/traffic/__init__.py +43 -0
  1062. skcomplex/models/engineering/traffic/_arrival.py +117 -0
  1063. skcomplex/models/engineering/traffic/_cab.py +170 -0
  1064. skcomplex/models/engineering/traffic/_cab_view.py +21 -0
  1065. skcomplex/models/engineering/traffic/_car.py +31 -0
  1066. skcomplex/models/engineering/traffic/_car_following.py +245 -0
  1067. skcomplex/models/engineering/traffic/_careless_braking.py +87 -0
  1068. skcomplex/models/engineering/traffic/_continuum.py +429 -0
  1069. skcomplex/models/engineering/traffic/_delayed_following.py +65 -0
  1070. skcomplex/models/engineering/traffic/_driver.py +140 -0
  1071. skcomplex/models/engineering/traffic/_driver_view.py +18 -0
  1072. skcomplex/models/engineering/traffic/_drivers.py +133 -0
  1073. skcomplex/models/engineering/traffic/_gas_kinetic_traffic.py +96 -0
  1074. skcomplex/models/engineering/traffic/_intelligent_driver.py +90 -0
  1075. skcomplex/models/engineering/traffic/_kerner_konhauser.py +42 -0
  1076. skcomplex/models/engineering/traffic/_langevin.py +170 -0
  1077. skcomplex/models/engineering/traffic/_langevin_driving.py +95 -0
  1078. skcomplex/models/engineering/traffic/_lead_car.py +40 -0
  1079. skcomplex/models/engineering/traffic/_lighthill_whitham_richards.py +30 -0
  1080. skcomplex/models/engineering/traffic/_motorist.py +118 -0
  1081. skcomplex/models/engineering/traffic/_motorist_view.py +18 -0
  1082. skcomplex/models/engineering/traffic/_optimal_velocity.py +72 -0
  1083. skcomplex/models/engineering/traffic/_payne.py +38 -0
  1084. skcomplex/models/engineering/traffic/_rider.py +72 -0
  1085. skcomplex/models/engineering/traffic/_rider_view.py +16 -0
  1086. skcomplex/models/engineering/traffic/_ridesharing.py +179 -0
  1087. skcomplex/models/engineering/traffic/_traffic.py +143 -0
  1088. skcomplex/models/engineering/traffic/_traffic_moments.py +57 -0
  1089. skcomplex/models/mathematics/__init__.py +1 -0
  1090. skcomplex/models/mathematics/common/__init__.py +3 -0
  1091. skcomplex/models/mathematics/common/flows/__init__.py +7 -0
  1092. skcomplex/models/mathematics/common/flows/_lorenz.py +90 -0
  1093. skcomplex/models/mathematics/dynamical_systems/__init__.py +90 -0
  1094. skcomplex/models/mathematics/dynamical_systems/_baker_map.py +59 -0
  1095. skcomplex/models/mathematics/dynamical_systems/_blow_up.py +64 -0
  1096. skcomplex/models/mathematics/dynamical_systems/_cat_map.py +44 -0
  1097. skcomplex/models/mathematics/dynamical_systems/_chaotic_ensembles.py +186 -0
  1098. skcomplex/models/mathematics/dynamical_systems/_circle_map.py +49 -0
  1099. skcomplex/models/mathematics/dynamical_systems/_cubic_walk.py +72 -0
  1100. skcomplex/models/mathematics/dynamical_systems/_cusp.py +64 -0
  1101. skcomplex/models/mathematics/dynamical_systems/_doubling_map.py +65 -0
  1102. skcomplex/models/mathematics/dynamical_systems/_driven_flows.py +158 -0
  1103. skcomplex/models/mathematics/dynamical_systems/_flows.py +179 -0
  1104. skcomplex/models/mathematics/dynamical_systems/_henon_map.py +54 -0
  1105. skcomplex/models/mathematics/dynamical_systems/_hopf.py +77 -0
  1106. skcomplex/models/mathematics/dynamical_systems/_intermittency_map.py +44 -0
  1107. skcomplex/models/mathematics/dynamical_systems/_jerk.py +72 -0
  1108. skcomplex/models/mathematics/dynamical_systems/_koopman.py +118 -0
  1109. skcomplex/models/mathematics/dynamical_systems/_logistic_map.py +44 -0
  1110. skcomplex/models/mathematics/dynamical_systems/_maps.py +465 -0
  1111. skcomplex/models/mathematics/dynamical_systems/_newton_map.py +44 -0
  1112. skcomplex/models/mathematics/dynamical_systems/_normal_forms.py +154 -0
  1113. skcomplex/models/mathematics/dynamical_systems/_rossler.py +83 -0
  1114. skcomplex/models/mathematics/dynamical_systems/_saddle_node.py +59 -0
  1115. skcomplex/models/mathematics/dynamical_systems/_skew_tent_map.py +63 -0
  1116. skcomplex/models/mathematics/dynamical_systems/_standard_map.py +52 -0
  1117. skcomplex/models/mathematics/dynamical_systems/_subcritical_forms.py +160 -0
  1118. skcomplex/models/mathematics/dynamical_systems/_takens_bogdanov.py +74 -0
  1119. skcomplex/models/mathematics/dynamical_systems/_tent_map.py +44 -0
  1120. skcomplex/models/mathematics/dynamical_systems/_towel_map.py +59 -0
  1121. skcomplex/models/mathematics/fractals/__init__.py +61 -0
  1122. skcomplex/models/mathematics/fractals/_affine_spec.py +100 -0
  1123. skcomplex/models/mathematics/fractals/_cantor_element.py +92 -0
  1124. skcomplex/models/mathematics/fractals/_chaos_game.py +140 -0
  1125. skcomplex/models/mathematics/fractals/_geometry_spec.py +84 -0
  1126. skcomplex/models/mathematics/fractals/_geometry_visual.py +190 -0
  1127. skcomplex/models/mathematics/fractals/_group_spec.py +24 -0
  1128. skcomplex/models/mathematics/fractals/_koch_element.py +43 -0
  1129. skcomplex/models/mathematics/fractals/_module_spec.py +47 -0
  1130. skcomplex/models/mathematics/fractals/_patch_element.py +89 -0
  1131. skcomplex/models/mathematics/fractals/_patch_kernel.py +200 -0
  1132. skcomplex/models/mathematics/fractals/_patch_structure_spec.py +108 -0
  1133. skcomplex/models/mathematics/fractals/_production_law.py +105 -0
  1134. skcomplex/models/mathematics/fractals/_prototile_spec.py +53 -0
  1135. skcomplex/models/mathematics/fractals/_quadratic.py +191 -0
  1136. skcomplex/models/mathematics/fractals/_random_affine_map.py +100 -0
  1137. skcomplex/models/mathematics/fractals/_rewriting_compiler.py +300 -0
  1138. skcomplex/models/mathematics/fractals/_rewriting_error.py +10 -0
  1139. skcomplex/models/mathematics/fractals/_rewriting_loops.py +180 -0
  1140. skcomplex/models/mathematics/fractals/_rewriting_problem_spec.py +30 -0
  1141. skcomplex/models/mathematics/fractals/_rewriting_solver.py +125 -0
  1142. skcomplex/models/mathematics/fractals/_sierpinski_element.py +110 -0
  1143. skcomplex/models/mathematics/fractals/_substitution.py +130 -0
  1144. skcomplex/models/mathematics/fractals/_substitution_law.py +76 -0
  1145. skcomplex/models/mathematics/fractals/_successor_spec.py +23 -0
  1146. skcomplex/models/mathematics/fractals/_word_element.py +94 -0
  1147. skcomplex/models/mathematics/fractals/_word_kernel.py +526 -0
  1148. skcomplex/models/mathematics/fractals/_word_structure_spec.py +110 -0
  1149. skcomplex/models/mathematics/fractals/_words.py +38 -0
  1150. skcomplex/models/mathematics/fractals/types.py +12 -0
  1151. skcomplex/models/mathematics/fractional_dynamics/__init__.py +29 -0
  1152. skcomplex/models/mathematics/fractional_dynamics/_fractional.py +338 -0
  1153. skcomplex/models/mathematics/fractional_dynamics/_oscillator.py +71 -0
  1154. skcomplex/models/mathematics/fractional_dynamics/_relaxation.py +59 -0
  1155. skcomplex/models/mathematics/fractional_dynamics/_van_der_pol.py +66 -0
  1156. skcomplex/models/mathematics/networks/__init__.py +61 -0
  1157. skcomplex/models/mathematics/networks/_copying_vertex.py +50 -0
  1158. skcomplex/models/mathematics/networks/_ensemble_node.py +48 -0
  1159. skcomplex/models/mathematics/networks/_ensembles.py +195 -0
  1160. skcomplex/models/mathematics/networks/_failing.py +58 -0
  1161. skcomplex/models/mathematics/networks/_giant_component.py +52 -0
  1162. skcomplex/models/mathematics/networks/_growth.py +223 -0
  1163. skcomplex/models/mathematics/networks/_hypergraphs.py +131 -0
  1164. skcomplex/models/mathematics/networks/_link.py +21 -0
  1165. skcomplex/models/mathematics/networks/_network_measures.py +59 -0
  1166. skcomplex/models/mathematics/networks/_network_node.py +86 -0
  1167. skcomplex/models/mathematics/networks/_network_walker.py +49 -0
  1168. skcomplex/models/mathematics/networks/_network_walker_view.py +12 -0
  1169. skcomplex/models/mathematics/networks/_node_content.py +47 -0
  1170. skcomplex/models/mathematics/networks/_node_rank.py +57 -0
  1171. skcomplex/models/mathematics/networks/_processes.py +148 -0
  1172. skcomplex/models/mathematics/networks/_regulated_link.py +47 -0
  1173. skcomplex/models/mathematics/networks/_regulated_node.py +43 -0
  1174. skcomplex/models/mathematics/networks/_simplex.py +46 -0
  1175. skcomplex/models/mathematics/networks/_simplex_ageing.py +46 -0
  1176. skcomplex/models/mathematics/networks/_size_biased_move.py +44 -0
  1177. skcomplex/models/mathematics/networks/_structure.py +170 -0
  1178. skcomplex/models/mathematics/networks/_triad_vertex.py +64 -0
  1179. skcomplex/models/mathematics/networks/_triadic.py +114 -0
  1180. skcomplex/models/mathematics/networks/_triadic_regulation.py +65 -0
  1181. skcomplex/models/mathematics/networks/_vertex.py +52 -0
  1182. skcomplex/models/mathematics/networks/_walker_density.py +51 -0
  1183. skcomplex/models/mathematics/stochastic_processes/__init__.py +62 -0
  1184. skcomplex/models/mathematics/stochastic_processes/_ageing_walker.py +68 -0
  1185. skcomplex/models/mathematics/stochastic_processes/_ageing_walker_view.py +15 -0
  1186. skcomplex/models/mathematics/stochastic_processes/_bernoulli_trial.py +61 -0
  1187. skcomplex/models/mathematics/stochastic_processes/_bernoulli_trial_view.py +14 -0
  1188. skcomplex/models/mathematics/stochastic_processes/_branching.py +103 -0
  1189. skcomplex/models/mathematics/stochastic_processes/_counting.py +88 -0
  1190. skcomplex/models/mathematics/stochastic_processes/_fragment.py +91 -0
  1191. skcomplex/models/mathematics/stochastic_processes/_fragment_view.py +13 -0
  1192. skcomplex/models/mathematics/stochastic_processes/_hidden_markov_source.py +46 -0
  1193. skcomplex/models/mathematics/stochastic_processes/_individual_view.py +13 -0
  1194. skcomplex/models/mathematics/stochastic_processes/_intermittency.py +115 -0
  1195. skcomplex/models/mathematics/stochastic_processes/_markov_source.py +41 -0
  1196. skcomplex/models/mathematics/stochastic_processes/_memory_walker.py +57 -0
  1197. skcomplex/models/mathematics/stochastic_processes/_persistent_walker.py +52 -0
  1198. skcomplex/models/mathematics/stochastic_processes/_poisson_counter.py +47 -0
  1199. skcomplex/models/mathematics/stochastic_processes/_queues.py +117 -0
  1200. skcomplex/models/mathematics/stochastic_processes/_random_walker.py +52 -0
  1201. skcomplex/models/mathematics/stochastic_processes/_reducing.py +104 -0
  1202. skcomplex/models/mathematics/stochastic_processes/_reducing_ball.py +63 -0
  1203. skcomplex/models/mathematics/stochastic_processes/_reducing_ball_view.py +14 -0
  1204. skcomplex/models/mathematics/stochastic_processes/_reducing_jump.py +44 -0
  1205. skcomplex/models/mathematics/stochastic_processes/_sources.py +90 -0
  1206. skcomplex/models/mathematics/stochastic_processes/_urns.py +112 -0
  1207. skcomplex/models/mathematics/stochastic_processes/_walks.py +280 -0
  1208. skcomplex/models/mathematics/stochastic_processes/_weakening_particle.py +57 -0
  1209. skcomplex/models/mathematics/stochastic_processes/types.py +8 -0
  1210. skcomplex/models/physics/__init__.py +1 -0
  1211. skcomplex/models/physics/active_matter/__init__.py +95 -0
  1212. skcomplex/models/physics/active_matter/_active_particle.py +88 -0
  1213. skcomplex/models/physics/active_matter/_alignment.py +192 -0
  1214. skcomplex/models/physics/active_matter/_angular_alignment.py +98 -0
  1215. skcomplex/models/physics/active_matter/_angular_diffusion.py +67 -0
  1216. skcomplex/models/physics/active_matter/_binary_collisions.py +126 -0
  1217. skcomplex/models/physics/active_matter/_chemotaxis.py +173 -0
  1218. skcomplex/models/physics/active_matter/_cohesive_particle.py +132 -0
  1219. skcomplex/models/physics/active_matter/_collective.py +327 -0
  1220. skcomplex/models/physics/active_matter/_collisions.py +127 -0
  1221. skcomplex/models/physics/active_matter/_contractile_gel_site.py +81 -0
  1222. skcomplex/models/physics/active_matter/_cucker_smale_alignment.py +89 -0
  1223. skcomplex/models/physics/active_matter/_depot_particle.py +103 -0
  1224. skcomplex/models/physics/active_matter/_flocker.py +46 -0
  1225. skcomplex/models/physics/active_matter/_flocker_view.py +20 -0
  1226. skcomplex/models/physics/active_matter/_flocks.py +258 -0
  1227. skcomplex/models/physics/active_matter/_gels.py +141 -0
  1228. skcomplex/models/physics/active_matter/_heading_alignment.py +73 -0
  1229. skcomplex/models/physics/active_matter/_kinetic_flocks.py +111 -0
  1230. skcomplex/models/physics/active_matter/_landau_de_gennes_energy.py +107 -0
  1231. skcomplex/models/physics/active_matter/_model_b.py +170 -0
  1232. skcomplex/models/physics/active_matter/_nematic_density_site.py +78 -0
  1233. skcomplex/models/physics/active_matter/_nematic_gel_site.py +115 -0
  1234. skcomplex/models/physics/active_matter/_nematic_particle.py +61 -0
  1235. skcomplex/models/physics/active_matter/_nematics.py +323 -0
  1236. skcomplex/models/physics/active_matter/_nonreciprocal.py +214 -0
  1237. skcomplex/models/physics/active_matter/_ornstein_uhlenbeck_particle.py +87 -0
  1238. skcomplex/models/physics/active_matter/_particles.py +323 -0
  1239. skcomplex/models/physics/active_matter/_phoretic_attraction.py +80 -0
  1240. skcomplex/models/physics/active_matter/_polar_fluid.py +119 -0
  1241. skcomplex/models/physics/active_matter/_polar_gel_site.py +120 -0
  1242. skcomplex/models/physics/active_matter/_propulsion_step.py +64 -0
  1243. skcomplex/models/physics/active_matter/_self_propulsion.py +73 -0
  1244. skcomplex/models/physics/active_matter/_tumbler.py +100 -0
  1245. skcomplex/models/physics/active_matter/_tumbler_view.py +23 -0
  1246. skcomplex/models/physics/active_matter/_vicsek_particle.py +61 -0
  1247. skcomplex/models/physics/celestial_mechanics/__init__.py +19 -0
  1248. skcomplex/models/physics/celestial_mechanics/_dipoles.py +160 -0
  1249. skcomplex/models/physics/celestial_mechanics/_kepler_body.py +76 -0
  1250. skcomplex/models/physics/celestial_mechanics/_orbits.py +332 -0
  1251. skcomplex/models/physics/celestial_mechanics/_rotating_frame_body.py +72 -0
  1252. skcomplex/models/physics/celestial_mechanics/_sitnikov_body.py +54 -0
  1253. skcomplex/models/physics/celestial_mechanics/types.py +6 -0
  1254. skcomplex/models/physics/climate/__init__.py +60 -0
  1255. skcomplex/models/physics/climate/_carbon_cycle.py +169 -0
  1256. skcomplex/models/physics/climate/_climate_anomaly.py +55 -0
  1257. skcomplex/models/physics/climate/_daisyworld.py +158 -0
  1258. skcomplex/models/physics/climate/_delayed_oscillator.py +68 -0
  1259. skcomplex/models/physics/climate/_early_warning.py +102 -0
  1260. skcomplex/models/physics/climate/_energy_balance.py +207 -0
  1261. skcomplex/models/physics/climate/_geodynamo.py +86 -0
  1262. skcomplex/models/physics/climate/_ice_ages.py +179 -0
  1263. skcomplex/models/physics/climate/_ice_albedo_climate.py +100 -0
  1264. skcomplex/models/physics/climate/_latitude_band.py +156 -0
  1265. skcomplex/models/physics/climate/_lorenz84.py +91 -0
  1266. skcomplex/models/physics/climate/_lorenz96.py +67 -0
  1267. skcomplex/models/physics/climate/_low_order.py +162 -0
  1268. skcomplex/models/physics/climate/_net_energy.py +210 -0
  1269. skcomplex/models/physics/climate/_ramped_fold.py +92 -0
  1270. skcomplex/models/physics/climate/_saltzman_maasch.py +123 -0
  1271. skcomplex/models/physics/climate/_soil.py +116 -0
  1272. skcomplex/models/physics/climate/_stochastic_energy_balance.py +124 -0
  1273. skcomplex/models/physics/climate/_tipping.py +141 -0
  1274. skcomplex/models/physics/climate/_tipping_types.py +159 -0
  1275. skcomplex/models/physics/climate/_van_der_pol_ice_ages.py +101 -0
  1276. skcomplex/models/physics/climate/_variability.py +103 -0
  1277. skcomplex/models/physics/common/__init__.py +6 -0
  1278. skcomplex/models/physics/common/fields/__init__.py +14 -0
  1279. skcomplex/models/physics/common/fields/_landau_energy.py +76 -0
  1280. skcomplex/models/physics/common/fields/_phase_field.py +43 -0
  1281. skcomplex/models/physics/common/fields/_swift_hohenberg_energy.py +74 -0
  1282. skcomplex/models/physics/common/fields/_transports.py +119 -0
  1283. skcomplex/models/physics/common/mechanics/__init__.py +5 -0
  1284. skcomplex/models/physics/common/mechanics/_reflection.py +139 -0
  1285. skcomplex/models/physics/common/oscillators/__init__.py +13 -0
  1286. skcomplex/models/physics/common/oscillators/_kuramoto_coupling.py +140 -0
  1287. skcomplex/models/physics/common/oscillators/_phase_oscillator.py +68 -0
  1288. skcomplex/models/physics/common/oscillators/_sited_oscillator.py +55 -0
  1289. skcomplex/models/physics/common/oscillators/_stuart_landau.py +106 -0
  1290. skcomplex/models/physics/common/particles/__init__.py +28 -0
  1291. skcomplex/models/physics/common/particles/_constant_force.py +65 -0
  1292. skcomplex/models/physics/common/particles/_damping.py +72 -0
  1293. skcomplex/models/physics/common/particles/_gravity.py +74 -0
  1294. skcomplex/models/physics/common/particles/_harmonic_potential.py +77 -0
  1295. skcomplex/models/physics/common/particles/_lammps.py +47 -0
  1296. skcomplex/models/physics/common/particles/_langevin_thermostat.py +103 -0
  1297. skcomplex/models/physics/common/particles/_lennard_jones.py +87 -0
  1298. skcomplex/models/physics/common/particles/_mass_point.py +57 -0
  1299. skcomplex/models/physics/common/particles/_potential_energy.py +56 -0
  1300. skcomplex/models/physics/common/particles/_soft_sphere.py +82 -0
  1301. skcomplex/models/physics/common/particles/_spring.py +78 -0
  1302. skcomplex/models/physics/common/particles/_utils.py +25 -0
  1303. skcomplex/models/physics/common/quantum/__init__.py +18 -0
  1304. skcomplex/models/physics/common/quantum/_mode.py +46 -0
  1305. skcomplex/models/physics/common/quantum/_quantum.py +127 -0
  1306. skcomplex/models/physics/common/quantum/_qubit.py +61 -0
  1307. skcomplex/models/physics/common/quantum/_site.py +49 -0
  1308. skcomplex/models/physics/common/quantum/_spin.py +92 -0
  1309. skcomplex/models/physics/common/spins/__init__.py +15 -0
  1310. skcomplex/models/physics/common/spins/_ising_sampling.py +75 -0
  1311. skcomplex/models/physics/common/spins/_potts_sampling.py +73 -0
  1312. skcomplex/models/physics/common/spins/_spin_sampling.py +100 -0
  1313. skcomplex/models/physics/common/spins/_thermal_sampling.py +105 -0
  1314. skcomplex/models/physics/common/spins/_xy_sampling.py +67 -0
  1315. skcomplex/models/physics/cosmology/__init__.py +8 -0
  1316. skcomplex/models/physics/cosmology/_expansion.py +148 -0
  1317. skcomplex/models/physics/criticality/__init__.py +29 -0
  1318. skcomplex/models/physics/criticality/_absorbing.py +210 -0
  1319. skcomplex/models/physics/criticality/_avalanche.py +69 -0
  1320. skcomplex/models/physics/criticality/_crackling_noise.py +129 -0
  1321. skcomplex/models/physics/criticality/_criticality.py +235 -0
  1322. skcomplex/models/physics/criticality/_evolutionary_learning.py +231 -0
  1323. skcomplex/models/physics/criticality/_fire.py +70 -0
  1324. skcomplex/models/physics/criticality/_forest.py +55 -0
  1325. skcomplex/models/physics/criticality/_learning.py +175 -0
  1326. skcomplex/models/physics/criticality/_sandpile_cell.py +47 -0
  1327. skcomplex/models/physics/fluids/__init__.py +49 -0
  1328. skcomplex/models/physics/fluids/_bhatnagar_gross_krook.py +54 -0
  1329. skcomplex/models/physics/fluids/_boussinesq.py +62 -0
  1330. skcomplex/models/physics/fluids/_burgers.py +39 -0
  1331. skcomplex/models/physics/fluids/_carleman_gas.py +61 -0
  1332. skcomplex/models/physics/fluids/_flows.py +436 -0
  1333. skcomplex/models/physics/fluids/_kinetic_equations.py +327 -0
  1334. skcomplex/models/physics/fluids/_kinetics.py +147 -0
  1335. skcomplex/models/physics/fluids/_kuramoto_sivashinsky.py +41 -0
  1336. skcomplex/models/physics/fluids/_lattice_gases.py +217 -0
  1337. skcomplex/models/physics/fluids/_marangoni.py +136 -0
  1338. skcomplex/models/physics/fluids/_shallow_water.py +55 -0
  1339. skcomplex/models/physics/fluids/_vorticity.py +56 -0
  1340. skcomplex/models/physics/fluids/_wave_number.py +50 -0
  1341. skcomplex/models/physics/heat/__init__.py +13 -0
  1342. skcomplex/models/physics/heat/_cooling.py +96 -0
  1343. skcomplex/models/physics/heat/_heat.py +182 -0
  1344. skcomplex/models/physics/mechanics/__init__.py +93 -0
  1345. skcomplex/models/physics/mechanics/_ballistic_pendulum.py +80 -0
  1346. skcomplex/models/physics/mechanics/_bouncing_ball.py +51 -0
  1347. skcomplex/models/physics/mechanics/_cart_pendulum.py +92 -0
  1348. skcomplex/models/physics/mechanics/_cart_pendulum_interaction.py +57 -0
  1349. skcomplex/models/physics/mechanics/_clock_pendulum.py +94 -0
  1350. skcomplex/models/physics/mechanics/_clock_pendulum_interaction.py +60 -0
  1351. skcomplex/models/physics/mechanics/_disc_billiard.py +90 -0
  1352. skcomplex/models/physics/mechanics/_double_pendulum.py +95 -0
  1353. skcomplex/models/physics/mechanics/_double_pendulum_interaction.py +53 -0
  1354. skcomplex/models/physics/mechanics/_elastic_collision.py +78 -0
  1355. skcomplex/models/physics/mechanics/_gyroscope.py +105 -0
  1356. skcomplex/models/physics/mechanics/_gyroscope_interaction.py +57 -0
  1357. skcomplex/models/physics/mechanics/_hanging_ball.py +65 -0
  1358. skcomplex/models/physics/mechanics/_magnet.py +70 -0
  1359. skcomplex/models/physics/mechanics/_mechanics.py +426 -0
  1360. skcomplex/models/physics/mechanics/_parametric_pendulum.py +75 -0
  1361. skcomplex/models/physics/mechanics/_parametric_pendulum_interaction.py +56 -0
  1362. skcomplex/models/physics/mechanics/_pendulum.py +73 -0
  1363. skcomplex/models/physics/mechanics/_pendulum_interaction.py +52 -0
  1364. skcomplex/models/physics/mechanics/_pendulum_spring.py +68 -0
  1365. skcomplex/models/physics/mechanics/_pendulums.py +547 -0
  1366. skcomplex/models/physics/mechanics/_rotating_ball.py +66 -0
  1367. skcomplex/models/physics/mechanics/_rotating_swing.py +100 -0
  1368. skcomplex/models/physics/mechanics/_rotating_swing_interaction.py +70 -0
  1369. skcomplex/models/physics/mechanics/_rotations.py +244 -0
  1370. skcomplex/models/physics/mechanics/_springs.py +176 -0
  1371. skcomplex/models/physics/mechanics/_support_spring.py +65 -0
  1372. skcomplex/models/physics/mechanics/_wells.py +102 -0
  1373. skcomplex/models/physics/nonlinear_oscillators/__init__.py +26 -0
  1374. skcomplex/models/physics/nonlinear_oscillators/_adler_phase.py +73 -0
  1375. skcomplex/models/physics/nonlinear_oscillators/_billiards.py +137 -0
  1376. skcomplex/models/physics/nonlinear_oscillators/_duffing.py +78 -0
  1377. skcomplex/models/physics/nonlinear_oscillators/_henon_heiles.py +57 -0
  1378. skcomplex/models/physics/nonlinear_oscillators/_mushroom_billiard.py +96 -0
  1379. skcomplex/models/physics/nonlinear_oscillators/_oscillators.py +313 -0
  1380. skcomplex/models/physics/nonlinear_oscillators/_sinai_billiard.py +101 -0
  1381. skcomplex/models/physics/nonlinear_oscillators/_van_der_pol.py +92 -0
  1382. skcomplex/models/physics/oceanography/__init__.py +12 -0
  1383. skcomplex/models/physics/oceanography/_gyres.py +145 -0
  1384. skcomplex/models/physics/oceanography/_quasi_geostrophic_site.py +66 -0
  1385. skcomplex/models/physics/oceanography/_thermohaline.py +133 -0
  1386. skcomplex/models/physics/pattern_formation/__init__.py +18 -0
  1387. skcomplex/models/physics/pattern_formation/_conserved.py +168 -0
  1388. skcomplex/models/physics/pattern_formation/_ginzburg_landau.py +83 -0
  1389. skcomplex/models/physics/pattern_formation/_ordering.py +183 -0
  1390. skcomplex/models/physics/pattern_formation/_pattern_field.py +37 -0
  1391. skcomplex/models/physics/pattern_formation/_patterns.py +135 -0
  1392. skcomplex/models/physics/seismology/__init__.py +11 -0
  1393. skcomplex/models/physics/seismology/_faults.py +118 -0
  1394. skcomplex/models/physics/seismology/_spring_blocks.py +175 -0
  1395. skcomplex/models/physics/soft_matter/__init__.py +76 -0
  1396. skcomplex/models/physics/soft_matter/_anomalous.py +331 -0
  1397. skcomplex/models/physics/soft_matter/_brownian.py +137 -0
  1398. skcomplex/models/physics/soft_matter/_brownian_particle.py +58 -0
  1399. skcomplex/models/physics/soft_matter/_colored_noise.py +137 -0
  1400. skcomplex/models/physics/soft_matter/_continuous_time_walker.py +62 -0
  1401. skcomplex/models/physics/soft_matter/_diffusion.py +418 -0
  1402. skcomplex/models/physics/soft_matter/_double_well.py +57 -0
  1403. skcomplex/models/physics/soft_matter/_flashing_sawtooth.py +82 -0
  1404. skcomplex/models/physics/soft_matter/_fractional_walker.py +54 -0
  1405. skcomplex/models/physics/soft_matter/_friction.py +214 -0
  1406. skcomplex/models/physics/soft_matter/_levy_flier.py +54 -0
  1407. skcomplex/models/physics/soft_matter/_levy_walker.py +67 -0
  1408. skcomplex/models/physics/soft_matter/_modulated_particle.py +76 -0
  1409. skcomplex/models/physics/soft_matter/_optical_trap.py +93 -0
  1410. skcomplex/models/physics/soft_matter/_ratchets.py +163 -0
  1411. skcomplex/models/physics/soft_matter/_scaled_walker.py +57 -0
  1412. skcomplex/models/physics/soft_matter/_speckle_field.py +81 -0
  1413. skcomplex/models/physics/soft_matter/_thermal_noise.py +52 -0
  1414. skcomplex/models/physics/soft_matter/_tilted_washboard.py +70 -0
  1415. skcomplex/models/physics/soft_matter/_transient_walker.py +61 -0
  1416. skcomplex/models/physics/soft_matter/_traps.py +166 -0
  1417. skcomplex/models/physics/soft_matter/_wall_particle.py +72 -0
  1418. skcomplex/models/physics/statistical_mechanics/__init__.py +114 -0
  1419. skcomplex/models/physics/statistical_mechanics/_absorbing_processes.py +156 -0
  1420. skcomplex/models/physics/statistical_mechanics/_boltzmann_average.py +44 -0
  1421. skcomplex/models/physics/statistical_mechanics/_boltzmann_sum.py +83 -0
  1422. skcomplex/models/physics/statistical_mechanics/_bond_sampling.py +46 -0
  1423. skcomplex/models/physics/statistical_mechanics/_bond_spin.py +76 -0
  1424. skcomplex/models/physics/statistical_mechanics/_contact_site.py +85 -0
  1425. skcomplex/models/physics/statistical_mechanics/_dephasing.py +59 -0
  1426. skcomplex/models/physics/statistical_mechanics/_disk.py +36 -0
  1427. skcomplex/models/physics/statistical_mechanics/_driven_particles.py +250 -0
  1428. skcomplex/models/physics/statistical_mechanics/_energy_level.py +30 -0
  1429. skcomplex/models/physics/statistical_mechanics/_exclusion_hops.py +76 -0
  1430. skcomplex/models/physics/statistical_mechanics/_exclusion_site.py +61 -0
  1431. skcomplex/models/physics/statistical_mechanics/_fully_connected_spins.py +232 -0
  1432. skcomplex/models/physics/statistical_mechanics/_gases.py +156 -0
  1433. skcomplex/models/physics/statistical_mechanics/_graph_spins.py +93 -0
  1434. skcomplex/models/physics/statistical_mechanics/_ising_spin.py +63 -0
  1435. skcomplex/models/physics/statistical_mechanics/_kinetic_temperature.py +66 -0
  1436. skcomplex/models/physics/statistical_mechanics/_master_equations.py +171 -0
  1437. skcomplex/models/physics/statistical_mechanics/_mattis_spin.py +79 -0
  1438. skcomplex/models/physics/statistical_mechanics/_maxwell_boltzmann.py +96 -0
  1439. skcomplex/models/physics/statistical_mechanics/_microstate.py +102 -0
  1440. skcomplex/models/physics/statistical_mechanics/_order_parameter.py +90 -0
  1441. skcomplex/models/physics/statistical_mechanics/_particle_site.py +41 -0
  1442. skcomplex/models/physics/statistical_mechanics/_percolation.py +60 -0
  1443. skcomplex/models/physics/statistical_mechanics/_percolation_site.py +73 -0
  1444. skcomplex/models/physics/statistical_mechanics/_potts_spin.py +58 -0
  1445. skcomplex/models/physics/statistical_mechanics/_processes.py +355 -0
  1446. skcomplex/models/physics/statistical_mechanics/_q2r_spin.py +51 -0
  1447. skcomplex/models/physics/statistical_mechanics/_quantum_spins.py +153 -0
  1448. skcomplex/models/physics/statistical_mechanics/_random_energy.py +68 -0
  1449. skcomplex/models/physics/statistical_mechanics/_reservoir.py +81 -0
  1450. skcomplex/models/physics/statistical_mechanics/_spin_glasses.py +203 -0
  1451. skcomplex/models/physics/statistical_mechanics/_spins.py +200 -0
  1452. skcomplex/models/physics/statistical_mechanics/_susceptibility.py +112 -0
  1453. skcomplex/models/physics/statistical_mechanics/_traps.py +135 -0
  1454. skcomplex/models/physics/statistical_mechanics/_tree_node.py +48 -0
  1455. skcomplex/models/physics/statistical_mechanics/_urns.py +107 -0
  1456. skcomplex/models/physics/statistical_mechanics/_walker.py +81 -0
  1457. skcomplex/models/physics/statistical_mechanics/_walker_view.py +20 -0
  1458. skcomplex/models/physics/statistical_mechanics/_xxz_exchange.py +67 -0
  1459. skcomplex/models/physics/statistical_mechanics/_xy_spin.py +58 -0
  1460. skcomplex/models/physics/statistical_mechanics/_zeeman_field.py +56 -0
  1461. skcomplex/models/physics/statistical_mechanics/_zero_range_hop.py +86 -0
  1462. skcomplex/models/physics/statistical_mechanics/_zero_range_hops.py +81 -0
  1463. skcomplex/models/physics/statistical_mechanics/_zone.py +78 -0
  1464. skcomplex/models/physics/synchronization/__init__.py +64 -0
  1465. skcomplex/models/physics/synchronization/_aggregate_averaging.py +63 -0
  1466. skcomplex/models/physics/synchronization/_amplitude_death.py +278 -0
  1467. skcomplex/models/physics/synchronization/_chaos.py +152 -0
  1468. skcomplex/models/physics/synchronization/_diffusive_coupling.py +69 -0
  1469. skcomplex/models/physics/synchronization/_edge_coupling.py +50 -0
  1470. skcomplex/models/physics/synchronization/_hypergraphs.py +166 -0
  1471. skcomplex/models/physics/synchronization/_integrate_and_fire_oscillator.py +80 -0
  1472. skcomplex/models/physics/synchronization/_kuramoto.py +423 -0
  1473. skcomplex/models/physics/synchronization/_link.py +46 -0
  1474. skcomplex/models/physics/synchronization/_logistic_coupling.py +78 -0
  1475. skcomplex/models/physics/synchronization/_logistic_node.py +59 -0
  1476. skcomplex/models/physics/synchronization/_logistic_unit.py +43 -0
  1477. skcomplex/models/physics/synchronization/_networks.py +184 -0
  1478. skcomplex/models/physics/synchronization/_pulses.py +138 -0
  1479. skcomplex/models/physics/synchronization/_rossler_oscillator.py +95 -0
  1480. skcomplex/models/physics/synchronization/_swarmalator.py +48 -0
  1481. skcomplex/models/physics/synchronization/_swarmalators.py +182 -0
  1482. skcomplex/models/physics/synchronization/_utils.py +29 -0
  1483. skcomplex/models/physics/synchronization/_winfree_mean_field.py +62 -0
  1484. skcomplex/models/physics/waves/__init__.py +23 -0
  1485. skcomplex/models/physics/waves/_charged.py +203 -0
  1486. skcomplex/models/physics/waves/_driven_anchor.py +63 -0
  1487. skcomplex/models/physics/waves/_lattice_hamiltonian.py +60 -0
  1488. skcomplex/models/physics/waves/_position_dephasing.py +64 -0
  1489. skcomplex/models/physics/waves/_quantum.py +125 -0
  1490. skcomplex/models/physics/waves/_strings.py +169 -0
  1491. skcomplex/models/physics/waves/_wave_function.py +79 -0
  1492. skcomplex/models/physics/waves/_wave_string.py +52 -0
  1493. skcomplex/models/social/__init__.py +1 -0
  1494. skcomplex/models/social/cooperation/__init__.py +34 -0
  1495. skcomplex/models/social/cooperation/_contributor.py +62 -0
  1496. skcomplex/models/social/cooperation/_dilemma.py +56 -0
  1497. skcomplex/models/social/cooperation/_hyperedge_goods.py +54 -0
  1498. skcomplex/models/social/cooperation/_hypergraph_games.py +249 -0
  1499. skcomplex/models/social/cooperation/_prisoner.py +56 -0
  1500. skcomplex/models/social/cooperation/_prisoners_dilemma.py +126 -0
  1501. skcomplex/models/social/cooperation/_public_goods.py +54 -0
  1502. skcomplex/models/social/cooperation/_simplicial_dilemma.py +119 -0
  1503. skcomplex/models/social/cooperation/_spatial_games.py +159 -0
  1504. skcomplex/models/social/cooperation/_strategist.py +57 -0
  1505. skcomplex/models/social/cooperation/_strategist_view.py +14 -0
  1506. skcomplex/models/social/cooperation/_tournament.py +126 -0
  1507. skcomplex/models/social/cooperation/_tournaments.py +87 -0
  1508. skcomplex/models/social/crowds/__init__.py +46 -0
  1509. skcomplex/models/social/crowds/_criminal_contagion.py +108 -0
  1510. skcomplex/models/social/crowds/_criminality.py +223 -0
  1511. skcomplex/models/social/crowds/_crowding.py +115 -0
  1512. skcomplex/models/social/crowds/_deterrence.py +101 -0
  1513. skcomplex/models/social/crowds/_evacuation.py +196 -0
  1514. skcomplex/models/social/crowds/_guidance.py +69 -0
  1515. skcomplex/models/social/crowds/_motivation.py +67 -0
  1516. skcomplex/models/social/crowds/_pedestrians.py +85 -0
  1517. skcomplex/models/social/crowds/_recruitment.py +90 -0
  1518. skcomplex/models/social/crowds/_security_agents.py +48 -0
  1519. skcomplex/models/social/crowds/_social_repulsion.py +86 -0
  1520. skcomplex/models/social/crowds/_walking.py +186 -0
  1521. skcomplex/models/social/crowds/_walls.py +69 -0
  1522. skcomplex/models/social/language/__init__.py +13 -0
  1523. skcomplex/models/social/language/_language.py +30 -0
  1524. skcomplex/models/social/language/_least_effort.py +69 -0
  1525. skcomplex/models/social/language/_word.py +39 -0
  1526. skcomplex/models/social/language/_word_frequencies.py +48 -0
  1527. skcomplex/models/social/opinion_dynamics/__init__.py +142 -0
  1528. skcomplex/models/social/opinion_dynamics/_adopter.py +61 -0
  1529. skcomplex/models/social/opinion_dynamics/_adopter_view.py +14 -0
  1530. skcomplex/models/social/opinion_dynamics/_adoption.py +83 -0
  1531. skcomplex/models/social/opinion_dynamics/_axelrod.py +160 -0
  1532. skcomplex/models/social/opinion_dynamics/_believer.py +71 -0
  1533. skcomplex/models/social/opinion_dynamics/_believer_view.py +16 -0
  1534. skcomplex/models/social/opinion_dynamics/_bounded_confidence.py +126 -0
  1535. skcomplex/models/social/opinion_dynamics/_citizen.py +49 -0
  1536. skcomplex/models/social/opinion_dynamics/_citizen_view.py +12 -0
  1537. skcomplex/models/social/opinion_dynamics/_club_member.py +78 -0
  1538. skcomplex/models/social/opinion_dynamics/_coevolution.py +187 -0
  1539. skcomplex/models/social/opinion_dynamics/_coevolving_voter.py +63 -0
  1540. skcomplex/models/social/opinion_dynamics/_cognition.py +73 -0
  1541. skcomplex/models/social/opinion_dynamics/_complex_agent.py +58 -0
  1542. skcomplex/models/social/opinion_dynamics/_complex_agent_view.py +13 -0
  1543. skcomplex/models/social/opinion_dynamics/_confidence_coupling.py +76 -0
  1544. skcomplex/models/social/opinion_dynamics/_confident.py +50 -0
  1545. skcomplex/models/social/opinion_dynamics/_conventions.py +44 -0
  1546. skcomplex/models/social/opinion_dynamics/_conversations.py +116 -0
  1547. skcomplex/models/social/opinion_dynamics/_cultural_influence.py +93 -0
  1548. skcomplex/models/social/opinion_dynamics/_diffusion.py +205 -0
  1549. skcomplex/models/social/opinion_dynamics/_discussant.py +60 -0
  1550. skcomplex/models/social/opinion_dynamics/_discussant_view.py +14 -0
  1551. skcomplex/models/social/opinion_dynamics/_discussions.py +51 -0
  1552. skcomplex/models/social/opinion_dynamics/_encounters.py +48 -0
  1553. skcomplex/models/social/opinion_dynamics/_hypergraph_consensus.py +106 -0
  1554. skcomplex/models/social/opinion_dynamics/_influencee.py +70 -0
  1555. skcomplex/models/social/opinion_dynamics/_influencee_view.py +16 -0
  1556. skcomplex/models/social/opinion_dynamics/_kinetic_opinion.py +287 -0
  1557. skcomplex/models/social/opinion_dynamics/_majority_voter.py +43 -0
  1558. skcomplex/models/social/opinion_dynamics/_namer.py +53 -0
  1559. skcomplex/models/social/opinion_dynamics/_namer_view.py +13 -0
  1560. skcomplex/models/social/opinion_dynamics/_naming_games.py +68 -0
  1561. skcomplex/models/social/opinion_dynamics/_opinion.py +39 -0
  1562. skcomplex/models/social/opinion_dynamics/_persuader.py +52 -0
  1563. skcomplex/models/social/opinion_dynamics/_persuader_view.py +12 -0
  1564. skcomplex/models/social/opinion_dynamics/_persuasion.py +247 -0
  1565. skcomplex/models/social/opinion_dynamics/_random_pairs.py +53 -0
  1566. skcomplex/models/social/opinion_dynamics/_schedule.py +39 -0
  1567. skcomplex/models/social/opinion_dynamics/_separation.py +71 -0
  1568. skcomplex/models/social/opinion_dynamics/_social_impact.py +60 -0
  1569. skcomplex/models/social/opinion_dynamics/_standardization.py +212 -0
  1570. skcomplex/models/social/opinion_dynamics/_thinker.py +61 -0
  1571. skcomplex/models/social/opinion_dynamics/_thinker_view.py +15 -0
  1572. skcomplex/models/social/opinion_dynamics/_three_body_consensus.py +71 -0
  1573. skcomplex/models/social/opinion_dynamics/_tie.py +21 -0
  1574. skcomplex/models/social/opinion_dynamics/_variant_voter.py +67 -0
  1575. skcomplex/models/social/opinion_dynamics/_variant_voter_view.py +14 -0
  1576. skcomplex/models/social/opinion_dynamics/_variant_voting.py +63 -0
  1577. skcomplex/models/social/opinion_dynamics/_village.py +61 -0
  1578. skcomplex/models/social/opinion_dynamics/_village_view.py +14 -0
  1579. skcomplex/models/social/opinion_dynamics/_voter.py +49 -0
  1580. skcomplex/models/social/opinion_dynamics/_voter_imitation.py +48 -0
  1581. skcomplex/models/social/opinion_dynamics/_voter_view.py +12 -0
  1582. skcomplex/models/social/opinion_dynamics/_voters.py +197 -0
  1583. skcomplex/models/social/organizations/__init__.py +68 -0
  1584. skcomplex/models/social/organizations/_arms_race.py +34 -0
  1585. skcomplex/models/social/organizations/_burden.py +38 -0
  1586. skcomplex/models/social/organizations/_city_resident.py +41 -0
  1587. skcomplex/models/social/organizations/_contender_view.py +14 -0
  1588. skcomplex/models/social/organizations/_contest.py +32 -0
  1589. skcomplex/models/social/organizations/_daily_movements.py +144 -0
  1590. skcomplex/models/social/organizations/_eater.py +282 -0
  1591. skcomplex/models/social/organizations/_eater_view.py +24 -0
  1592. skcomplex/models/social/organizations/_employee.py +173 -0
  1593. skcomplex/models/social/organizations/_employee_view.py +35 -0
  1594. skcomplex/models/social/organizations/_employment.py +127 -0
  1595. skcomplex/models/social/organizations/_execution.py +79 -0
  1596. skcomplex/models/social/organizations/_gravity_contact.py +69 -0
  1597. skcomplex/models/social/organizations/_hierarchies.py +174 -0
  1598. skcomplex/models/social/organizations/_obesity.py +131 -0
  1599. skcomplex/models/social/organizations/_premises.py +75 -0
  1600. skcomplex/models/social/organizations/_premises_view.py +16 -0
  1601. skcomplex/models/social/organizations/_queues.py +52 -0
  1602. skcomplex/models/social/organizations/_restaurant.py +59 -0
  1603. skcomplex/models/social/organizations/_restaurant_view.py +14 -0
  1604. skcomplex/models/social/organizations/_sabotage.py +183 -0
  1605. skcomplex/models/social/organizations/_supervisor.py +25 -0
  1606. skcomplex/models/social/organizations/_task.py +65 -0
  1607. skcomplex/models/social/organizations/_task_view.py +15 -0
  1608. skcomplex/models/social/organizations/_trafficking.py +184 -0
  1609. skcomplex/models/social/organizations/_traps.py +322 -0
  1610. skcomplex/models/social/organizations/_traveller.py +55 -0
  1611. skcomplex/models/social/organizations/_traveller_view.py +13 -0
  1612. skcomplex/models/social/organizations/_urban_scaling.py +72 -0
  1613. skcomplex/models/social/segregation/__init__.py +21 -0
  1614. skcomplex/models/social/segregation/_block_moves.py +127 -0
  1615. skcomplex/models/social/segregation/_blocks.py +111 -0
  1616. skcomplex/models/social/segregation/_dweller.py +70 -0
  1617. skcomplex/models/social/segregation/_dweller_view.py +16 -0
  1618. skcomplex/models/social/segregation/_relocation.py +60 -0
  1619. skcomplex/models/social/segregation/_resident.py +55 -0
  1620. skcomplex/models/social/segregation/_resident_view.py +13 -0
  1621. skcomplex/models/social/segregation/_schelling.py +75 -0
  1622. skcomplex/models/social/spreading/__init__.py +37 -0
  1623. skcomplex/models/social/spreading/_cascades.py +118 -0
  1624. skcomplex/models/social/spreading/_exposure.py +166 -0
  1625. skcomplex/models/social/spreading/_growing_word.py +55 -0
  1626. skcomplex/models/social/spreading/_growing_word_view.py +13 -0
  1627. skcomplex/models/social/spreading/_growth.py +52 -0
  1628. skcomplex/models/social/spreading/_infective.py +55 -0
  1629. skcomplex/models/social/spreading/_listeners.py +41 -0
  1630. skcomplex/models/social/spreading/_participant.py +50 -0
  1631. skcomplex/models/social/spreading/_rumour_contacts.py +81 -0
  1632. skcomplex/models/social/spreading/_rumours.py +57 -0
  1633. skcomplex/models/social/spreading/_simplicial.py +120 -0
  1634. skcomplex/models/social/spreading/_simplicial_infection.py +64 -0
  1635. skcomplex/models/social/spreading/_threshold_activation.py +50 -0
  1636. skcomplex/models/social/spreading/_threshold_node_view.py +13 -0
  1637. skcomplex/models/social/spreading/_writing.py +86 -0
  1638. skcomplex/models/types.py +10 -0
  1639. skcomplex/specs/__init__.py +198 -0
  1640. skcomplex/specs/_accelerated_spec.py +46 -0
  1641. skcomplex/specs/_agent_snapshot_spec.py +34 -0
  1642. skcomplex/specs/_agent_state_spec.py +26 -0
  1643. skcomplex/specs/_arguments_spec.py +60 -0
  1644. skcomplex/specs/_axis_spec.py +59 -0
  1645. skcomplex/specs/_base_record_spec.py +16 -0
  1646. skcomplex/specs/_base_spec.py +73 -0
  1647. skcomplex/specs/_base_structure_spec.py +173 -0
  1648. skcomplex/specs/_batch_matching_spec.py +23 -0
  1649. skcomplex/specs/_breakpoints_spec.py +58 -0
  1650. skcomplex/specs/_call_spec.py +64 -0
  1651. skcomplex/specs/_capacity_rows_spec.py +120 -0
  1652. skcomplex/specs/_cardinality_spec.py +58 -0
  1653. skcomplex/specs/_cascade_record_spec.py +36 -0
  1654. skcomplex/specs/_clamp_spec.py +54 -0
  1655. skcomplex/specs/_clause_spec.py +42 -0
  1656. skcomplex/specs/_compiled_flow_spec.py +20 -0
  1657. skcomplex/specs/_composed_rule_spec.py +33 -0
  1658. skcomplex/specs/_continuous_matching_spec.py +48 -0
  1659. skcomplex/specs/_control_solution_spec.py +54 -0
  1660. skcomplex/specs/_control_spec.py +21 -0
  1661. skcomplex/specs/_covariance_adaptation_spec.py +25 -0
  1662. skcomplex/specs/_dataset_spec.py +85 -0
  1663. skcomplex/specs/_delay_spec.py +27 -0
  1664. skcomplex/specs/_dialect_spec.py +207 -0
  1665. skcomplex/specs/_differential_evolution_spec.py +33 -0
  1666. skcomplex/specs/_direction_spec.py +44 -0
  1667. skcomplex/specs/_draw_spec.py +273 -0
  1668. skcomplex/specs/_entry_spec.py +403 -0
  1669. skcomplex/specs/_event_record_spec.py +37 -0
  1670. skcomplex/specs/_evolution_strategy_spec.py +25 -0
  1671. skcomplex/specs/_extremal_record_spec.py +32 -0
  1672. skcomplex/specs/_fractional_rows_spec.py +33 -0
  1673. skcomplex/specs/_fractional_state_spec.py +30 -0
  1674. skcomplex/specs/_held_reduction_spec.py +29 -0
  1675. skcomplex/specs/_hilbert_spec.py +75 -0
  1676. skcomplex/specs/_hyperedge_reduction_spec.py +38 -0
  1677. skcomplex/specs/_issue_spec.py +52 -0
  1678. skcomplex/specs/_iterative_matching_spec.py +39 -0
  1679. skcomplex/specs/_jump_channels_spec.py +40 -0
  1680. skcomplex/specs/_jump_path_spec.py +29 -0
  1681. skcomplex/specs/_layer_spec.py +47 -0
  1682. skcomplex/specs/_layout_spec.py +158 -0
  1683. skcomplex/specs/_local_operator_spec.py +72 -0
  1684. skcomplex/specs/_lookup_spec.py +33 -0
  1685. skcomplex/specs/_loop_spec.py +17 -0
  1686. skcomplex/specs/_lowered_functions_spec.py +71 -0
  1687. skcomplex/specs/_match_spec.py +37 -0
  1688. skcomplex/specs/_matrix_law_spec.py +31 -0
  1689. skcomplex/specs/_move_spec.py +69 -0
  1690. skcomplex/specs/_neighbor_read_spec.py +83 -0
  1691. skcomplex/specs/_neighbor_reduction_spec.py +39 -0
  1692. skcomplex/specs/_network_rows_spec.py +124 -0
  1693. skcomplex/specs/_network_snapshot_spec.py +61 -0
  1694. skcomplex/specs/_noise_process_spec.py +41 -0
  1695. skcomplex/specs/_objective_spec.py +39 -0
  1696. skcomplex/specs/_observable_spec.py +79 -0
  1697. skcomplex/specs/_operator_spec.py +170 -0
  1698. skcomplex/specs/_orders_spec.py +16 -0
  1699. skcomplex/specs/_outer_totalistic_spec.py +38 -0
  1700. skcomplex/specs/_owners_spec.py +28 -0
  1701. skcomplex/specs/_pair_read_spec.py +38 -0
  1702. skcomplex/specs/_parameter_spec.py +81 -0
  1703. skcomplex/specs/_parameters_spec.py +26 -0
  1704. skcomplex/specs/_particle_swarm_spec.py +33 -0
  1705. skcomplex/specs/_partner_spec.py +98 -0
  1706. skcomplex/specs/_partner_switch_spec.py +39 -0
  1707. skcomplex/specs/_phase_spec.py +61 -0
  1708. skcomplex/specs/_phases_schedule_spec.py +59 -0
  1709. skcomplex/specs/_plan_spec.py +18 -0
  1710. skcomplex/specs/_planned_partition_spec.py +30 -0
  1711. skcomplex/specs/_queue_spec.py +46 -0
  1712. skcomplex/specs/_radius_spec.py +66 -0
  1713. skcomplex/specs/_random_search_spec.py +51 -0
  1714. skcomplex/specs/_read_spec.py +45 -0
  1715. skcomplex/specs/_reduction_spec.py +48 -0
  1716. skcomplex/specs/_renewal_record_spec.py +49 -0
  1717. skcomplex/specs/_requirement_spec.py +32 -0
  1718. skcomplex/specs/_role_spec.py +54 -0
  1719. skcomplex/specs/_run_result_spec.py +52 -0
  1720. skcomplex/specs/_run_state_spec.py +41 -0
  1721. skcomplex/specs/_sampled_draw_spec.py +32 -0
  1722. skcomplex/specs/_sampler_spec.py +57 -0
  1723. skcomplex/specs/_samples_spec.py +29 -0
  1724. skcomplex/specs/_schedule_spec.py +17 -0
  1725. skcomplex/specs/_sector_spec.py +31 -0
  1726. skcomplex/specs/_segment_spec.py +21 -0
  1727. skcomplex/specs/_series_spec.py +29 -0
  1728. skcomplex/specs/_signature_spec.py +55 -0
  1729. skcomplex/specs/_snapshots_spec.py +56 -0
  1730. skcomplex/specs/_stable_matching_spec.py +58 -0
  1731. skcomplex/specs/_state_spec.py +138 -0
  1732. skcomplex/specs/_step_spec.py +39 -0
  1733. skcomplex/specs/_structure_state_spec.py +30 -0
  1734. skcomplex/specs/_support_spec.py +76 -0
  1735. skcomplex/specs/_symmetry_spec.py +59 -0
  1736. skcomplex/specs/_table_spec.py +42 -0
  1737. skcomplex/specs/_table_values_spec.py +36 -0
  1738. skcomplex/specs/_tensor_spec.py +197 -0
  1739. skcomplex/specs/_topology_request_spec.py +97 -0
  1740. skcomplex/specs/_totalistic_spec.py +37 -0
  1741. skcomplex/specs/_unknown_spec.py +22 -0
  1742. skcomplex/specs/_validation_report_spec.py +62 -0
  1743. skcomplex/specs/_variable_spec.py +124 -0
  1744. skcomplex/specs/_visual_spec.py +30 -0
  1745. skcomplex/specs/_weight_spec.py +16 -0
  1746. skcomplex/specs/_wiener_block_spec.py +31 -0
  1747. skcomplex/specs/_wiener_process_spec.py +54 -0
  1748. skcomplex/types.py +140 -0
@@ -0,0 +1,1668 @@
1
+ """Lower differential operators on fields to finite-difference stencils and graph Laplacians."""
2
+
3
+ # Author: Georgios Douzas <gdouzas@icloud.com>
4
+ # License: MIT
5
+
6
+ import functools
7
+ import re
8
+ from collections import defaultdict
9
+ from collections.abc import Callable, Mapping
10
+
11
+ import numpy as np
12
+ import numpy.typing as npt
13
+ import scipy.fft
14
+ from sage.all__sagemath_symbolics import SR, Expression
15
+ from sage.modules.free_module_element import FreeModuleElement
16
+ from scipy.ndimage import convolve, map_coordinates
17
+ from scipy.signal import oaconvolve
18
+ from scipy.sparse import csr_matrix, diags, identity
19
+ from scipy.sparse.linalg import factorized
20
+ from skfem import Basis, ElementTetP1, ElementTriP1, asm
21
+ from skfem.models.poisson import laplace, mass
22
+
23
+ from ...core.elements import FieldElement
24
+ from ...core.laws import BaseLaw, BoundaryLaw, FluxLaw, NoiseLaw, RateLaw, UpdateLaw
25
+ from ...core.laws.utils import COORDINATE_PREFIX, INVERSION_BOUNDARIES, displacement, where
26
+ from ...core.spaces import (
27
+ AdjacencyNeighborhood,
28
+ LatticeNeighborhood,
29
+ LatticeSpace,
30
+ MeshSpace,
31
+ NetworkSpace,
32
+ PhaseSpace,
33
+ )
34
+ from ...errors import ValidationError
35
+ from ...specs import NeighborReadSpec, RunStateSpec
36
+ from ...types import Indices, IntTuple
37
+ from .._utils import domain_of, symbol
38
+ from ..problems import (
39
+ CollisionKernel,
40
+ DeclarationsSpec,
41
+ DiffusiveLimitSpec,
42
+ ExpressionPrinter,
43
+ KernelSpec,
44
+ ReferenceSpec,
45
+ )
46
+ from ..problems._field_operator_kernel import FieldOperatorKernel
47
+ from ..problems._law_kernel import LATTICE_BOUNDARIES, MODES
48
+ from ..types import ReadKind
49
+ from ._base import BaseLowering, BasePass
50
+ from ._compilation import Compilation
51
+
52
+ OPERATOR_NAMES = (
53
+ 'laplacian',
54
+ 'partial',
55
+ 'upwind',
56
+ 'inverse_helmholtz',
57
+ 'convolve',
58
+ 'shifted',
59
+ 'reduce_axes',
60
+ 'maximum_entropy',
61
+ 'collision',
62
+ )
63
+ PHASE_OPERATOR_NAMES = ('reduce_axes', 'maximum_entropy', 'collision')
64
+ NEWTON_STEPS = 50
65
+ NEWTON_TOLERANCE = 1e-14
66
+ LARGEST_EXPONENT_CHANGE = 5.0
67
+ TIME = symbol('t')
68
+ PLANE = 2
69
+ SMALL_KERNEL = 7
70
+ WHOLE_SITE = 1e-9
71
+ SHIFTED_MODES = {'periodic': 'grid-wrap', 'zero-flux': 'reflect', 'fixed': 'grid-constant'}
72
+ FILTER_MODES = {'periodic': 'wrap', 'zero-flux': 'reflect', 'fixed': 'constant'}
73
+
74
+
75
+ class FieldLowering(BaseLowering[list[BaseLaw]]):
76
+ """Lowering of the differential operators in the laws of one component to stencils, with the symbols they read.
77
+
78
+ `prepare(compilation)` reads the fields and the initial values of the compilation, and `run(laws)` returns the laws
79
+ with every operator replaced by its stencil, noting the stable steps of the Laplacians of rate laws.
80
+
81
+ Args:
82
+ spec:
83
+ The kernel spec of the component, which `_apply_references` replaces by a copy with the neighbour reads
84
+ and the derived values.
85
+
86
+ Attributes:
87
+ fields_:
88
+ The field of every member entry by entry name.
89
+
90
+ initial_:
91
+ The initial value of every symbol that can be evaluated, for stability limits.
92
+
93
+ shifted_:
94
+ The symbol and offset every neighbour read reads.
95
+
96
+ derived_:
97
+ The field and the derived read of every spectral or finite element operator.
98
+
99
+ limits_:
100
+ The stable steps of the explicit Laplacians of finite-difference fields.
101
+
102
+ volume_limits_:
103
+ The stable steps of the Laplacians of finite-volume fields, as functions of the parameters.
104
+
105
+ written_:
106
+ The lowered value and the value as written of every law, by the entry name and column of its targets.
107
+
108
+ tables_:
109
+ The neighbour tables, by their axis, offset, boundary, and space.
110
+
111
+ solution_boundaries_:
112
+ The boundary condition given to an inversion, by the symbol of its solution.
113
+
114
+ cross_section_:
115
+ The cross-section of the collision law being lowered, or `None`.
116
+
117
+ applied_:
118
+ The lowered value of every operator call so far, by its name, its lowered operands, and the cross-section,
119
+ so an identical call shares one value.
120
+ """
121
+
122
+ fields_: Mapping[str, FieldElement]
123
+ initial_: Mapping[Expression, float]
124
+ shifted_: dict[Expression, tuple[Expression, IntTuple | int]]
125
+ derived_: dict[Expression, tuple[FieldElement, FieldOperatorKernel]]
126
+ limits_: list[float]
127
+ volume_limits_: list[DiffusiveLimitSpec]
128
+ written_: dict[tuple[str, int], list[tuple[Expression, Expression]]]
129
+ tables_: dict[tuple[object, ...], tuple[Indices, float | None]]
130
+ solution_boundaries_: dict[Expression, tuple[str, object]]
131
+ cross_section_: Callable[..., object] | None
132
+ applied_: dict[tuple[object, ...], Expression]
133
+
134
+ def __init__(self, spec: KernelSpec) -> None:
135
+ self.spec = spec
136
+
137
+ def _prepare(self, context: Compilation | None) -> None:
138
+ """Read the fields and the initial values of the compilation, with no stencil yet.
139
+
140
+ Args:
141
+ context:
142
+ The compilation.
143
+
144
+ Raises:
145
+ ValidationError:
146
+ The compilation has no layout yet.
147
+ """
148
+ super()._prepare(context)
149
+ declarations = self.compilation_.layout
150
+ if declarations is None:
151
+ error_msg = 'The compilation has no layout yet. Lower differential operators after the layout pass.'
152
+ raise ValidationError(error_msg)
153
+ self.fields_ = self._field_entries(declarations)
154
+ self.initial_ = self._initial_values(self.spec, declarations)
155
+ self.shifted_, self.derived_, self.tables_, self.solution_boundaries_, self.applied_ = {}, {}, {}, {}, {}
156
+ self.limits_, self.volume_limits_ = [], []
157
+ self.written_ = defaultdict(list)
158
+ self.cross_section_ = None
159
+
160
+ def _run(self, inputs: list[BaseLaw] | None) -> None:
161
+ """Set laws whose differential operators are lowered, noting the stable steps of rate laws.
162
+
163
+ Args:
164
+ inputs:
165
+ The laws of the component.
166
+ """
167
+ result: list[BaseLaw] = []
168
+ for law in inputs or []:
169
+ if isinstance(law, FluxLaw) and self._law_has_operators(law):
170
+ result.append(BasePass._replaced(law, flux=[self._lower(SR(item)) for item in self._components(law)]))
171
+ continue
172
+ if not isinstance(law, RateLaw | NoiseLaw | UpdateLaw | BoundaryLaw) or not self._has_operators(law.value):
173
+ result.append(law)
174
+ continue
175
+ if isinstance(law, RateLaw):
176
+ self._note_limit(law.value)
177
+ self.cross_section_ = law.cross_section if isinstance(law, RateLaw) else None
178
+ lowered = self._lower(law.value)
179
+ if isinstance(law.value, Expression):
180
+ for reference in self.spec._target_references(law._get_targets()[0]):
181
+ self.written_[(reference.entry.name, reference.column)].append((lowered, law.value))
182
+ result.append(BasePass._replaced(law, value=lowered))
183
+ self.lowered_ = result
184
+
185
+ @staticmethod
186
+ def _field_entries(declarations: DeclarationsSpec) -> dict[str, FieldElement]:
187
+ """Return the fields by the name of each of their entries."""
188
+ return {
189
+ entry.name: block.node.component
190
+ for block in declarations.blocks.values()
191
+ if isinstance(block.node.component, FieldElement)
192
+ for entry in block.entries.values()
193
+ }
194
+
195
+ @staticmethod
196
+ def _initial_values(spec: KernelSpec, declarations: DeclarationsSpec) -> dict[Expression, float]:
197
+ """Return the initial value of every symbol of a component, the first member's for groups."""
198
+ states = np.concatenate([np.zeros(0), *declarations.initial_states])
199
+ parameters = np.concatenate([np.zeros(0), *declarations.initial_parameters])
200
+ return {
201
+ item: float((states if reference.is_state else parameters)[reference.entry.start + reference.column])
202
+ for item, reference in spec.references.items()
203
+ if reference.entry.start + reference.column < (states if reference.is_state else parameters).size
204
+ }
205
+
206
+ def _known_reference(self, item: Expression) -> ReferenceSpec:
207
+ """Return the reference of a symbol of the spec, raising an error for a symbol the spec does not read.
208
+
209
+ Args:
210
+ item:
211
+ The symbol.
212
+
213
+ Returns:
214
+ reference:
215
+ The reference of the symbol.
216
+
217
+ Raises:
218
+ ValidationError:
219
+ The spec does not read the symbol.
220
+ """
221
+ reference = self._reference_of(item, self.spec)
222
+ if reference is None:
223
+ error_msg = f'A law of {self.spec.owner} reads {item}, which is not a state or parameter of its namespace.'
224
+ raise ValidationError(error_msg)
225
+ return reference
226
+
227
+ def _field_of(self, item: Expression) -> FieldElement | None:
228
+ """Return the field whose member a symbol reads, or `None` for a single value."""
229
+ reference = self._known_reference(item)
230
+ if reference.source is not ReadKind.MEMBER:
231
+ return None
232
+ found = self.fields_.get(reference.entry.name)
233
+ if found is None:
234
+ error_msg = (
235
+ f'A law of {self.spec.owner} applies a differential operator to {item}, which is not a state or '
236
+ 'parameter of a field. Create the group with `FieldElement`.'
237
+ )
238
+ raise ValidationError(error_msg)
239
+ return found
240
+
241
+ def _table(
242
+ self,
243
+ item: Expression,
244
+ place: FieldElement,
245
+ offset: IntTuple | int,
246
+ ) -> tuple[Indices, float | None, int | None]:
247
+ """Return the neighbour table, the fixed value, and the mode of a symbol at an offset."""
248
+ reference = self._known_reference(item)
249
+ variable = reference.entry.name.rpartition('.')[2]
250
+ if reference.is_state:
251
+ kind, value = place._get_boundary(variable, reference.column)
252
+ else:
253
+ kind, value = (
254
+ 'periodic' if getattr(place.space, 'boundary', 'periodic') == 'periodic' else 'zero-flux',
255
+ 0.0,
256
+ )
257
+ key = (id(place), kind, value, offset)
258
+ if key not in self.tables_:
259
+ space = place.space
260
+ if isinstance(space, NetworkSpace):
261
+ table = space._index_table(AdjacencyNeighborhood())
262
+ sites = np.arange(table.shape[0])[:, None]
263
+ self.tables_[key] = (np.where(table == table.shape[0], sites, table)[:, offset], None)
264
+ else:
265
+ if not isinstance(space, LatticeSpace) or isinstance(offset, int) or not isinstance(value, float):
266
+ error_msg = (
267
+ f'A law of {self.spec.owner} reads {item} at a lattice offset, which needs a field on a '
268
+ 'lattice with a number outside fixed edges.'
269
+ )
270
+ raise ValidationError(error_msg)
271
+ lattice = space._with_edges(LATTICE_BOUNDARIES[kind], value)
272
+ table = lattice._index_table(LatticeNeighborhood((offset,)))[:, 0]
273
+ self.tables_[key] = (table, value if kind == 'fixed' else None)
274
+ table, ghost = self.tables_[key]
275
+ return table, ghost, self._read_mode(place.space, kind, offset)
276
+
277
+ def _shift(self, expression: Expression, offset: IntTuple | int) -> Expression:
278
+ """Return an expression read at a neighbouring site of every member.
279
+
280
+ Args:
281
+ expression:
282
+ The expression of member symbols, possibly already shifted.
283
+
284
+ offset:
285
+ The lattice offset, or the network neighbour slot.
286
+
287
+ Returns:
288
+ shifted:
289
+ The expression in symbols that read the neighbour.
290
+ """
291
+ expression = SR(expression)
292
+ replacements = {}
293
+ for item in expression.variables():
294
+ base, current = self.shifted_.get(item, (item, None))
295
+ if base in self.derived_:
296
+ replacements[item] = self._shifted_derived(base, self._total_offset(current, offset))
297
+ continue
298
+ reference = self._reference_of(base, self.spec)
299
+ if reference is None:
300
+ continue
301
+ if reference.source is ReadKind.NEIGHBOR and base == item and base not in self.shifted_:
302
+ error_msg = (
303
+ f'A law of {self.spec.owner} differentiates {base}, a field over position read on a phase space, '
304
+ 'by a stencil. Use the finite-volume discretization, whose fluxes read it cell by cell.'
305
+ )
306
+ raise ValidationError(error_msg)
307
+ place = self._field_of(base)
308
+ if place is None:
309
+ continue
310
+ total = self._total_offset(current, offset)
311
+ if not isinstance(total, int) and not any(total):
312
+ replacements[item] = base
313
+ continue
314
+ name = f'{base}__{self._tag(total)}'
315
+ target = symbol(name, domain_of(base))
316
+ if self._reference_of(target, self.spec) is None:
317
+ reference = self._known_reference(base)
318
+ table, ghost, mode = self._table(base, place, total)
319
+ space = place.space
320
+ lattice = space if isinstance(space, LatticeSpace) and mode is not None else None
321
+ read = NeighborReadSpec(
322
+ table,
323
+ ghost,
324
+ None if lattice is None else lattice.shape_,
325
+ total if lattice is not None and not isinstance(total, int) else None,
326
+ mode or 0,
327
+ )
328
+ self._add_reference(
329
+ self.spec,
330
+ target,
331
+ ReferenceSpec(reference.entry, reference.is_state, reference.column, ReadKind.NEIGHBOR, read),
332
+ )
333
+ self.shifted_[target] = (base, total)
334
+ replacements[item] = target
335
+ return expression.subs(replacements)
336
+
337
+ def _read_mode(self, space: object, kind: str, offset: IntTuple | int) -> int | None:
338
+ """Return the mode of the edges a read at an offset crosses, or `None` when it crosses edges of two kinds."""
339
+ if not isinstance(space, PhaseSpace) or isinstance(offset, int):
340
+ return MODES[kind]
341
+ kinds = {
342
+ kind if axis in space.position_axes_ else ('periodic' if space.axes_periodic_[axis] else 'zero-flux')
343
+ for axis in range(space.n_dim_)
344
+ if offset[axis]
345
+ }
346
+ return MODES[kinds.pop() if kinds else kind] if len(kinds) < PLANE else None
347
+
348
+ def _total_offset(self, current: IntTuple | int | None, offset: IntTuple | int) -> IntTuple | int:
349
+ """Return the offset of a read at an offset from a read that is already shifted."""
350
+ if isinstance(offset, int) or isinstance(current, int):
351
+ if current is not None:
352
+ error_msg = f'A law of {self.spec.owner} nests operators on a network, which only take one step.'
353
+ raise ValidationError(error_msg)
354
+ return offset
355
+ return tuple(a + b for a, b in zip(current or (0,) * len(offset), offset, strict=True))
356
+
357
+ def _boundaries(self, expression: Expression) -> list[tuple[str, object]]:
358
+ """Return the boundary conditions of the field states an expression reads, through derived values."""
359
+ found = []
360
+ for item in SR(expression).variables():
361
+ if item in self.solution_boundaries_:
362
+ found.append(self.solution_boundaries_[item])
363
+ continue
364
+ if item in self.derived_:
365
+ found += self._boundaries(self.derived_[item][1].operand)
366
+ continue
367
+ base = self.shifted_.get(item, (item, None))[0]
368
+ reference = self._reference_of(base, self.spec)
369
+ if reference is None or not reference.is_state or reference.source is not ReadKind.MEMBER:
370
+ continue
371
+ place = self._field_of(base)
372
+ if place is not None:
373
+ found.append(place._get_boundary(reference.entry.name.rpartition('.')[2], reference.column))
374
+ return found
375
+
376
+ def _boundary(self, expression: Expression, place: FieldElement) -> tuple[str, object]:
377
+ """Return the one boundary condition of the field states an expression reads, or the edges of the space."""
378
+ found = set(self._boundaries(expression))
379
+ if len(found) > 1:
380
+ error_msg = (
381
+ f'A law of {self.spec.owner} applies a nonlocal operator to {expression}, whose states have different '
382
+ 'boundary conditions. Give the states of the operand one boundary condition, or give an inversion '
383
+ 'the boundary of its solution.'
384
+ )
385
+ raise ValidationError(error_msg)
386
+ return found.pop() if found else place._get_boundary('')
387
+
388
+ def _neighbor_table(self, place: FieldElement, kind: str, value: object, offset: IntTuple | int) -> Indices:
389
+ """Return the neighbour of every site at an offset, with the number of sites for reads beyond fixed edges."""
390
+ space = place.space
391
+ if isinstance(space, NetworkSpace) and isinstance(offset, int):
392
+ table = space._index_table(AdjacencyNeighborhood())
393
+ sites = np.arange(table.shape[0])[:, None]
394
+ return np.asarray(np.where(table == table.shape[0], sites, table)[:, offset], dtype=np.intp)
395
+ if not isinstance(space, LatticeSpace) or isinstance(offset, int) or not isinstance(value, float):
396
+ error_msg = (
397
+ f'A law of {self.spec.owner} reads a nonlocal value at a neighbour, which needs a field on a lattice '
398
+ 'or a network with a number outside fixed edges.'
399
+ )
400
+ raise ValidationError(error_msg)
401
+ lattice = space._with_edges(LATTICE_BOUNDARIES[kind], value)
402
+ return np.asarray(lattice._index_table(LatticeNeighborhood((offset,)))[:, 0], dtype=np.intp)
403
+
404
+ def _shifted_derived(self, base: Expression, total: IntTuple | int) -> Expression:
405
+ """Return the symbol of a derived value read at a neighbouring site, indexing its values by the neighbour table.
406
+
407
+ Args:
408
+ base:
409
+ The symbol of the derived value.
410
+
411
+ total:
412
+ The lattice offset, or the network neighbour slot.
413
+
414
+ Returns:
415
+ shifted:
416
+ The symbol of the derived value at the neighbour.
417
+ """
418
+ if not isinstance(total, int) and not any(total):
419
+ return base
420
+ target = symbol(f'{base}__{self._tag(total)}')
421
+ if target in self.derived_:
422
+ return target
423
+ place = self.derived_[base][0]
424
+ kind, value = self._boundary(base, place)
425
+ table = self._neighbor_table(place, kind, value, total)
426
+ size = table.shape[0]
427
+ inside = table < size
428
+ matrix = csr_matrix((np.ones(inside.sum()), (np.flatnonzero(inside), table[inside])), shape=(size, size))
429
+ ghost = float(value) if kind == 'fixed' and isinstance(value, float) else 0.0
430
+
431
+ def apply(values: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
432
+ return np.append(values, ghost)[table]
433
+
434
+ read = FieldOperatorKernel(operand=base, symbols=[base], apply=apply, matrix=matrix).check().prepare()
435
+ self.shifted_[target] = (base, total)
436
+ return self._derived(place, read, target)
437
+
438
+ def _places(self, expression: Expression) -> dict[int, FieldElement]:
439
+ """Return the fields an expression reads, through member symbols, neighbour reads, and derived values."""
440
+ places: dict[int, FieldElement] = {}
441
+ place: FieldElement | None
442
+ for item in SR(expression).variables():
443
+ if item in self.derived_:
444
+ place = self.derived_[item][0]
445
+ else:
446
+ base = self.shifted_.get(item, (item, None))[0]
447
+ place = self._field_of(base) if self._reference_of(base, self.spec) is not None else None
448
+ if place is not None:
449
+ places[id(place)] = place
450
+ return places
451
+
452
+ def _place(self, expression: Expression) -> FieldElement:
453
+ """Return the one field an expression reads, or raise an error."""
454
+ places = self._places(expression)
455
+ discretizations = {place.discretization for place in places.values()}
456
+ spaces = {id(place.space) for place in places.values()}
457
+ if len(spaces) != 1 or len(discretizations) != 1:
458
+ error_msg = (
459
+ f'A law of {self.spec.owner} applies an operator to {expression}, which reads {len(spaces)} fields. An '
460
+ 'operator acts on the states of fields of one space and one discretization.'
461
+ )
462
+ raise ValidationError(error_msg)
463
+ return next(iter(places.values()))
464
+
465
+ def _space(self, expression: Expression) -> LatticeSpace | NetworkSpace:
466
+ """Return the space of the fields an expression reads."""
467
+ spaces = {id(place.space): place.space for place in self._places(expression).values()}
468
+ if len(spaces) != 1:
469
+ error_msg = (
470
+ f'A law of {self.spec.owner} applies an operator to {expression}, which reads {len(spaces)} fields. An '
471
+ 'operator acts on the states of fields of one space.'
472
+ )
473
+ raise ValidationError(error_msg)
474
+ space = next(iter(spaces.values()))
475
+ if not isinstance(space, LatticeSpace | NetworkSpace):
476
+ error_msg = (
477
+ f'A law of {self.spec.owner} applies a stencil to {expression}, which lives on a mesh. Use the '
478
+ 'finite-element discretization.'
479
+ )
480
+ raise ValidationError(error_msg)
481
+ return space
482
+
483
+ def _laplacian(self, expression: Expression) -> Expression:
484
+ """Return the stencil of the Laplacian of an expression."""
485
+ space = self._space(expression)
486
+ if isinstance(space, NetworkSpace):
487
+ width = space._index_table(AdjacencyNeighborhood()).shape[1]
488
+ return sum((self._shift(expression, slot) - expression for slot in range(width)), SR(0))
489
+ total = SR(0)
490
+ for axis in range(space.n_dim_):
491
+ step = tuple(int(axis == other) for other in range(space.n_dim_))
492
+ back = tuple(-item for item in step)
493
+ total += (self._shift(expression, step) + self._shift(expression, back) - 2 * expression) / (
494
+ space.spacings_[axis] ** 2
495
+ )
496
+ return total
497
+
498
+ def _lattice(self, expression: Expression, axis: int, name: str) -> tuple[LatticeSpace, IntTuple, IntTuple]:
499
+ """Return the lattice of an expression and the unit offsets along an axis."""
500
+ space = self._space(expression)
501
+ if not isinstance(space, LatticeSpace) or not 0 <= axis < space.n_dim_:
502
+ error_msg = (
503
+ f'A law of {self.spec.owner} takes the {name} of {expression} along axis {axis}, which needs a lattice.'
504
+ )
505
+ raise ValidationError(error_msg)
506
+ step = tuple(int(axis == other) for other in range(space.n_dim_))
507
+ return space, step, tuple(-item for item in step)
508
+
509
+ def _lower(self, expression: object) -> object:
510
+ """Return an expression with every operator replaced by its stencil, innermost first.
511
+
512
+ Args:
513
+ expression:
514
+ The value of a law.
515
+
516
+ Returns:
517
+ lowered:
518
+ The value with stencils.
519
+ """
520
+ if not isinstance(expression, Expression) or not self._has_operators(expression):
521
+ return expression
522
+ call = expression
523
+ operator = call.operator()
524
+ operands = [self._lower(item) for item in call.operands()]
525
+ name = getattr(operator, 'name', lambda: '')()
526
+ if name not in OPERATOR_NAMES:
527
+ return operator(*operands)
528
+ key = (name, *operands, id(self.cross_section_))
529
+ if key not in self.applied_:
530
+ self.applied_[key] = self._lowered_call(name, operands)
531
+ return self.applied_[key]
532
+
533
+ def _lowered_call(self, name: str, operands: list[object]) -> Expression:
534
+ """Return the value of one operator whose operands are lowered."""
535
+ if name == 'shifted':
536
+ return self._shifted(SR(operands[0]), [SR(item) for item in operands[1:]])
537
+ if name in {'laplacian', 'partial', 'upwind'} and not SR(operands[0]).variables():
538
+ return SR(0)
539
+ place = self._place(SR(operands[0]))
540
+ if name in PHASE_OPERATOR_NAMES:
541
+ return self._phase_operator(name, [SR(item) for item in operands], place)
542
+ if name == 'convolve':
543
+ return self._convolve(SR(operands[0]), SR(operands[1]), SR(operands[2]), place)
544
+ return self._discretized(name, operands, place)
545
+
546
+ def _phase_operator(self, name: str, operands: list[Expression], place: FieldElement) -> Expression:
547
+ """Return the value of an operator over the class axes of a phase space."""
548
+ if name == 'reduce_axes':
549
+ return self._reduced(operands[0], operands[1:], place)
550
+ if name == 'maximum_entropy':
551
+ return self._equilibrium(operands[0], int(operands[1]), operands[2:], place)
552
+ return self._collision(operands[0], place)
553
+
554
+ def _phase_space(self, operand: Expression, place: FieldElement) -> PhaseSpace:
555
+ """Return the phase space of a field whose class axes an operator reads, raising an error for another space."""
556
+ if not isinstance(place.space, PhaseSpace):
557
+ error_msg = (
558
+ f'A law of {self.spec.owner} reduces {operand} over class axes, but its field lives on '
559
+ f'{type(place.space).__name__}. Give the field a `PhaseSpace`.'
560
+ )
561
+ raise ValidationError(error_msg)
562
+ return place.space
563
+
564
+ def _axes_of(self, coordinates: list[Expression], space: PhaseSpace) -> tuple[int, ...]:
565
+ """Return the indices of the class axes of their coordinates, raising an error for an axis the space lacks."""
566
+ names = [str(item).removeprefix(COORDINATE_PREFIX) for item in coordinates]
567
+ missing = [name for name in names if name not in space.class_axes_]
568
+ if missing:
569
+ error_msg = (
570
+ f'A law of {self.spec.owner} reads the class axes {missing}, but the phase space holds the axes '
571
+ f'{list(space.class_axes_)}.'
572
+ )
573
+ raise ValidationError(error_msg)
574
+ return tuple(space.class_axes_[name] for name in names)
575
+
576
+ def _reduced(self, operand: Expression, coordinates: list[Expression], place: FieldElement) -> Expression:
577
+ """Return the symbol of the integral of an expression over class axes, broadcast back along them."""
578
+ space = self._phase_space(operand, place)
579
+ axes = self._axes_of(coordinates, space)
580
+ width = float(np.prod([space.spacings_[axis] for axis in axes]))
581
+ dimensions = space.shape_
582
+
583
+ over_positions = self.spec.rows == space.position_size_ != space.size_
584
+
585
+ def apply(values: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
586
+ reduced = np.reshape(values, dimensions).sum(axis=axes, keepdims=True) * width
587
+ return reduced.ravel() if over_positions else np.broadcast_to(reduced, dimensions).ravel()
588
+
589
+ read = FieldOperatorKernel(operand=operand, symbols=self._symbols(operand), apply=apply)
590
+ return self._derived(place, read.check().prepare())
591
+
592
+ def _equilibrium(
593
+ self,
594
+ operand: Expression,
595
+ order: int,
596
+ coordinates: list[Expression],
597
+ place: FieldElement,
598
+ ) -> Expression:
599
+ """Return the symbol of the density with the largest entropy and the moments of an expression."""
600
+ space = self._phase_space(operand, place)
601
+ apply = self._equilibrium_apply(space, self._axes_of(coordinates, space), order)
602
+ read = FieldOperatorKernel(operand=operand, symbols=self._symbols(operand), apply=apply)
603
+ return self._derived(place, read.check().prepare())
604
+
605
+ def _collision(self, operand: Expression, place: FieldElement) -> Expression:
606
+ """Return the symbol of the binary collision integral of a density over the class axes of its phase space."""
607
+ space = self._phase_space(operand, place)
608
+ if self.cross_section_ is None:
609
+ error_msg = (
610
+ f'A law of {self.spec.owner} reads a collision integral, which only a `RateLaw` with a cross-section '
611
+ 'declares.'
612
+ )
613
+ raise ValidationError(error_msg)
614
+ spacings = (space.spacings_[-PLANE], space.spacings_[-1])
615
+ kernel = CollisionKernel(space.shape_, spacings, self.cross_section_).check().prepare()
616
+ empty = np.zeros(0)
617
+
618
+ def apply(values: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
619
+ return kernel.run(RunStateSpec(0.0, values, empty)).values_
620
+
621
+ read = FieldOperatorKernel(operand=operand, symbols=self._symbols(operand), apply=apply)
622
+ return self._derived(place, read.check().prepare())
623
+
624
+ def _discretized(self, name: str, operands: list[object], place: FieldElement) -> Expression:
625
+ """Return a local operator or an inversion lowered for the discretization of its field."""
626
+ if place.discretization == 'spectral':
627
+ return self._spectral(name, operands, place)
628
+ if name == 'inverse_helmholtz':
629
+ given = self._given_boundary(operands[2:])
630
+ return self._inverse(SR(operands[0]), self._screening(SR(operands[1])), place, given)
631
+ if place.discretization == 'finite-element':
632
+ return self._finite_element(name, SR(operands[0]), place)
633
+ return self._stencil(name, operands)
634
+
635
+ def _stencil(self, name: str, operands: list[object]) -> Expression:
636
+ """Return the finite-difference stencil of an operator on a lattice or a network."""
637
+ if name == 'laplacian':
638
+ return self._laplacian(SR(operands[0]))
639
+ axis = int(SR(operands[1]))
640
+ value = SR(operands[0])
641
+ space, step, back = self._lattice(value, axis, 'derivative' if name == 'partial' else 'advection')
642
+ if name == 'partial':
643
+ return (self._shift(value, step) - self._shift(value, back)) / (2 * space.spacings_[axis])
644
+ velocity = SR(operands[2])
645
+ behind = (value - self._shift(value, back)) / space.spacings_[axis]
646
+ ahead = (self._shift(value, step) - value) / space.spacings_[axis]
647
+ return velocity * where(velocity > 0, behind, ahead)
648
+
649
+ def _derived(self, place: FieldElement, read: FieldOperatorKernel, target: Expression | None = None) -> Expression:
650
+ """Return a symbol that stands for a derived value of a field, a new one by default, with its read."""
651
+ target = symbol(f'_derived_{place.label}_{len(self.derived_)}') if target is None else target
652
+ references = [self._known_reference(item) for item in read.symbols]
653
+ entry = next(
654
+ reference.entry
655
+ for reference in references
656
+ if reference.source in {ReadKind.MEMBER, ReadKind.NEIGHBOR, ReadKind.DERIVED}
657
+ )
658
+ self._add_reference(self.spec, target, ReferenceSpec(entry, True, 0, ReadKind.DERIVED, read))
659
+ self.derived_[target] = (place, read)
660
+ return target
661
+
662
+ def _spectral(self, name: str, operands: list[object], place: FieldElement) -> Expression:
663
+ """Return the symbol of a spectral operator applied to an expression, composing chains of operators."""
664
+ space = place.space
665
+ if not isinstance(space, LatticeSpace) or space.boundary != 'periodic':
666
+ error_msg = f'A law of {self.spec.owner} uses a spectral field, which needs a periodic lattice.'
667
+ raise ValidationError(error_msg)
668
+ if name == 'upwind':
669
+ velocity = SR(operands[2])
670
+ return velocity * self._spectral('partial', [operands[0], operands[1]], place)
671
+ if name == 'inverse_helmholtz' and self._given_boundary(operands[2:]) not in {None, ('periodic', 0.0)}:
672
+ error_msg = (
673
+ f'A law of {self.spec.owner} inverts on a spectral field with a boundary that is not periodic. Give '
674
+ 'the inversion no boundary, or use the finite-difference discretization.'
675
+ )
676
+ raise ValidationError(error_msg)
677
+ axis = int(SR(operands[1])) if name == 'partial' else 0
678
+ if name == 'partial' and not 0 <= axis < space.n_dim_:
679
+ error_msg = f'A law of {self.spec.owner} takes a derivative along axis {axis} of a {space.n_dim_}D lattice.'
680
+ raise ValidationError(error_msg)
681
+ screening = self._screening(SR(operands[1])) if name == 'inverse_helmholtz' else 0.0
682
+ if isinstance(space, PhaseSpace) and name == 'partial' and space._axis_boundary(axis) != 'periodic':
683
+ error_msg = (
684
+ f'A law of {self.spec.owner} takes a spectral derivative along axis {axis}, which is an interval. Use '
685
+ 'a periodic class axis or the finite-volume discretization.'
686
+ )
687
+ raise ValidationError(error_msg)
688
+ multiplier = self._spectral_multiplier(
689
+ name,
690
+ axis,
691
+ space.shape_,
692
+ space.spacings_,
693
+ screening,
694
+ axes=self._transported_axes(space, name),
695
+ )
696
+ return self._multiplied(SR(operands[0]), multiplier, place)
697
+
698
+ def _multiplied(
699
+ self,
700
+ operand: Expression,
701
+ multiplier: npt.NDArray[np.complex128],
702
+ place: FieldElement,
703
+ ) -> Expression:
704
+ """Return the symbol of a Fourier multiplier applied to an expression, composing chains of multipliers."""
705
+ dimensions = place.space.shape_ if isinstance(place.space, LatticeSpace) else ()
706
+ inner = self.derived_.get(operand)
707
+ if inner is not None and inner[1].multiplier is not None:
708
+ operand, multiplier = inner[1].operand, multiplier * inner[1].multiplier
709
+ symbols = sorted(
710
+ (item for item in operand.variables() if self._reference_of(item, self.spec) is not None),
711
+ key=str,
712
+ )
713
+ read = (
714
+ FieldOperatorKernel(
715
+ operand=operand,
716
+ symbols=symbols,
717
+ apply=self._spectral_apply(multiplier, dimensions),
718
+ multiplier=multiplier,
719
+ dimensions=dimensions,
720
+ )
721
+ .check()
722
+ .prepare()
723
+ )
724
+ return self._derived(place, read)
725
+
726
+ def _symbols(self, expression: Expression) -> list[Expression]:
727
+ """Return the symbols of an expression that the spec reads, sorted by name."""
728
+ return sorted(
729
+ (item for item in SR(expression).variables() if self._reference_of(item, self.spec) is not None),
730
+ key=str,
731
+ )
732
+
733
+ def _screening(self, screening: Expression) -> float:
734
+ """Return the value of a screening at the current parameters, raising an error when it is not a real number."""
735
+ value = SR(screening).subs(self.initial_)
736
+ if value.variables() or not value.is_real() or float(value) < 0:
737
+ error_msg = (
738
+ f'A law of {self.spec.owner} inverts with the screening {screening}, which is not a non-negative '
739
+ 'number of the parameters. Use a screening whose square is non-negative and that reads no state.'
740
+ )
741
+ raise ValidationError(error_msg)
742
+ return float(value)
743
+
744
+ def _given_boundary(self, operands: list[object]) -> tuple[str, float] | None:
745
+ """Return the boundary condition given to an inversion by its code and value, or `None` when none is given."""
746
+ if not operands:
747
+ return None
748
+ code, value = SR(operands[0]), SR(operands[1])
749
+ if code.variables() or value.variables() or not 0 <= int(code) < len(INVERSION_BOUNDARIES):
750
+ error_msg = (
751
+ f'A law of {self.spec.owner} inverts with the boundary code {code} and value {value}. Give '
752
+ '`inverse_helmholtz` its boundary as `boundary=`, with a number as the fixed value.'
753
+ )
754
+ raise ValidationError(error_msg)
755
+ return INVERSION_BOUNDARIES[int(code)], float(value)
756
+
757
+ def _inverse(
758
+ self,
759
+ operand: Expression,
760
+ screening: float,
761
+ place: FieldElement,
762
+ given: tuple[str, float] | None = None,
763
+ ) -> Expression:
764
+ """Return the symbol of the solution of a modified-Helmholtz equation on a lattice, a network, or a mesh.
765
+
766
+ Args:
767
+ operand:
768
+ The right-hand side.
769
+
770
+ screening:
771
+ The screening, a non-negative number.
772
+
773
+ place:
774
+ The field.
775
+
776
+ given:
777
+ The boundary condition of the solution, or `None` for the boundary condition of the operand's states.
778
+
779
+ Returns:
780
+ solution:
781
+ The symbol of the solution.
782
+
783
+ Raises:
784
+ ValidationError:
785
+ The field's space or the boundary has no inversion, such as a boundary given on a network.
786
+ """
787
+ space = place.space
788
+ kind, value = self._boundary(operand, place) if given is None else given
789
+ apply: Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]]
790
+ if isinstance(space, NetworkSpace) and given is not None:
791
+ error_msg = f'A law of {self.spec.owner} inverts on a network with a boundary. Give the inversion none.'
792
+ raise ValidationError(error_msg)
793
+ if isinstance(space, MeshSpace):
794
+ apply = self._mesh_inverse(space, screening, kind, value)
795
+ elif isinstance(space, NetworkSpace):
796
+ apply = self._network_inverse(space, screening)
797
+ elif isinstance(space, PhaseSpace) and (kind != 'fixed' or isinstance(value, float)):
798
+ fill = float(value) if isinstance(value, float) else 0.0
799
+ apply = self._over_positions(space, self._lattice_inverse(space.position, screening, kind, fill))
800
+ elif isinstance(space, LatticeSpace) and (kind != 'fixed' or isinstance(value, float)):
801
+ apply = self._lattice_inverse(space, screening, kind, float(value) if isinstance(value, float) else 0.0)
802
+ else:
803
+ error_msg = (
804
+ f'A law of {self.spec.owner} inverts {operand} on a {type(space).__name__} with the boundary {kind}, '
805
+ 'which needs a lattice, a network, or a mesh, with a number outside fixed lattice edges.'
806
+ )
807
+ raise ValidationError(error_msg)
808
+ read = FieldOperatorKernel(operand=operand, symbols=self._symbols(operand), apply=apply).check().prepare()
809
+ solution = self._derived(place, read)
810
+ if given is not None:
811
+ self.solution_boundaries_[solution] = (kind, value)
812
+ return solution
813
+
814
+ def _kernel_weights(
815
+ self,
816
+ kernel: Expression,
817
+ space: LatticeSpace,
818
+ radius: Expression,
819
+ *,
820
+ wrapped: bool,
821
+ ) -> npt.NDArray[np.float64]:
822
+ """Return a kernel sampled at the displacements of a lattice within a radius, times the cell volume.
823
+
824
+ Args:
825
+ kernel:
826
+ The kernel, an expression of the displacement and the parameters.
827
+
828
+ space:
829
+ The lattice.
830
+
831
+ radius:
832
+ The distance beyond which the kernel is zero, or infinity.
833
+
834
+ wrapped:
835
+ Whether to sample every displacement of a periodic lattice in FFT order, rather than a centred window.
836
+
837
+ Returns:
838
+ weights:
839
+ The sampled kernel.
840
+
841
+ Raises:
842
+ ValidationError:
843
+ The kernel reads a symbol that is not a displacement or a parameter.
844
+ """
845
+ axes = [displacement(axis) for axis in range(space.n_dim_)]
846
+ parameters = {
847
+ key: item
848
+ for key, item in self.initial_.items()
849
+ if not getattr(self._reference_of(key, self.spec), 'is_state', True)
850
+ }
851
+ value = SR(kernel).subs(parameters)
852
+ unknown = sorted(set(value.variables()) - set(axes), key=str)
853
+ if unknown:
854
+ error_msg = (
855
+ f'A law of {self.spec.owner} convolves with the kernel {kernel}, which reads '
856
+ f'{", ".join(map(str, unknown))}. Write the kernel in the displacements and the parameters.'
857
+ )
858
+ raise ValidationError(error_msg)
859
+ distance = float('inf') if SR(radius).is_infinity() else float(SR(radius).subs(parameters))
860
+ if wrapped:
861
+ steps = [np.fft.fftfreq(size, d=1.0 / size) for size in space.shape_]
862
+ else:
863
+ reach = [
864
+ size - 1 if np.isinf(distance) else min(size - 1, int(np.ceil(distance / step - WHOLE_SITE)))
865
+ for size, step in zip(space.shape_, space.spacings_, strict=True)
866
+ ]
867
+ steps = [np.arange(-item, item + 1, dtype=float) for item in reach]
868
+ grids = np.meshgrid(*[item * step for item, step in zip(steps, space.spacings_, strict=True)], indexing='ij')
869
+ printer = ExpressionPrinter(time=TIME, compiled=True).check().prepare(axes)
870
+ function = ExpressionPrinter._function_of(printer.run([value]).code_)
871
+ computed = ExpressionPrinter._values_of(function(0.0, *grids))[0]
872
+ sampled = np.broadcast_to(np.asarray(computed, dtype=float), grids[0].shape)
873
+ inside = np.sqrt(sum((grid**2 for grid in grids), np.zeros(grids[0].shape))) <= distance * (1 + WHOLE_SITE)
874
+ return np.where(inside, sampled, 0.0) * float(np.prod(space.spacings_))
875
+
876
+ def _convolve(self, operand: Expression, kernel: Expression, radius: Expression, place: FieldElement) -> Expression:
877
+ """Return the symbol of the convolution of an expression with a kernel on a lattice."""
878
+ space = place.space
879
+ if not isinstance(space, LatticeSpace):
880
+ error_msg = (
881
+ f'A law of {self.spec.owner} convolves {operand} on a {type(space).__name__}, which needs a lattice '
882
+ 'space. Give the field a lattice space.'
883
+ )
884
+ raise ValidationError(error_msg)
885
+ if place.discretization == 'spectral':
886
+ weights = self._kernel_weights(kernel, space, radius, wrapped=True)
887
+ return self._multiplied(operand, np.fft.rfftn(weights).astype(complex), place)
888
+ kind, value = self._boundary(operand, place)
889
+ if kind == 'fixed' and not isinstance(value, float):
890
+ error_msg = f'A law of {self.spec.owner} convolves {operand}, which needs a number outside fixed edges.'
891
+ raise ValidationError(error_msg)
892
+ window = self._kernel_weights(kernel, space, radius, wrapped=False)
893
+ if kind == 'periodic' and max(window.shape) > SMALL_KERNEL:
894
+ weights = self._kernel_weights(kernel, space, radius, wrapped=True)
895
+ apply = self._spectral_apply(np.fft.rfftn(weights).astype(complex), space.shape_)
896
+ else:
897
+ apply = self._window_apply(window, space.shape_, kind, float(value) if isinstance(value, float) else 0.0)
898
+ matrix = None if SR(radius).is_infinity() else self._window_matrix(window, place, kind, value)
899
+ read = FieldOperatorKernel(operand=operand, symbols=self._symbols(operand), apply=apply, matrix=matrix)
900
+ return self._derived(place, read.check().prepare())
901
+
902
+ def _window_matrix(
903
+ self,
904
+ window: npt.NDArray[np.float64],
905
+ place: FieldElement,
906
+ kind: str,
907
+ value: object,
908
+ ) -> csr_matrix:
909
+ """Return the sparse matrix of the linear part of a convolution with a window, the sites within its radius."""
910
+ size = place.size_
911
+ total = csr_matrix((size, size))
912
+ centre = np.asarray(window.shape) // 2
913
+ for index in zip(*np.nonzero(window), strict=True):
914
+ offset = tuple(int(item) for item in centre - np.asarray(index))
915
+ table = self._neighbor_table(place, kind, value, offset)
916
+ inside = table < size
917
+ selection = (np.full(inside.sum(), window[index]), (np.flatnonzero(inside), table[inside]))
918
+ total = total + csr_matrix(selection, shape=(size, size))
919
+ return csr_matrix(total)
920
+
921
+ def _shifted(self, operand: Expression, operands: list[Expression]) -> Expression:
922
+ """Return an expression read at a physical displacement, a neighbour read for whole sites, else interpolated.
923
+
924
+ Args:
925
+ operand:
926
+ The expression.
927
+
928
+ operands:
929
+ The displacement along every axis, followed by the order of the interpolation when it is not 1.
930
+
931
+ Returns:
932
+ read:
933
+ The expression read at the displacement.
934
+
935
+ Raises:
936
+ ValidationError:
937
+ The field is not on a lattice, the displacement does not have one component per axis, or a fixed edge
938
+ has no number.
939
+ """
940
+ place = self._place(operand)
941
+ space = place.space
942
+ dimensions = space.n_dim_ if isinstance(space, LatticeSpace) else 0
943
+ offset, orders = operands[:dimensions], operands[dimensions:]
944
+ if not isinstance(space, LatticeSpace) or len(offset) != space.n_dim_ or len(orders) > 1:
945
+ error_msg = (
946
+ f'A law of {self.spec.owner} reads {operand} at a shifted position, which needs a field on a lattice '
947
+ 'space and one displacement per axis. Give the field a lattice space.'
948
+ )
949
+ raise ValidationError(error_msg)
950
+ sites = self._whole_sites(offset, space.spacings_)
951
+ if sites is not None:
952
+ return self._shift(operand, sites)
953
+ kind, value = self._boundary(operand, place)
954
+ if kind == 'fixed' and not isinstance(value, float):
955
+ error_msg = f'A law of {self.spec.owner} reads {operand} beyond fixed edges, which needs a number there.'
956
+ raise ValidationError(error_msg)
957
+ symbols = sorted(set(self._symbols(operand)).union(*[self._symbols(item) for item in offset]), key=str)
958
+ apply = self._interpolated_apply(
959
+ space.shape_,
960
+ space.spacings_,
961
+ kind,
962
+ float(value) if isinstance(value, float) else 0.0,
963
+ int(orders[0]) if orders else 1,
964
+ )
965
+ read = FieldOperatorKernel(
966
+ operand=operand,
967
+ symbols=symbols,
968
+ apply=apply,
969
+ displacement=offset,
970
+ )
971
+ return self._derived(place, read.check().prepare())
972
+
973
+ def _finite_element(self, name: str, operand: Expression, place: FieldElement) -> Expression:
974
+ """Return the symbol of the finite element Laplacian of an expression."""
975
+ if name != 'laplacian':
976
+ error_msg = (
977
+ f'A law of {self.spec.owner} takes the {name} of a finite element field, which takes Laplacians only.'
978
+ )
979
+ raise ValidationError(error_msg)
980
+ if not isinstance(place.space, MeshSpace):
981
+ error_msg = f'A law of {self.spec.owner} uses a finite element field, which needs a mesh.'
982
+ raise ValidationError(error_msg)
983
+ matrix = self._mesh_laplacian(place.space)
984
+ symbols = sorted(
985
+ (item for item in operand.variables() if self._reference_of(item, self.spec) is not None),
986
+ key=str,
987
+ )
988
+ read = (
989
+ FieldOperatorKernel(
990
+ operand=operand,
991
+ symbols=symbols,
992
+ apply=lambda values: matrix @ values,
993
+ matrix=matrix,
994
+ )
995
+ .check()
996
+ .prepare()
997
+ )
998
+ return self._derived(place, read)
999
+
1000
+ def _note_volume_limit(self, coefficient: Expression, stiffness: float) -> None:
1001
+ """Record the diffusive step limit of a finite-volume field as a function of the parameters it reads."""
1002
+ symbols = sorted(set(coefficient.variables()) - {TIME}, key=str)
1003
+ found = [self._reference_of(item, self.spec) for item in symbols]
1004
+ references = [reference for reference in found if reference is not None]
1005
+ if len(references) < len(symbols) or any(reference.is_state for reference in references):
1006
+ return
1007
+ function = ExpressionPrinter(time=TIME, compiled=True).check().prepare(symbols).run([coefficient]).code_
1008
+ if not callable(function):
1009
+ error_msg = f'A compiled printer returns a function, not a {type(function).__name__}.'
1010
+ raise TypeError(error_msg)
1011
+ self.volume_limits_.append(DiffusiveLimitSpec(function, tuple(references), stiffness))
1012
+
1013
+ def _note_limit(self, value: object) -> None:
1014
+ """Record the diffusive step limit of the Laplacians in a law value.
1015
+
1016
+ A finite-difference field records the limit when the coefficient is a number at the initial values, and a
1017
+ finite-volume field records it as a function of the parameters the coefficient reads.
1018
+
1019
+ Args:
1020
+ value:
1021
+ The value of a rate law before lowering.
1022
+ """
1023
+ if not isinstance(value, Expression):
1024
+ return
1025
+ for call in self._operator_calls(value, 'laplacian'):
1026
+ place = self._place(call.operands()[0])
1027
+ if place.discretization not in {'finite-difference', 'finite-volume'}:
1028
+ continue
1029
+ placeholder = symbol('_laplacian_')
1030
+ expression = SR(value.subs({call: placeholder})).diff(placeholder)
1031
+ space = place.space
1032
+ if isinstance(space, NetworkSpace):
1033
+ stiffness = max((item for _, item in space.graph.degree), default=1)
1034
+ elif isinstance(space, LatticeSpace):
1035
+ stiffness = sum(2 / step**2 for step in space.spacings_)
1036
+ else:
1037
+ continue
1038
+ if stiffness == 0:
1039
+ continue
1040
+ if place.discretization == 'finite-volume':
1041
+ self._note_volume_limit(expression, stiffness)
1042
+ continue
1043
+ coefficient = expression.subs(self.initial_)
1044
+ if coefficient.variables():
1045
+ continue
1046
+ magnitude = abs(float(coefficient))
1047
+ if magnitude == 0:
1048
+ continue
1049
+ self.limits_.append(1 / (stiffness * magnitude))
1050
+
1051
+ @staticmethod
1052
+ def _basis(space: PhaseSpace, axes: tuple[int, ...], order: int) -> npt.NDArray[np.float64]:
1053
+ """Return the functions whose moments an equilibrium keeps at every class, one column per function.
1054
+
1055
+ Args:
1056
+ space:
1057
+ The phase space.
1058
+
1059
+ axes:
1060
+ The indices of the class axes of the equilibrium.
1061
+
1062
+ order:
1063
+ The highest order of the moments, 0, 1, or 2.
1064
+
1065
+ Returns:
1066
+ basis:
1067
+ The value 1, the coordinates for an order above 0, and their squared length for the order 2.
1068
+ """
1069
+ names = {index: name for name, index in space.class_axes_.items()}
1070
+ grids = np.meshgrid(*(space.coordinates_[names[axis]] for axis in axes), indexing='ij')
1071
+ points = [grid.ravel() for grid in grids]
1072
+ columns = [np.ones(points[0].size)]
1073
+ if order >= 1:
1074
+ columns += points
1075
+ if order == PLANE:
1076
+ columns.append(sum(point**2 for point in points))
1077
+ return np.column_stack(columns)
1078
+
1079
+ @staticmethod
1080
+ def _newton(
1081
+ basis: npt.NDArray[np.float64],
1082
+ moments: npt.NDArray[np.float64],
1083
+ width: float,
1084
+ guess: npt.NDArray[np.float64],
1085
+ ) -> npt.NDArray[np.float64]:
1086
+ """Return the exponents of the densities `exp(basis @ a)` of the given discrete moments, by damped Newton steps.
1087
+
1088
+ Args:
1089
+ basis:
1090
+ The functions at every class, one column per function.
1091
+
1092
+ moments:
1093
+ The discrete moments of every density, one row per density.
1094
+
1095
+ width:
1096
+ The volume of a cell of the class axes.
1097
+
1098
+ guess:
1099
+ The exponents to start from, one row per density.
1100
+
1101
+ Returns:
1102
+ exponents:
1103
+ The exponents, one row per density.
1104
+ """
1105
+ exponents = guess.copy()
1106
+ scale = np.maximum(np.abs(moments).max(axis=1, keepdims=True), 1.0)
1107
+ for _ in range(NEWTON_STEPS):
1108
+ density = np.exp(exponents @ basis.T)
1109
+ error = width * density @ basis - moments
1110
+ if np.abs(error / scale).max() <= NEWTON_TOLERANCE:
1111
+ break
1112
+ hessian = width * np.einsum('ij,jk,jl->ikl', density, basis, basis, optimize=True)
1113
+ step = np.linalg.solve(hessian, -error[..., None])[..., 0]
1114
+ largest = np.abs(step @ basis.T).max(axis=1, keepdims=True)
1115
+ exponents += step * np.minimum(1.0, LARGEST_EXPONENT_CHANGE / np.maximum(largest, 1e-300))
1116
+ return exponents
1117
+
1118
+ @staticmethod
1119
+ def _equilibrium_apply(
1120
+ space: PhaseSpace,
1121
+ axes: tuple[int, ...],
1122
+ order: int,
1123
+ ) -> Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]]:
1124
+ """Return the function of the values of a density to its maximum-entropy equilibrium at every position.
1125
+
1126
+ Args:
1127
+ space:
1128
+ The phase space.
1129
+
1130
+ axes:
1131
+ The indices of the class axes of the equilibrium.
1132
+
1133
+ order:
1134
+ The highest order of the moments that are kept.
1135
+
1136
+ Returns:
1137
+ apply:
1138
+ The function of the values at every site.
1139
+ """
1140
+ basis = FieldLowering._basis(space, axes, order)
1141
+ width = float(np.prod([space.spacings_[axis] for axis in axes]))
1142
+ moved = tuple(range(space.n_dim_ - len(axes), space.n_dim_))
1143
+ dimension = len(axes)
1144
+
1145
+ def apply(values: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
1146
+ grid = np.moveaxis(np.reshape(values, space.shape_), axes, moved)
1147
+ shape = grid.shape
1148
+ rows = grid.reshape(-1, basis.shape[0])
1149
+ moments = width * rows @ basis
1150
+ total = moments[:, 0]
1151
+ filled = total > 0
1152
+ result = np.zeros(rows.shape)
1153
+ if filled.any():
1154
+ guess = FieldLowering._equilibrium_guess(moments[filled], width, basis.shape[0], dimension)
1155
+ exponents = FieldLowering._newton(basis, moments[filled], width, guess)
1156
+ result[filled] = np.exp(exponents @ basis.T)
1157
+ return np.moveaxis(result.reshape(shape), moved, axes).ravel()
1158
+
1159
+ return apply
1160
+
1161
+ @staticmethod
1162
+ def _equilibrium_guess(
1163
+ moments: npt.NDArray[np.float64],
1164
+ width: float,
1165
+ classes: int,
1166
+ dimension: int,
1167
+ ) -> npt.NDArray[np.float64]:
1168
+ """Return the exponents of the continuous Maxwellian of given moments, or a uniform density below order 2."""
1169
+ guess = np.zeros(moments.shape)
1170
+ total = moments[:, 0]
1171
+ if moments.shape[1] == dimension + PLANE:
1172
+ mean = moments[:, 1:-1] / total[:, None]
1173
+ squared = np.sum(mean**2, axis=1)
1174
+ spread = np.maximum((moments[:, -1] / total - squared) / dimension, width ** (2 / dimension))
1175
+ guess[:, 0] = np.log(total) - dimension * np.log(2 * np.pi * spread) / 2 - squared / (2 * spread)
1176
+ guess[:, 1:-1] = mean / spread[:, None]
1177
+ guess[:, -1] = -1 / (2 * spread)
1178
+ return guess
1179
+ guess[:, 0] = np.log(total / (classes * width))
1180
+ return guess
1181
+
1182
+ @staticmethod
1183
+ def _components(law: FluxLaw) -> list[object]:
1184
+ """Return the flux of every dimension of a flux law."""
1185
+ return list(law.flux) if isinstance(law.flux, FreeModuleElement | list | tuple) else [law.flux]
1186
+
1187
+ @staticmethod
1188
+ def _law_has_operators(law: BaseLaw) -> bool:
1189
+ """Check whether the value of a law, or a flux of a flux law, applies a differential operator."""
1190
+ if isinstance(law, FluxLaw):
1191
+ return any(FieldLowering._has_operators(SR(item)) for item in FieldLowering._components(law))
1192
+ return FieldLowering._has_operators(getattr(law, 'value', None))
1193
+
1194
+ @staticmethod
1195
+ def _over_positions(
1196
+ space: PhaseSpace,
1197
+ apply: Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]],
1198
+ ) -> Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]]:
1199
+ """Return an operator of the position lattice on values over the phase space that do not vary with class."""
1200
+ classes = space.size_ // space.position_size_
1201
+
1202
+ def over(values: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
1203
+ return np.repeat(apply(np.reshape(values, (space.position_size_, classes))[:, 0]), classes)
1204
+
1205
+ return over
1206
+
1207
+ @staticmethod
1208
+ def _transported_axes(space: LatticeSpace, name: str) -> tuple[int, ...] | None:
1209
+ """Return the axes a spectral operator of a phase space acts along, or `None` for all of them on a lattice."""
1210
+ if not isinstance(space, PhaseSpace):
1211
+ return None
1212
+ if name == 'inverse_helmholtz':
1213
+ return space.position_axes_
1214
+ return tuple(axis for axis in range(space.n_dim_) if space._axis_boundary(axis) == 'periodic')
1215
+
1216
+ @staticmethod
1217
+ def _tag(offset: IntTuple | int) -> str:
1218
+ """Return a name fragment for a lattice offset or a network neighbour slot."""
1219
+ if isinstance(offset, int):
1220
+ return f'k{offset}'
1221
+ return '_'.join(f'{"m" if step < 0 else "p"}{abs(step)}' for step in offset)
1222
+
1223
+ @staticmethod
1224
+ def _operator_calls(expression: Expression, name: str) -> list[Expression]:
1225
+ """Return the calls of an operator by name inside an expression."""
1226
+ found, stack = [], [SR(expression)]
1227
+ while stack:
1228
+ item = stack.pop()
1229
+ if item.operator() is None:
1230
+ continue
1231
+ if getattr(item.operator(), 'name', lambda: '')() == name:
1232
+ found.append(item)
1233
+ stack.extend(item.operands())
1234
+ return found
1235
+
1236
+ @staticmethod
1237
+ def _spectral_apply(
1238
+ multiplier: npt.NDArray[np.complex128],
1239
+ dimensions: tuple[int, ...],
1240
+ ) -> Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]]:
1241
+ """Return the function that applies a Fourier multiplier to the values of a periodic lattice.
1242
+
1243
+ Args:
1244
+ multiplier:
1245
+ The factor of every real Fourier mode.
1246
+
1247
+ dimensions:
1248
+ The lattice shape.
1249
+
1250
+ Returns:
1251
+ apply:
1252
+ The function of the values at every site.
1253
+ """
1254
+
1255
+ def apply(values: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
1256
+ transformed = np.fft.rfftn(np.reshape(values, dimensions)) * multiplier
1257
+ return np.fft.irfftn(transformed, s=dimensions, axes=range(len(dimensions))).ravel()
1258
+
1259
+ return apply
1260
+
1261
+ @staticmethod
1262
+ def _whole_sites(offset: list[Expression], spacings: tuple[float, ...]) -> IntTuple | None:
1263
+ """Return a displacement in whole sites when every component is a number of whole spacings, else `None`."""
1264
+ sites = []
1265
+ for item, step in zip(offset, spacings, strict=True):
1266
+ if SR(item).variables() or not SR(item).is_real():
1267
+ return None
1268
+ ratio = float(SR(item)) / step
1269
+ if abs(ratio - round(ratio)) > WHOLE_SITE:
1270
+ return None
1271
+ sites.append(round(ratio))
1272
+ return tuple(sites)
1273
+
1274
+ @staticmethod
1275
+ def _window_apply(
1276
+ window: npt.NDArray[np.float64],
1277
+ dimensions: tuple[int, ...],
1278
+ kind: str,
1279
+ fill: float,
1280
+ ) -> Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]]:
1281
+ """Return the function that convolves the values of a lattice with a centred window of weights.
1282
+
1283
+ Windows of at most `SMALL_KERNEL` sites per axis use a direct filter, and larger ones an overlap-add FFT of the
1284
+ values padded beyond the edges with the fixed value or their mirror image.
1285
+
1286
+ Args:
1287
+ window:
1288
+ The weights at the displacements from `-reach` to `reach` sites along every axis.
1289
+
1290
+ dimensions:
1291
+ The lattice shape.
1292
+
1293
+ kind:
1294
+ The boundary, `'periodic'`, `'zero-flux'`, or `'fixed'`.
1295
+
1296
+ fill:
1297
+ The value beyond fixed edges.
1298
+
1299
+ Returns:
1300
+ apply:
1301
+ The function of the values at every site.
1302
+ """
1303
+ reach = [(size // 2, size // 2) for size in window.shape]
1304
+
1305
+ def apply(values: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
1306
+ grid = np.reshape(values, dimensions)
1307
+ if max(window.shape) <= SMALL_KERNEL:
1308
+ return np.asarray(convolve(grid, window, mode=FILTER_MODES[kind], cval=fill)).ravel()
1309
+ if kind == 'fixed':
1310
+ padded = np.pad(grid, reach, mode='constant', constant_values=fill)
1311
+ else:
1312
+ padded = np.pad(grid, reach, mode='symmetric')
1313
+ return np.asarray(oaconvolve(padded, window, mode='valid')).ravel()
1314
+
1315
+ return apply
1316
+
1317
+ @staticmethod
1318
+ def _interpolated_apply(
1319
+ dimensions: tuple[int, ...],
1320
+ spacings: tuple[float, ...],
1321
+ kind: str,
1322
+ fill: float,
1323
+ order: int = 1,
1324
+ ) -> Callable[[npt.NDArray[np.float64], npt.NDArray[np.float64]], npt.NDArray[np.float64]]:
1325
+ """Return the function that reads the values of a lattice at displaced positions by spline interpolation.
1326
+
1327
+ Args:
1328
+ dimensions:
1329
+ The lattice shape.
1330
+
1331
+ spacings:
1332
+ The distance between sites along every axis.
1333
+
1334
+ kind:
1335
+ The boundary, `'periodic'`, `'zero-flux'`, or `'fixed'`.
1336
+
1337
+ fill:
1338
+ The value beyond fixed edges.
1339
+
1340
+ order:
1341
+ The order of the spline, 1 for linear or 3 for cubic.
1342
+
1343
+ Returns:
1344
+ apply:
1345
+ The function of the values and the displacement along every axis at every site.
1346
+ """
1347
+ sites = np.indices(dimensions).reshape(len(dimensions), -1).astype(float)
1348
+ steps = np.asarray(spacings, dtype=float)[:, None]
1349
+
1350
+ def apply(values: npt.NDArray[np.float64], offset: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
1351
+ grid = np.reshape(values, dimensions)
1352
+ positions = sites + np.reshape(offset, sites.shape) / steps
1353
+ return np.asarray(map_coordinates(grid, positions, order=order, mode=SHIFTED_MODES[kind], cval=fill))
1354
+
1355
+ return apply
1356
+
1357
+ @staticmethod
1358
+ def _lattice_inverse(
1359
+ space: LatticeSpace,
1360
+ screening: float,
1361
+ kind: str,
1362
+ fill: float,
1363
+ ) -> Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]]:
1364
+ """Return the function that inverts the lattice stencil of `laplacian - screening**2` by a fast transform.
1365
+
1366
+ Periodic edges use real FFTs, fixed edges the sine transform of type 1 with the fixed value lifted into the
1367
+ right-hand side, and zero-flux edges the cosine transform of type 2, each with the eigenvalues of the stencil.
1368
+ The mode of zero eigenvalue, the mean, is set to zero.
1369
+
1370
+ Args:
1371
+ space:
1372
+ The lattice.
1373
+
1374
+ screening:
1375
+ The screening, a non-negative number.
1376
+
1377
+ kind:
1378
+ The boundary, `'periodic'`, `'zero-flux'`, or `'fixed'`.
1379
+
1380
+ fill:
1381
+ The value beyond fixed edges.
1382
+
1383
+ Returns:
1384
+ apply:
1385
+ The function of the right-hand side at every site.
1386
+ """
1387
+ dimensions, spacings = space.shape_, space.spacings_
1388
+ if kind == 'periodic':
1389
+ waves = FieldLowering._wavenumbers(dimensions, spacings)
1390
+ eigenvalues = sum(
1391
+ ((2 * np.cos(wave * step) - 2) / step**2 for wave, step in zip(waves, spacings, strict=True)),
1392
+ np.zeros(waves[0].shape),
1393
+ )
1394
+ denominator = eigenvalues - screening**2
1395
+ nonzero = np.abs(denominator) > 0
1396
+ multiplier = np.where(nonzero, 1.0 / np.where(nonzero, denominator, 1.0), 0.0).astype(complex)
1397
+ return FieldLowering._spectral_apply(multiplier, dimensions)
1398
+ if kind == 'fixed':
1399
+ modes = [np.arange(1, size + 1) / (size + 1) for size in dimensions]
1400
+ else:
1401
+ modes = [np.arange(size) / size for size in dimensions]
1402
+ axes = [(2 * np.cos(np.pi * mode) - 2) / step**2 for mode, step in zip(modes, spacings, strict=True)]
1403
+ grids = np.meshgrid(*axes, indexing='ij')
1404
+ denominator = sum(grids, np.zeros(dimensions)) - screening**2
1405
+ nonzero = np.abs(denominator) > 0
1406
+ inverse = np.where(nonzero, 1.0 / np.where(nonzero, denominator, 1.0), 0.0)
1407
+ lift = np.zeros(dimensions)
1408
+ for axis, step in enumerate(spacings):
1409
+ edges = [slice(None)] * len(dimensions)
1410
+ for index in (0, -1):
1411
+ edges[axis] = slice(index, index + 1 if index == 0 else None)
1412
+ lift[tuple(edges)] += fill / step**2
1413
+ kind_number = 1 if kind == 'fixed' else 2
1414
+ transform = scipy.fft.dstn if kind == 'fixed' else scipy.fft.dctn
1415
+ backward = scipy.fft.idstn if kind == 'fixed' else scipy.fft.idctn
1416
+
1417
+ def apply(values: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
1418
+ right = np.reshape(values, dimensions) - (lift if kind == 'fixed' else 0.0)
1419
+ spectrum = transform(right, type=kind_number, norm='ortho') * inverse
1420
+ return np.asarray(backward(spectrum, type=kind_number, norm='ortho')).ravel()
1421
+
1422
+ return apply
1423
+
1424
+ @staticmethod
1425
+ def _grounded_solver(
1426
+ matrix: csr_matrix,
1427
+ free: npt.NDArray[np.intp],
1428
+ ) -> Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]]:
1429
+ """Return the function that solves a sparse system on its free rows, factorised once, zero on the others."""
1430
+ solve = factorized(matrix[free][:, free].tocsc())
1431
+ size = matrix.shape[0]
1432
+
1433
+ def apply(values: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
1434
+ solution = np.zeros(size)
1435
+ solution[free] = solve(np.asarray(values, dtype=float)[free])
1436
+ return solution
1437
+
1438
+ return apply
1439
+
1440
+ @staticmethod
1441
+ def _network_inverse(
1442
+ space: NetworkSpace,
1443
+ screening: float,
1444
+ ) -> Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]]:
1445
+ """Return the function that inverts the graph Laplacian minus `screening**2`, with zero mean when unscreened.
1446
+
1447
+ Args:
1448
+ space:
1449
+ The network.
1450
+
1451
+ screening:
1452
+ The screening, a non-negative number.
1453
+
1454
+ Returns:
1455
+ apply:
1456
+ The function of the right-hand side at every node.
1457
+ """
1458
+ table = space._index_table(AdjacencyNeighborhood())
1459
+ size = table.shape[0]
1460
+ rows = np.repeat(np.arange(size), table.shape[1])
1461
+ columns = table.ravel()
1462
+ inside = columns < size
1463
+ adjacency = csr_matrix((np.ones(inside.sum()), (rows[inside], columns[inside])), shape=(size, size))
1464
+ degrees = np.asarray(adjacency.sum(axis=1)).ravel()
1465
+ matrix = csr_matrix(adjacency - diags(degrees) - screening**2 * identity(size))
1466
+ if screening > 0:
1467
+ return FieldLowering._grounded_solver(matrix, np.arange(size))
1468
+ solve = FieldLowering._grounded_solver(matrix, np.arange(1, size))
1469
+
1470
+ def apply(values: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
1471
+ right = np.asarray(values, dtype=float)
1472
+ solution = solve(right - right.mean())
1473
+ return solution - solution.mean()
1474
+
1475
+ return apply
1476
+
1477
+ @staticmethod
1478
+ def _mesh_inverse(
1479
+ space: MeshSpace,
1480
+ screening: float,
1481
+ kind: str,
1482
+ fill: object,
1483
+ ) -> Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]]:
1484
+ """Return the function that inverts the lumped finite element Laplacian minus `screening**2` on a mesh.
1485
+
1486
+ It solves `(K + screening**2 M) psi = -M f` with the stiffness matrix `K` and the lumped mass `M`, with the
1487
+ fixed value on the boundary nodes of fixed edges and zero mean for unscreened zero-flux edges.
1488
+
1489
+ Args:
1490
+ space:
1491
+ The mesh.
1492
+
1493
+ screening:
1494
+ The screening, a non-negative number.
1495
+
1496
+ kind:
1497
+ The boundary, `'zero-flux'` or `'fixed'`.
1498
+
1499
+ fill:
1500
+ The value on the boundary nodes of fixed edges, a number or a function of the node coordinates.
1501
+
1502
+ Returns:
1503
+ apply:
1504
+ The function of the right-hand side at every node.
1505
+ """
1506
+ stiffness, lumped = FieldLowering._mesh_matrices(space)
1507
+ size = lumped.size
1508
+ matrix = csr_matrix(stiffness + screening**2 * diags(lumped))
1509
+ if kind == 'fixed':
1510
+ nodes = space.boundary_nodes_
1511
+ coordinates = space.positions_[nodes]
1512
+ fixed = np.zeros(size)
1513
+ fixed[nodes] = np.broadcast_to(fill(*coordinates.T) if callable(fill) else float(str(fill)), nodes.shape)
1514
+ free = np.setdiff1d(np.arange(size), nodes)
1515
+ solve = FieldLowering._grounded_solver(matrix, free)
1516
+ carried = matrix @ fixed
1517
+
1518
+ def apply(values: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
1519
+ return solve(-lumped * np.asarray(values, dtype=float) - carried) + fixed
1520
+
1521
+ return apply
1522
+ if screening > 0:
1523
+ solve = FieldLowering._grounded_solver(matrix, np.arange(size))
1524
+ return lambda values: solve(-lumped * np.asarray(values, dtype=float))
1525
+ solve = FieldLowering._grounded_solver(matrix, np.arange(1, size))
1526
+
1527
+ def apply_mean(values: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
1528
+ right = np.asarray(values, dtype=float)
1529
+ solution = solve(-lumped * (right - np.average(right, weights=lumped)))
1530
+ return solution - np.average(solution, weights=lumped)
1531
+
1532
+ return apply_mean
1533
+
1534
+ @staticmethod
1535
+ def _has_operators(expression: object) -> bool:
1536
+ """Check whether an expression applies a differential operator.
1537
+
1538
+ Args:
1539
+ expression:
1540
+ The expression.
1541
+
1542
+ Returns:
1543
+ found:
1544
+ Whether it calls one of `OPERATOR_NAMES`.
1545
+ """
1546
+ if not isinstance(expression, Expression):
1547
+ return False
1548
+ names = '|'.join(OPERATOR_NAMES)
1549
+ return bool(re.search(rf'\b({names})\(', str(expression)))
1550
+
1551
+ @staticmethod
1552
+ @functools.cache
1553
+ def _cached_mesh_matrices(
1554
+ points: bytes,
1555
+ cells: bytes,
1556
+ shape: tuple[int, int],
1557
+ cell_shape: tuple[int, int],
1558
+ ) -> tuple[csr_matrix, npt.NDArray[np.float64]]:
1559
+ """Return the stiffness matrix and the lumped mass of a mesh, cached by its nodes and cells."""
1560
+ nodes = np.frombuffer(points).reshape(shape)
1561
+ elements = np.frombuffer(cells, dtype=np.int64).reshape(cell_shape)
1562
+ space = MeshSpace(nodes, elements)
1563
+ basis = Basis(space.check().prepare().mesh_, ElementTriP1() if shape[0] == PLANE else ElementTetP1())
1564
+ stiffness = asm(laplace, basis).tocsr()
1565
+ lumped = np.asarray(asm(mass, basis).sum(axis=1)).ravel()
1566
+ return stiffness, lumped
1567
+
1568
+ @staticmethod
1569
+ def _mesh_matrices(space: MeshSpace) -> tuple[csr_matrix, npt.NDArray[np.float64]]:
1570
+ """Return the stiffness matrix and the lumped mass of the linear elements of a mesh.
1571
+
1572
+ Args:
1573
+ space:
1574
+ The mesh.
1575
+
1576
+ Returns:
1577
+ matrices:
1578
+ The stiffness matrix and the lumped mass of every node.
1579
+ """
1580
+ points = np.ascontiguousarray(np.asarray(space.points, dtype=float))
1581
+ cells = np.ascontiguousarray(np.asarray(space.cells, dtype=np.int64))
1582
+ return FieldLowering._cached_mesh_matrices(points.tobytes(), cells.tobytes(), points.shape, cells.shape)
1583
+
1584
+ @staticmethod
1585
+ def _mesh_laplacian(space: MeshSpace) -> csr_matrix:
1586
+ """Return the discrete Laplacian of linear elements with lumped mass, `-M^-1 K`, as a sparse matrix.
1587
+
1588
+ Args:
1589
+ space:
1590
+ The mesh.
1591
+
1592
+ Returns:
1593
+ laplacian:
1594
+ The sparse matrix that maps nodal values to the nodal Laplacian.
1595
+ """
1596
+ stiffness, lumped = FieldLowering._mesh_matrices(space)
1597
+ return -diags(1.0 / lumped) @ stiffness
1598
+
1599
+ @staticmethod
1600
+ @functools.cache
1601
+ def _wavenumbers(dimensions: tuple[int, ...], spacings: tuple[float, ...]) -> tuple[npt.NDArray[np.float64], ...]:
1602
+ """Return the angular wavenumbers of the real Fourier modes of a periodic lattice, broadcast along each axis."""
1603
+ axes = [2 * np.pi * np.fft.fftfreq(size, d=step) for size, step in zip(dimensions[:-1], spacings, strict=False)]
1604
+ axes.append(2 * np.pi * np.fft.rfftfreq(dimensions[-1], d=spacings[-1]))
1605
+ return tuple(np.meshgrid(*axes, indexing='ij'))
1606
+
1607
+ @staticmethod
1608
+ @functools.cache
1609
+ def _dealiasing_mask(dimensions: tuple[int, ...]) -> npt.NDArray[np.bool_]:
1610
+ """Return the Fourier modes the two-thirds rule keeps, below two thirds of the largest along every axis."""
1611
+ axes = [np.abs(np.fft.fftfreq(size, d=1.0 / size)) < size / 3 for size in dimensions[:-1]]
1612
+ axes.append(np.fft.rfftfreq(dimensions[-1], d=1.0 / dimensions[-1]) < dimensions[-1] / 3)
1613
+ grids = np.meshgrid(*axes, indexing='ij')
1614
+ return np.logical_and.reduce(grids)
1615
+
1616
+ @staticmethod
1617
+ def _spectral_multiplier(
1618
+ name: str,
1619
+ axis: int,
1620
+ dimensions: tuple[int, ...],
1621
+ spacings: tuple[float, ...],
1622
+ screening: float = 0.0,
1623
+ *,
1624
+ axes: tuple[int, ...] | None = None,
1625
+ ) -> npt.NDArray[np.complex128]:
1626
+ """Return the Fourier multiplier of an operator on a periodic lattice.
1627
+
1628
+ The Laplacian and its inverse act on every mode, so the Laplacian damps the Nyquist mode by `-|k|^2` like any
1629
+ other. A first derivative is zero at the Nyquist mode of its axis, and keeps only the modes of the two-thirds
1630
+ rule, which dealiases the derivatives of products.
1631
+
1632
+ Args:
1633
+ name:
1634
+ `'laplacian'`, `'partial'`, or `'inverse_helmholtz'`.
1635
+
1636
+ axis:
1637
+ The axis of a derivative.
1638
+
1639
+ dimensions:
1640
+ The lattice shape.
1641
+
1642
+ spacings:
1643
+ The distance between sites along every axis.
1644
+
1645
+ screening:
1646
+ The screening of the inverse Helmholtz operator.
1647
+
1648
+ axes:
1649
+ The axes the operator acts along, whose modes the two-thirds rule alone cuts, or `None` for every axis.
1650
+
1651
+ Returns:
1652
+ multiplier:
1653
+ The factor of every real Fourier mode.
1654
+ """
1655
+ waves = FieldLowering._wavenumbers(dimensions, spacings)
1656
+ squared = np.sum([waves[item] ** 2 for item in (range(len(waves)) if axes is None else axes)], axis=0)
1657
+ if name == 'laplacian':
1658
+ return -squared.astype(complex)
1659
+ if name == 'inverse_helmholtz':
1660
+ screened = squared + screening**2
1661
+ return np.where(screened > 0, -1.0 / np.where(screened > 0, screened, 1.0), 0.0).astype(complex)
1662
+ factor = 1j * waves[axis]
1663
+ if dimensions[axis] % 2 == 0:
1664
+ nyquist = np.isclose(np.abs(waves[axis]), np.pi / spacings[axis])
1665
+ factor = np.where(nyquist, 0.0, factor)
1666
+ if axes is None:
1667
+ return np.where(FieldLowering._dealiasing_mask(dimensions), factor, 0.0)
1668
+ return np.where(np.abs(waves[axis]) * spacings[axis] < 2 * np.pi / 3, factor, 0.0)