pathsim 0.28.0__tar.gz → 0.29.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pathsim-0.28.0 → pathsim-0.29.0}/PKG-INFO +1 -1
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/__init__.py +1 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/_version.py +3 -3
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/__init__.py +1 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/_block.py +2 -34
- pathsim-0.29.0/src/pathsim/blocks/splitter.py +124 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/connection.py +31 -9
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/optim/linearization.py +24 -8
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/simulation.py +24 -23
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/subsystem.py +10 -1
- pathsim-0.29.0/src/pathsim/utils/carrier.py +213 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/utils/graph.py +7 -4
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/utils/portreference.py +34 -10
- pathsim-0.29.0/src/pathsim/utils/register.py +298 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim.egg-info/PKG-INFO +1 -1
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim.egg-info/SOURCES.txt +6 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim.egg-info/scm_file_list.json +6 -0
- pathsim-0.29.0/src/pathsim.egg-info/scm_version.json +8 -0
- pathsim-0.29.0/tests/pathsim/blocks/test_splitter.py +154 -0
- pathsim-0.29.0/tests/pathsim/test_simulation_steadystate_recovery.py +94 -0
- pathsim-0.29.0/tests/pathsim/test_subsystem_current_inputs.py +63 -0
- pathsim-0.29.0/tests/pathsim/utils/test_carrier.py +365 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/utils/test_register.py +19 -0
- pathsim-0.28.0/src/pathsim/utils/register.py +0 -190
- pathsim-0.28.0/src/pathsim.egg-info/scm_version.json +0 -8
- {pathsim-0.28.0 → pathsim-0.29.0}/.codecov.yml +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/.github/FUNDING.yml +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/.github/pull_request_template.md +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/.github/workflows/pypi_deployment.yml +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/.github/workflows/tests_codecov.yml +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/.github/workflows/urlchecker.yml +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/.gitignore +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/CITATION.cff +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/CONTRIBUTING.md +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/LICENSE.txt +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/README.md +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/conftest.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/abs_braking.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/algebraic_loop.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/billards.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/bouncing_ball.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/bouncing_pendulum.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/cascade_controller.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/checkpoints.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/chemical_reactor.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/coupled_oscillators.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/data/BouncingBall_ME.fmu +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/data/CoupledClutches_CS_linux64.fmu +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/data/CoupledClutches_CS_win64.fmu +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/data/Dahlquist.fmu +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/data/VanDerPol_ME.fmu +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/dcmotor_control.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/delta_sigma_adc.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/diode_circuit.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/elastic_pendulum.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/algebraicloop_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/billard_circle_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/bouncing_ball_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/bouncing_ball_both_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/bouncing_ball_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/bouncing_ball_result_events_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/bouncing_ball_result_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/bouncing_ball_result_timesteps_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/bouncing_pendulum_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/cascade_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/coupled_oscillators_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/coupled_oscillators_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/delta_sigma_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/diode_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/elastic_pendulum_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/fmcw_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/fmcw_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/harmonic_oscillator_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/harmonic_oscillator_result_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/kalman_filter_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/linear_feedback_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/linear_feedback_result_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/linear_feedback_result_sensitivity_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/miller_frequency_divider_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/nonlinear_noisy_amplifier_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/ode_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/pendulum_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/pid_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/sar_adc_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/stick_slip_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/stick_slip_blockdiagram_slip_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/stick_slip_blockdiagram_stick_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/stick_slip_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/thermostat_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/vanderpol_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/vanderpol_result_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/vanderpol_subsystem_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/vanderpol_subsystem_lvl1_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/vanderpol_subsystem_lvl2_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/vanderpol_subsystem_lvl3_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/figures_g/volterralotka_blockdiagram_g.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/ode_blockdiagram_2.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/stick_slip_blockdiagram_slip.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/figures/stick_slip_blockdiagram_stick.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/fmcw_radar.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/fmu_cosimulation.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/fmu_model_exchange_bouncing_ball.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/fmu_model_exchange_vanderpol.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/harmonic_oscillator.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/kalman_filter.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/linear_feedback.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/lorenz_attractor.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/nested_subsystems.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/noisy_amplifier.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/pendulum.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/pid_controller.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/poincare_maps.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/rf_network_oneport.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/sar_adc.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/spectrum_analysis.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/stick_slip.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/switched_bouncing_ball.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/thermostat.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/transfer_function.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/examples/vanderpol.ipynb +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/logos/pathsim_icon.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/logos/pathsim_logo.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/logos/pathsim_simplistic_logo.png +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/docs/source/pathsim_docs.mplstyle +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_abs_braking.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_adc.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_algebraicchain.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_algebraicloop.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_cascade.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_dcmotor.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_deltasigma.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_derivative.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_diode.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_dualslope.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_elastic_pendulum.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_feedback.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_filters.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_harmonic_oscillator.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_kalman_filter.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_nested_subsystems.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_noise.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_pendulum.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_phasenoise.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_pid.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_pid_antiwindup.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_pid_vs_discretePID.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_radar.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_reactor.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_sar.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_solar.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_solver_hotswap.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_spectrum.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_spectrum_rf_oneport.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_steadystate.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_stickslip.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_transferfunction.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/example_vanderpol_subsystem.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_event/example_billards_sphere.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_event/example_bouncing_pendulum.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_event/example_bouncingball.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_event/example_bouncingball_friction.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_event/example_bouncingball_switched.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_event/example_integrator_reset.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_event/example_pulse.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_event/example_stickslip_event.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_event/example_thermostat.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_event/example_volterralotka_event.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_bonhoeffer_vanderpol.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_brusselator.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_chemical.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_duffing.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_fairen_velarde.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_fitzhughnagumo.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_flame.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_glycolysis.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_lorenz.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_morse.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_robertson.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_roessler.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_thomas_cyclic.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_vanderpol.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/examples/examples_odes/example_volterralotka.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/git +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/pyproject.toml +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/setup.cfg +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/_constants.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/README.md +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/adder.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/amplifier.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/bvp.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/comparator.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/constraint.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/converters.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/counter.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/ctrl.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/dae.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/delay.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/differentiator.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/discrete.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/divider.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/dynsys.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/filters.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/fmu.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/function.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/integrator.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/kalman.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/logic.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/lti.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/math.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/multiplier.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/noise.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/ode.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/relay.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/rf.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/rng.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/scope.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/sources.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/spectrum.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/switch.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/table.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/blocks/wrapper.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/events/__init__.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/events/_event.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/events/condition.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/events/schedule.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/events/zerocrossing.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/exceptions.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/optim/__init__.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/optim/anderson.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/optim/booster.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/optim/jacobian.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/optim/newton.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/optim/numerical.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/optim/operator.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/README.md +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/__init__.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/_rungekutta.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/_solver.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/bdf.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/dirk2.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/dirk3.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/esdirk32.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/esdirk4.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/esdirk43.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/esdirk54.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/esdirk85.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/euler.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/gear.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/rk4.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/rkbs32.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/rkck54.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/rkdp54.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/rkdp87.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/rkf21.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/rkf45.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/rkf78.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/rkv65.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/ssprk22.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/ssprk33.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/ssprk34.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/solvers/steadystate.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/utils/__init__.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/utils/adaptivebuffer.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/utils/analysis.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/utils/deprecation.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/utils/diagnostics.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/utils/fmuwrapper.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/utils/gilbert.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/utils/logger.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/utils/mutable.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/utils/progresstracker.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim/utils/realtimeplotter.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim.egg-info/dependency_links.txt +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim.egg-info/requires.txt +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/src/pathsim.egg-info/top_level.txt +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/README.md +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/__init__.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/CoupledClutches_CS.fmu +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/__init__.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/conftest.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_algebraic_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_bouncingball_friction_event_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_bouncingball_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_brusselator_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_cosim_fmu_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_counter_comparator_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_dynamical_system_ivp.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_fitzhughnagumo_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_harmonic_oscillator_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_linear_feedback_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_logic_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_lorenz_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_me_analytical.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_model_exchange_fmu_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_pid_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_relay_thermostat_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_rescale_delay_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_robertson_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_roessler_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_signal_processing_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_steadystate_transient_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_switch_lti_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_vanderpol_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/evals/test_volterralotka_system.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/__init__.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/__init__.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/_embedding.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/rf/__init__.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/rf/ring_slot.s2p +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/rf/ring_slot_meas.s1p +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/rf/test_rf.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_adder.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_amplifier.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_block.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_bvp.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_comparator.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_constraint.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_converters.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_counter.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_ctrl.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_dae.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_delay.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_delay_channels.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_differentiator.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_discrete.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_divider.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_dynsys.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_filters.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_fmu.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_function.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_integrator.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_kalman.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_logic.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_lti.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_math.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_multiplier.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_noise.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_ode.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_relay.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_rng.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_scope.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_sources.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_sparsedae.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_spectrum.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_switch.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_table.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/blocks/test_wrapper.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/events/__init__.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/events/test_condition.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/events/test_event.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/events/test_schedule.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/events/test_zerocrossing.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/optim/__init__.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/optim/test_anderson.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/optim/test_linearization.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/optim/test_newton.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/optim/test_numerical.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/optim/test_operator.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/optim/test_sparse_newton.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/__init__.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/_referenceproblems.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_bdf.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_dirk2.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_dirk3.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_esdirk32.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_esdirk4.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_esdirk43.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_esdirk54.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_esdirk85.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_euler.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_gear.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_rfk21.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_rk4.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_rkbs32.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_rkck54.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_rkdp54.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_rkdp87.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_rkf45.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_rkf78.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_rkv65.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_solver.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_ssprk22.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_ssprk33.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_ssprk34.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/solvers/test_steadystate.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/test_auto_initial_step.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/test_checkpoint.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/test_connection.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/test_diagnostics.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/test_simulation.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/test_simulation_pss.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/test_subsystem.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/utils/__init__.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/utils/test_adaptivebuffer.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/utils/test_analysis.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/utils/test_fmuwrapper.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/utils/test_gilbert.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/utils/test_graph.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/utils/test_logger.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/utils/test_mutable.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/utils/test_portreference.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/utils/test_progresstracker.py +0 -0
- {pathsim-0.28.0 → pathsim-0.29.0}/tests/pathsim/utils/test_realtimeplotter.py +0 -0
|
@@ -8,5 +8,6 @@ except Exception:
|
|
|
8
8
|
from .simulation import Simulation
|
|
9
9
|
from .connection import Connection, Duplex
|
|
10
10
|
from .subsystem import Subsystem, Interface
|
|
11
|
+
from .utils.carrier import Carrier, Vector
|
|
11
12
|
from .utils.logger import LoggerManager
|
|
12
13
|
from .exceptions import StopSimulation
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.
|
|
22
|
-
__version_tuple__ = version_tuple = (0,
|
|
21
|
+
__version__ = version = '0.29.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 29, 0)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g220bc787c'
|
|
@@ -22,32 +22,6 @@ from ..optim.operator import DynamicOperator
|
|
|
22
22
|
from ..exceptions import LinearizationError
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
# HELPERS ===============================================================================
|
|
26
|
-
|
|
27
|
-
def _labels_size(labels):
|
|
28
|
-
"""Minimum register size required to hold all declared port labels.
|
|
29
|
-
|
|
30
|
-
Port labels map string aliases to integer port indices. The register has
|
|
31
|
-
to be large enough to address the highest declared index, otherwise blocks
|
|
32
|
-
with unconnected declared ports (e.g. a multi-input block placed without
|
|
33
|
-
connections) would default to the size 1 register and break positional
|
|
34
|
-
input access.
|
|
35
|
-
|
|
36
|
-
Parameters
|
|
37
|
-
----------
|
|
38
|
-
labels : dict[str: int] | None
|
|
39
|
-
port label mapping (alias -> index)
|
|
40
|
-
|
|
41
|
-
Returns
|
|
42
|
-
-------
|
|
43
|
-
size : int | None
|
|
44
|
-
minimum register size, or None if no labels are declared
|
|
45
|
-
"""
|
|
46
|
-
if not labels:
|
|
47
|
-
return None
|
|
48
|
-
return max(labels.values()) + 1
|
|
49
|
-
|
|
50
|
-
|
|
51
25
|
# BASE BLOCK CLASS ======================================================================
|
|
52
26
|
|
|
53
27
|
class Block:
|
|
@@ -123,14 +97,8 @@ class Block:
|
|
|
123
97
|
|
|
124
98
|
#registers to hold input and output values, pre-sized to the declared
|
|
125
99
|
#port labels so blocks with unconnected ports are still addressable
|
|
126
|
-
self.inputs = Register(
|
|
127
|
-
|
|
128
|
-
mapping=self.input_port_labels and self.input_port_labels.copy()
|
|
129
|
-
)
|
|
130
|
-
self.outputs = Register(
|
|
131
|
-
size=_labels_size(self.output_port_labels),
|
|
132
|
-
mapping=self.output_port_labels and self.output_port_labels.copy()
|
|
133
|
-
)
|
|
100
|
+
self.inputs = Register(mapping=self.input_port_labels)
|
|
101
|
+
self.outputs = Register(mapping=self.output_port_labels)
|
|
134
102
|
|
|
135
103
|
#initialize integration engine as 'None' by default
|
|
136
104
|
self.engine = None
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#########################################################################################
|
|
2
|
+
##
|
|
3
|
+
## SPLITTER BLOCK
|
|
4
|
+
## (blocks/splitter.py)
|
|
5
|
+
##
|
|
6
|
+
#########################################################################################
|
|
7
|
+
|
|
8
|
+
# IMPORTS ===============================================================================
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
from ._block import Block
|
|
13
|
+
from ..optim.operator import Operator
|
|
14
|
+
from ..utils.carrier import Carrier, Vector
|
|
15
|
+
from ..utils.mutable import mutable
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# SIMO BLOCKS ===========================================================================
|
|
19
|
+
|
|
20
|
+
@mutable
|
|
21
|
+
class Splitter(Block):
|
|
22
|
+
"""Splits the input into multiple outputs, weighted with fractions (SIMO).
|
|
23
|
+
|
|
24
|
+
.. math::
|
|
25
|
+
|
|
26
|
+
y_i(t) = f_i \\cdot u(t)
|
|
27
|
+
|
|
28
|
+
The fractions have to sum up to one, so the splitter conserves what flows
|
|
29
|
+
through it, for example a mass or molar flow.
|
|
30
|
+
|
|
31
|
+
With a carrier, the input is a stream of multiple channels, for example
|
|
32
|
+
the flows of multiple species. Every output is a stream with the same
|
|
33
|
+
layout and each channel is split with the same fractions.
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
Example
|
|
37
|
+
-------
|
|
38
|
+
Split a flow into two outputs with 90 and 10 percent:
|
|
39
|
+
|
|
40
|
+
.. code-block:: python
|
|
41
|
+
|
|
42
|
+
S = Splitter([0.9, 0.1])
|
|
43
|
+
|
|
44
|
+
Split a stream of species flows, the ports 'in', 'out_0' and 'out_1'
|
|
45
|
+
have the layout of the carrier:
|
|
46
|
+
|
|
47
|
+
.. code-block:: python
|
|
48
|
+
|
|
49
|
+
class Species(Carrier):
|
|
50
|
+
keys = ("H", "D", "T")
|
|
51
|
+
|
|
52
|
+
S = Splitter([0.9, 0.1], carrier=Species())
|
|
53
|
+
|
|
54
|
+
C = Connection(S["out_1"], B["in"])
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
Note
|
|
58
|
+
----
|
|
59
|
+
This block is purely algebraic and its operation (`op_alg`) will be called
|
|
60
|
+
multiple times per timestep, each time when `Simulation._update(t)` is
|
|
61
|
+
called in the global simulation loop.
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
fractions : array_like
|
|
67
|
+
fractions of the input for each output, must sum up to one
|
|
68
|
+
carrier : Carrier | None
|
|
69
|
+
layout of the input and output streams, single channel if 'None'
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
Attributes
|
|
73
|
+
----------
|
|
74
|
+
op_alg : Operator
|
|
75
|
+
internal algebraic operator
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
input_port_labels = {"in": 0}
|
|
79
|
+
output_port_labels = None
|
|
80
|
+
|
|
81
|
+
def __init__(self, fractions=None, carrier=None):
|
|
82
|
+
|
|
83
|
+
self.fractions = np.ones(1) if fractions is None else np.asarray(fractions, dtype=float)
|
|
84
|
+
self.carrier = carrier
|
|
85
|
+
|
|
86
|
+
#input validation
|
|
87
|
+
if not np.isclose(np.sum(self.fractions), 1.0):
|
|
88
|
+
raise ValueError(f"'fractions' must sum up to one but sum up to {np.sum(self.fractions)}!")
|
|
89
|
+
|
|
90
|
+
#ports with the layout of the carrier, placed one after another
|
|
91
|
+
n = 1 if carrier is None else len(carrier)
|
|
92
|
+
|
|
93
|
+
def _port(start):
|
|
94
|
+
if carrier is None:
|
|
95
|
+
return start
|
|
96
|
+
if carrier.keys:
|
|
97
|
+
return Carrier(start, keys=carrier.keys)
|
|
98
|
+
return Vector(n, start)
|
|
99
|
+
|
|
100
|
+
self.input_port_labels = {"in": _port(0)}
|
|
101
|
+
self.output_port_labels = {
|
|
102
|
+
f"out_{i}": _port(i * n) for i in range(len(self.fractions))
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
super().__init__()
|
|
106
|
+
|
|
107
|
+
#every channel of the input split with the same fractions
|
|
108
|
+
self.op_alg = Operator(
|
|
109
|
+
func=lambda u: np.kron(self.fractions, u),
|
|
110
|
+
jac=lambda u: np.kron(self.fractions.reshape(-1, 1), np.eye(len(u)))
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def update(self, t):
|
|
115
|
+
"""update system equation
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
t : float
|
|
120
|
+
evaluation time
|
|
121
|
+
"""
|
|
122
|
+
u = self.inputs.to_array()
|
|
123
|
+
y = self.op_alg(u)
|
|
124
|
+
self.outputs.update_from_array(y)
|
|
@@ -138,9 +138,12 @@ class Connection:
|
|
|
138
138
|
----------
|
|
139
139
|
_active : bool
|
|
140
140
|
flag to set 'Connection' as active or inactive
|
|
141
|
+
_transfers : list[tuple[Block, int | np.ndarray, int | np.ndarray]] | None
|
|
142
|
+
resolved data transfers to the targets as tuples of target block,
|
|
143
|
+
target and source channel indices, built by 'resolve_ports'
|
|
141
144
|
"""
|
|
142
145
|
|
|
143
|
-
__slots__ = ["source", "targets", "_active"]
|
|
146
|
+
__slots__ = ["source", "targets", "_active", "_transfers"]
|
|
144
147
|
|
|
145
148
|
|
|
146
149
|
def __init__(self, source, *targets):
|
|
@@ -153,6 +156,9 @@ class Connection:
|
|
|
153
156
|
|
|
154
157
|
#flag to set connection active
|
|
155
158
|
self._active = True
|
|
159
|
+
|
|
160
|
+
#resolved data transfers (lazily initialized)
|
|
161
|
+
self._transfers = None
|
|
156
162
|
|
|
157
163
|
#validate port aliases
|
|
158
164
|
self._validate_ports()
|
|
@@ -169,8 +175,10 @@ class Connection:
|
|
|
169
175
|
|
|
170
176
|
|
|
171
177
|
def __len__(self):
|
|
172
|
-
"""Returns the number of
|
|
173
|
-
|
|
178
|
+
"""Returns the number of channels that are defined in the connection,
|
|
179
|
+
ports that are carriers count with all of their channels
|
|
180
|
+
"""
|
|
181
|
+
return len(self.source.block.outputs._resolve(self.source.ports))
|
|
174
182
|
|
|
175
183
|
|
|
176
184
|
def __bool__(self):
|
|
@@ -199,9 +207,9 @@ class Connection:
|
|
|
199
207
|
"""Check the dimensions of the source and target ports,
|
|
200
208
|
if they dont match, raises an exception.
|
|
201
209
|
"""
|
|
202
|
-
n_src = len(self
|
|
210
|
+
n_src = len(self)
|
|
203
211
|
for trg in self.targets:
|
|
204
|
-
if len(trg) != n_src:
|
|
212
|
+
if len(trg.block.inputs._resolve(trg.ports)) != n_src:
|
|
205
213
|
raise ValueError(f"Source and target have different number of ports!")
|
|
206
214
|
|
|
207
215
|
|
|
@@ -245,8 +253,12 @@ class Connection:
|
|
|
245
253
|
"""Transfers data from the source block output port
|
|
246
254
|
to the target block input port.
|
|
247
255
|
"""
|
|
248
|
-
|
|
249
|
-
self.
|
|
256
|
+
if self._transfers is None:
|
|
257
|
+
self.resolve_ports()
|
|
258
|
+
|
|
259
|
+
_data = self.source.block.outputs._data
|
|
260
|
+
for block, i_trg, i_src in self._transfers:
|
|
261
|
+
block.inputs._data[i_trg] = _data[i_src]
|
|
250
262
|
|
|
251
263
|
|
|
252
264
|
def resolve_ports(self):
|
|
@@ -267,10 +279,20 @@ class Connection:
|
|
|
267
279
|
Calling ``resolve_ports`` once during graph assembly closes that
|
|
268
280
|
gap. Idempotent. New register slots are zero-initialised through
|
|
269
281
|
``np.zeros`` in ``Register.resize``.
|
|
282
|
+
|
|
283
|
+
The resolved indices are stored as data transfers for ``update``,
|
|
284
|
+
transfers of a single channel use plain integer indices, which is
|
|
285
|
+
faster than fancy indexing with an index array.
|
|
270
286
|
"""
|
|
271
|
-
self.source._get_output_indices()
|
|
287
|
+
i_src = self.source._get_output_indices()
|
|
288
|
+
|
|
289
|
+
self._transfers = []
|
|
272
290
|
for trg in self.targets:
|
|
273
|
-
trg._get_input_indices()
|
|
291
|
+
i_trg = trg._get_input_indices()
|
|
292
|
+
if len(i_trg) == 1:
|
|
293
|
+
self._transfers.append((trg.block, int(i_trg[0]), int(i_src[0])))
|
|
294
|
+
else:
|
|
295
|
+
self._transfers.append((trg.block, i_trg, i_src))
|
|
274
296
|
|
|
275
297
|
|
|
276
298
|
@deprecated(version="1.0.0")
|
|
@@ -69,28 +69,44 @@ def _state_labels(x_layout, keys):
|
|
|
69
69
|
return labels
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
def _port_labels(port_refs, keys):
|
|
73
|
-
"""One label per resolved
|
|
72
|
+
def _port_labels(port_refs, keys, inputs=True):
|
|
73
|
+
"""One label per resolved channel across a list of 'PortReference', in the
|
|
74
74
|
same order as the assembled 'B' columns or 'C' and 'D' rows.
|
|
75
75
|
|
|
76
|
+
Ports that are carriers get one label per channel, named by the channel
|
|
77
|
+
key or by the channel position for carriers without keys.
|
|
78
|
+
|
|
76
79
|
Parameters
|
|
77
80
|
----------
|
|
78
81
|
port_refs : list[PortReference]
|
|
79
82
|
break points or tap points
|
|
80
83
|
keys : dict[Block: str]
|
|
81
84
|
canonical identifiers from '_block_keys'
|
|
85
|
+
inputs : bool
|
|
86
|
+
resolve the ports in the block inputs, otherwise in the block outputs
|
|
82
87
|
|
|
83
88
|
Returns
|
|
84
89
|
-------
|
|
85
90
|
labels : list[str]
|
|
86
|
-
one label per
|
|
91
|
+
one label per channel
|
|
87
92
|
"""
|
|
88
93
|
labels = []
|
|
89
94
|
for pr in port_refs:
|
|
90
|
-
|
|
95
|
+
register = pr.block.inputs if inputs else pr.block.outputs
|
|
96
|
+
|
|
97
|
+
#single channel -> block identifier only
|
|
98
|
+
if len(register._resolve(pr.ports)) == 1:
|
|
91
99
|
labels.append(keys[pr.block])
|
|
92
|
-
|
|
93
|
-
|
|
100
|
+
continue
|
|
101
|
+
|
|
102
|
+
for p in pr.ports:
|
|
103
|
+
carrier = register._carriers.get(p) if isinstance(p, str) else None
|
|
104
|
+
if carrier is None:
|
|
105
|
+
name = f"{p[0]}.{p[1]}" if isinstance(p, tuple) else p
|
|
106
|
+
labels.append(f"{keys[pr.block]}[{name}]")
|
|
107
|
+
else:
|
|
108
|
+
names = carrier.keys or range(len(carrier))
|
|
109
|
+
labels.extend(f"{keys[pr.block]}[{p}.{k}]" for k in names)
|
|
94
110
|
return labels
|
|
95
111
|
|
|
96
112
|
|
|
@@ -305,6 +321,6 @@ def assemble_statespace(blocks, connections, inputs, outputs, t):
|
|
|
305
321
|
return (
|
|
306
322
|
A, B, C, D,
|
|
307
323
|
_state_labels(x_layout, keys),
|
|
308
|
-
_port_labels(inputs, keys),
|
|
309
|
-
_port_labels(outputs, keys)
|
|
324
|
+
_port_labels(inputs, keys, inputs=True),
|
|
325
|
+
_port_labels(outputs, keys, inputs=False)
|
|
310
326
|
)
|
|
@@ -1260,29 +1260,30 @@ class Simulation:
|
|
|
1260
1260
|
#log message begin of steady state solver
|
|
1261
1261
|
self.logger.info(f"STEADYSTATE -> STARTING (reset: {reset})")
|
|
1262
1262
|
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
evals, iters
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
success, evals, iters,
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1263
|
+
try:
|
|
1264
|
+
#solve for steady state at current time
|
|
1265
|
+
with Timer(verbose=False) as T:
|
|
1266
|
+
success, evals, iters = self._solve(self.time, self.dt)
|
|
1267
|
+
|
|
1268
|
+
#catch non convergence
|
|
1269
|
+
if not success:
|
|
1270
|
+
details = self._solve_tracker.details(lambda b: b.__class__.__name__)
|
|
1271
|
+
_msg = "STEADYSTATE -> FAILED (evals: {}, iters: {}, runtime: {})\n{}".format(
|
|
1272
|
+
evals, iters, T, "\n".join(details))
|
|
1273
|
+
self.logger.error(_msg)
|
|
1274
|
+
raise RuntimeError(_msg)
|
|
1275
|
+
|
|
1276
|
+
#sample result
|
|
1277
|
+
self._sample(self.time, self.dt)
|
|
1278
|
+
|
|
1279
|
+
#log message
|
|
1280
|
+
self.logger.info(
|
|
1281
|
+
"STEADYSTATE -> FINISHED (success: {}, evals: {}, iters: {}, runtime: {})".format(
|
|
1282
|
+
success, evals, iters, T)
|
|
1283
|
+
)
|
|
1284
|
+
finally:
|
|
1285
|
+
#restore the transient solver even if solving or sampling fails
|
|
1286
|
+
self._set_solver(_solver)
|
|
1286
1287
|
|
|
1287
1288
|
|
|
1288
1289
|
# initial timestep estimation -------------------------------------------------
|
|
@@ -786,6 +786,9 @@ class Subsystem(Block):
|
|
|
786
786
|
if not _blocks_dyn:
|
|
787
787
|
return None
|
|
788
788
|
|
|
789
|
+
#the parent may have supplied new inputs after evaluating our outputs
|
|
790
|
+
self.update(t)
|
|
791
|
+
|
|
789
792
|
_derivatives = []
|
|
790
793
|
for b in _blocks_dyn:
|
|
791
794
|
_d = b.derivative(t)
|
|
@@ -928,6 +931,9 @@ class Subsystem(Block):
|
|
|
928
931
|
max_error : float
|
|
929
932
|
maximum error of implicit update equaiton
|
|
930
933
|
"""
|
|
934
|
+
#refresh internal inputs for the current implicit stage
|
|
935
|
+
self.update(t)
|
|
936
|
+
|
|
931
937
|
max_error = 0.0
|
|
932
938
|
for block in self._blocks_dyn:
|
|
933
939
|
if not block: continue
|
|
@@ -963,6 +969,9 @@ class Subsystem(Block):
|
|
|
963
969
|
rescale factor for timestep
|
|
964
970
|
"""
|
|
965
971
|
|
|
972
|
+
#refresh internal inputs for the current explicit stage
|
|
973
|
+
self.update(t)
|
|
974
|
+
|
|
966
975
|
#initial timestep rescale and error estimate
|
|
967
976
|
success, max_error_norm, min_scale = True, 0.0, None
|
|
968
977
|
|
|
@@ -1045,4 +1054,4 @@ class Subsystem(Block):
|
|
|
1045
1054
|
evaluation time for buffering
|
|
1046
1055
|
"""
|
|
1047
1056
|
for block in self._blocks_dyn:
|
|
1048
|
-
if block: block.buffer(dt)
|
|
1057
|
+
if block: block.buffer(dt)
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
#########################################################################################
|
|
2
|
+
##
|
|
3
|
+
## CARRIER CLASS
|
|
4
|
+
## (utils/carrier.py)
|
|
5
|
+
##
|
|
6
|
+
## This module defines the 'Carrier' class that groups multiple
|
|
7
|
+
## scalar channels of a block register into a single named entity
|
|
8
|
+
##
|
|
9
|
+
#########################################################################################
|
|
10
|
+
|
|
11
|
+
# CLASSES ===============================================================================
|
|
12
|
+
|
|
13
|
+
class Carrier:
|
|
14
|
+
"""Named range of scalar channels of a block register.
|
|
15
|
+
|
|
16
|
+
A carrier describes a contiguous block of channels and gives each of them
|
|
17
|
+
a name. It is placed at an explicit position ('start') in the register of
|
|
18
|
+
a block and used as the value of a port label
|
|
19
|
+
|
|
20
|
+
.. code-block:: python
|
|
21
|
+
|
|
22
|
+
_in_1 = Carrier(keys=("F", "T"))
|
|
23
|
+
_in_2 = Carrier(_in_1.stop, keys=("F", "T"))
|
|
24
|
+
|
|
25
|
+
class Mixer(Block):
|
|
26
|
+
input_port_labels = {"in_1": _in_1, "in_2": _in_2}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
The carrier only exists while the system graph is assembled. Component
|
|
30
|
+
access resolves to plain integer indices, either by attribute or by key
|
|
31
|
+
|
|
32
|
+
.. code-block:: python
|
|
33
|
+
|
|
34
|
+
_in_1.F # -> 0
|
|
35
|
+
_in_1["T"] # -> 1
|
|
36
|
+
_in_1[1] # -> 1
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
so the values themselves stay in the flat float64 register of the block
|
|
40
|
+
and nothing carrier specific is left at runtime
|
|
41
|
+
|
|
42
|
+
.. code-block:: python
|
|
43
|
+
|
|
44
|
+
def func(u):
|
|
45
|
+
return u[_in_1.F] + u[_in_2.F]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
Note
|
|
49
|
+
----
|
|
50
|
+
Carriers are addressed as a whole when blocks are connected, a connection
|
|
51
|
+
to a carrier port transfers all its channels at once.
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
Parameters
|
|
55
|
+
----------
|
|
56
|
+
start : int
|
|
57
|
+
index of the first channel in the register of the block
|
|
58
|
+
keys : tuple[str] | list[str] | None
|
|
59
|
+
names of the channels, overrides the class level 'keys'
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
Attributes
|
|
63
|
+
----------
|
|
64
|
+
keys : tuple[str]
|
|
65
|
+
names of the channels
|
|
66
|
+
start : int
|
|
67
|
+
index of the first channel
|
|
68
|
+
stop : int
|
|
69
|
+
index after the last channel
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
keys = ()
|
|
73
|
+
|
|
74
|
+
#names that would collide with the carrier interface itself
|
|
75
|
+
_reserved = ("keys", "start", "stop", "size", "slice")
|
|
76
|
+
|
|
77
|
+
def __init__(self, start=0, keys=None):
|
|
78
|
+
|
|
79
|
+
#channel names, from the arguments or from the class
|
|
80
|
+
if keys is not None:
|
|
81
|
+
self.keys = tuple(keys)
|
|
82
|
+
|
|
83
|
+
#key validation
|
|
84
|
+
for key in self.keys:
|
|
85
|
+
if not isinstance(key, str):
|
|
86
|
+
raise ValueError(f"Key '{key}' must be str but is '{type(key)}'!")
|
|
87
|
+
if key in self._reserved or key.startswith("_"):
|
|
88
|
+
raise ValueError(f"Key '{key}' is reserved!")
|
|
89
|
+
if len(set(self.keys)) < len(self.keys):
|
|
90
|
+
raise ValueError("Keys must be unique!")
|
|
91
|
+
|
|
92
|
+
#position validation
|
|
93
|
+
if not isinstance(start, int) or start < 0:
|
|
94
|
+
raise ValueError(f"Start '{start}' must be a positive int!")
|
|
95
|
+
|
|
96
|
+
#size validation
|
|
97
|
+
if self.size < 1:
|
|
98
|
+
raise ValueError("Carrier must have at least one channel!")
|
|
99
|
+
|
|
100
|
+
self.start = start
|
|
101
|
+
self.stop = start + self.size
|
|
102
|
+
|
|
103
|
+
#channel indices as plain attributes, resolved once
|
|
104
|
+
for i, key in enumerate(self.keys):
|
|
105
|
+
setattr(self, key, start + i)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def __repr__(self):
|
|
109
|
+
return f"{self.__class__.__name__}({self.start}, {self.keys})"
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def size(self):
|
|
114
|
+
"""Number of channels covered by the carrier
|
|
115
|
+
|
|
116
|
+
Returns
|
|
117
|
+
-------
|
|
118
|
+
size : int
|
|
119
|
+
number of channels
|
|
120
|
+
"""
|
|
121
|
+
return len(self.keys)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def __len__(self):
|
|
125
|
+
return self.size
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def __getitem__(self, key):
|
|
129
|
+
"""Index of a single channel of the carrier, by key or by position.
|
|
130
|
+
|
|
131
|
+
Parameters
|
|
132
|
+
----------
|
|
133
|
+
key : int, str
|
|
134
|
+
channel name or channel position within the carrier
|
|
135
|
+
|
|
136
|
+
Returns
|
|
137
|
+
-------
|
|
138
|
+
index : int
|
|
139
|
+
index of the channel in the register of the block
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
if isinstance(key, str):
|
|
143
|
+
if key not in self.keys:
|
|
144
|
+
raise ValueError(f"Key '{key}' not defined for {self}!")
|
|
145
|
+
return getattr(self, key)
|
|
146
|
+
|
|
147
|
+
if isinstance(key, int):
|
|
148
|
+
if key < 0 or key >= self.size:
|
|
149
|
+
raise ValueError(f"Channel '{key}' outside of {self}!")
|
|
150
|
+
return self.start + key
|
|
151
|
+
|
|
152
|
+
raise ValueError(f"Key must be (int, str) but is '{type(key)}'!")
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def slice(self):
|
|
157
|
+
"""All channels of the carrier as a slice, for direct access to the
|
|
158
|
+
flat register data, for example 'u[_in_1.slice]'
|
|
159
|
+
|
|
160
|
+
Returns
|
|
161
|
+
-------
|
|
162
|
+
slice : slice
|
|
163
|
+
slice covering all channels of the carrier
|
|
164
|
+
"""
|
|
165
|
+
return slice(self.start, self.stop)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class Vector(Carrier):
|
|
169
|
+
"""Carrier for a fixed number of unnamed channels.
|
|
170
|
+
|
|
171
|
+
Channels are addressed by position only, which makes this the carrier
|
|
172
|
+
for values that have a size but no component names, such as a spatial
|
|
173
|
+
discretization
|
|
174
|
+
|
|
175
|
+
.. code-block:: python
|
|
176
|
+
|
|
177
|
+
v = Vector(3)
|
|
178
|
+
v[0] # -> 0
|
|
179
|
+
v[2] # -> 2
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
Parameters
|
|
183
|
+
----------
|
|
184
|
+
size : int
|
|
185
|
+
number of channels
|
|
186
|
+
start : int
|
|
187
|
+
index of the first channel in the register of the block
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
def __init__(self, size, start=0):
|
|
191
|
+
|
|
192
|
+
#size validation
|
|
193
|
+
if not isinstance(size, int) or size < 1:
|
|
194
|
+
raise ValueError(f"Size '{size}' must be a positive int!")
|
|
195
|
+
|
|
196
|
+
self._size = size
|
|
197
|
+
super().__init__(start)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def __repr__(self):
|
|
201
|
+
return f"{self.__class__.__name__}({self.size}, {self.start})"
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
@property
|
|
205
|
+
def size(self):
|
|
206
|
+
"""Number of channels covered by the carrier
|
|
207
|
+
|
|
208
|
+
Returns
|
|
209
|
+
-------
|
|
210
|
+
size : int
|
|
211
|
+
number of channels
|
|
212
|
+
"""
|
|
213
|
+
return self._size
|
|
@@ -115,16 +115,19 @@ class Graph:
|
|
|
115
115
|
def _validate_connections(self):
|
|
116
116
|
"""Fast O(N) validation that no connections overwrite each other.
|
|
117
117
|
|
|
118
|
-
Checks that no two connections target the same (block,
|
|
118
|
+
Checks that no two connections target the same (block, channel) pair.
|
|
119
|
+
Ports are resolved to channel indices first, so port names, ports that
|
|
120
|
+
are carriers and single carrier channels are compared on the channels
|
|
121
|
+
they actually cover.
|
|
119
122
|
"""
|
|
120
|
-
# {(block,
|
|
123
|
+
# {(block, channel_idx): connection}
|
|
121
124
|
connected_targets = set()
|
|
122
125
|
|
|
123
126
|
for connection in self.connections:
|
|
124
127
|
for target in connection.targets:
|
|
125
128
|
target_block = target.block
|
|
126
|
-
for port_idx in target.ports:
|
|
127
|
-
key = (target_block, port_idx)
|
|
129
|
+
for port_idx in target_block.inputs._resolve(target.ports):
|
|
130
|
+
key = (target_block, int(port_idx))
|
|
128
131
|
if key in connected_targets:
|
|
129
132
|
raise ValueError(
|
|
130
133
|
f"Connection conflict detected"
|