pyBondGraph 0.2.1__tar.gz → 0.4.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyBondGraph
3
- Version: 0.2.1
3
+ Version: 0.4.0
4
4
  Summary: Modelling tool for linear bond graph systems in Python
5
5
  Author-email: Matthias Panny <matthias.panny@mci.edu>
6
6
  License-Expression: CC-BY-NC-SA-4.0
@@ -19,6 +19,7 @@ Requires-Dist: networkx>=3.5
19
19
  Requires-Dist: numpy>=2.3.0
20
20
  Requires-Dist: matplotlib>=3.10.3
21
21
  Requires-Dist: control>=0.10.2
22
+ Requires-Dist: pythonfmu3>=0.3.4
22
23
  Provides-Extra: streamlit
23
24
  Requires-Dist: streamlit>=1.47.0; extra == "streamlit"
24
25
  Requires-Dist: streamlit-flow-component>=1.6.1; extra == "streamlit"
@@ -29,6 +30,8 @@ Dynamic: license-file
29
30
 
30
31
  The library allows users to construct bond graph models programmatically, automatically derive the governing equations, and analyze the resulting dynamic systems using tools from control theory.
31
32
 
33
+ `pyBondGraph` can also export FMUs [(Functional Mock-up Units)](https://fmi-standard.org/) based on FMI 3.0 for Model Exchange, enabling interoperability with other simulation tools such as Simulink.
34
+
32
35
  Bond graphs provide a **domain-independent modeling framework** for physical systems. Using a unified representation of power exchange, the same modeling approach can be used for electrical, mechanical, hydraulic, and multi-domain systems.
33
36
 
34
37
  ---
@@ -36,10 +39,15 @@ Bond graphs provide a **domain-independent modeling framework** for physical sys
36
39
  # Features
37
40
 
38
41
  * Programmatic construction of **bond graph models**
42
+ * **Automatic causality assignment** via SCAP (Sequential Causality Assignment Procedure), with optional manual override or mixed mode
39
43
  * Automatic **symbolic equation derivation** using SymPy
40
- * Conversion of models to **state-space systems**
41
- * Example models for electrical and mechanical systems
42
- * Capaility to **store** and **load** bond graph models in JSON format construct bond graphs from loaded sub bond graphs
44
+ * Conversion of models to **linear state-space systems** ($\dot{x} = Ax + Bu$, $y = Cx + Du$)
45
+ * **Composable sub-models** via `SubBondGraph` with deep-copy namespace isolation
46
+ * **Two-port elements**: Transformer and Gyrator with automatic causality propagation
47
+ * **Sensor elements**: `IntegratedEffortSensor` and `IntegratedFlowSensor` for measuring integrated generalized variables (e.g. position from velocity)
48
+ * **Domain-neutral aliases**: `Compliance` = `Capacitor`, `Inertance` = `Inductor`, `Resistance` = `Resistor`
49
+ * Example models for electrical and electromechanical systems
50
+ * Integration with **python-control** for numerical simulation (step response, Bode plots, etc.)
43
51
 
44
52
  ---
45
53
 
@@ -82,12 +90,12 @@ Optional dependencies are used for experimental visualization tools.
82
90
  ---
83
91
 
84
92
  # Basic Usage
85
- A bond graph model is constructed by creating elements and connecting them via bonds.
93
+ A bond graph model is constructed by creating elements and connecting them via the `connect()` convenience method, which creates bonds and adds them to the graph in one step.
86
94
 
87
- Simple RC-Filter circuit:
95
+ ## RC-Filter with automatic causality (SCAP)
88
96
 
89
97
  ```python
90
- from pyBondGraph import BondGraph, SourceEffort, Resistor, Capacitor, OneJunction, Bond, Causality
98
+ from pyBondGraph import BondGraph, SourceEffort, Resistor, Capacitor, OneJunction
91
99
 
92
100
  bg = BondGraph()
93
101
 
@@ -97,19 +105,22 @@ resistor = Resistor("R", "R")
97
105
  capacitor = Capacitor("C", "C")
98
106
  series_junction = OneJunction("J1")
99
107
 
100
- # connect elements
101
- # causalities need to be assigned manually ^
102
- bg.connect(voltage_source, series_junction, Causality.EFFORT_OUT)
103
- bg.connect(series_junction, resistor, Causality.EFFORT_OUT)
104
- bg.connect(series_junction, capacitor, Causality.FLOW_OUT)
108
+ # connect elements --> causality is assigned automatically by SCAP
109
+ bg.connect(voltage_source, series_junction)
110
+ bg.connect(series_junction, resistor)
111
+ bg.connect(series_junction, capacitor)
105
112
 
106
113
  # plot the resulting BondGraph
107
114
  bg.plot()
108
115
 
109
116
  # derive system equations in linear state space form
110
- A, B, C, D, x, n_states, n_inputs, n_outputs = bond_graph.get_state_space()
117
+ A, B, C, D, x, n_states, n_inputs, n_outputs = bg.get_state_space()
118
+
119
+ bg.to_fmu("rc_filter")
111
120
  ```
112
121
 
122
+ Causality can also be assigned **manually** by passing a `Causality` value to `connect()`, or in **mixed mode** where some bonds are fixed and SCAP resolves the rest.
123
+
113
124
  The library automatically derives the **symbolic system equations** describing the dynamics of the model.
114
125
 
115
126
  ---
@@ -127,6 +138,12 @@ Bond graphs represent **power exchange between system components**, where power
127
138
  | Se | Effort source |
128
139
  | Sf | Flow source |
129
140
 
141
+ ## Two-Port Elements
142
+ | Element | Meaning |
143
+ |-------------|------------------------------------------------------------|
144
+ | TF | Transformer — same causality on both bonds |
145
+ | GY | Gyrator — opposite causality on both bonds |
146
+
130
147
  ## Junctions
131
148
  | Junction | Meaning |
132
149
  |----------|---------------|
@@ -140,11 +157,9 @@ Bond graphs represent **power exchange between system components**, where power
140
157
  | IntegratedFlowSensor | Measures integral of the flow at its bond |
141
158
 
142
159
  In mechanical bond graph models:
143
- * **flow** corresponds to **velocity**
160
+ * **flow** corresponds to **velocity**, i.e. an *IntegratedFlowSensor* can be used to compute **position**.
144
161
  * **effort** corresponds to **force**
145
162
 
146
- An **integrated flow sensor** can therefore be used to compute **position**:
147
-
148
163
  ---
149
164
 
150
165
  # Example Systems
@@ -154,7 +169,7 @@ The repository contains example models illustrating typical applications of bond
154
169
  Demonstrates modeling of an electrical circuit using bond graph elements.
155
170
 
156
171
  ### DC Motor
157
- A multi-domain electromechanical system coupling electrical and mechanical dynamics.
172
+ A multi-domain electromechanical system coupling electrical and mechanical dynamics. Also demonstrates integration with the `python-control` package for numerical simulation (step response).
158
173
 
159
174
  ### Transformer
160
175
  Example of energy transformation between two ports.
@@ -164,6 +179,18 @@ Classical mass-spring-damper system with two degrees of freedom.
164
179
 
165
180
  ---
166
181
 
182
+ # Causality Assignment
183
+
184
+ pyBondGraph supports three modes for assigning causality:
185
+
186
+ 1. **Automatic (SCAP)** — omit causality in `connect()` calls; `assign_causality()` is called automatically when solving. The Sequential Causality Assignment Procedure assigns causality in priority order: sources, storage elements (integral causality), resistors, then propagation through junctions and two-port elements.
187
+ 2. **Manual** — pass `Causality.EFFORT_OUT` or `Causality.FLOW_OUT` explicitly to each `connect()` call.
188
+ 3. **Mixed** — fix causality on some bonds, let SCAP resolve the rest.
189
+
190
+ If a storage element cannot receive integral causality (which would imply a DAE rather than an ODE), a `DerivativeCausalityError` is raised with a clear diagnostic message.
191
+
192
+ ---
193
+
167
194
  # Typical Applications
168
195
  Bond graph modeling is particularly useful for:
169
196
 
@@ -172,3 +199,9 @@ Bond graph modeling is particularly useful for:
172
199
  * multi-domain energy systems
173
200
  * control system modeling
174
201
  * teaching system dynamics
202
+
203
+ ---
204
+
205
+ # Planned Features
206
+
207
+ * **Nonlinear element support**: general nonlinear constitutive laws with Jacobian linearization
@@ -3,6 +3,8 @@
3
3
 
4
4
  The library allows users to construct bond graph models programmatically, automatically derive the governing equations, and analyze the resulting dynamic systems using tools from control theory.
5
5
 
6
+ `pyBondGraph` can also export FMUs [(Functional Mock-up Units)](https://fmi-standard.org/) based on FMI 3.0 for Model Exchange, enabling interoperability with other simulation tools such as Simulink.
7
+
6
8
  Bond graphs provide a **domain-independent modeling framework** for physical systems. Using a unified representation of power exchange, the same modeling approach can be used for electrical, mechanical, hydraulic, and multi-domain systems.
7
9
 
8
10
  ---
@@ -10,10 +12,15 @@ Bond graphs provide a **domain-independent modeling framework** for physical sys
10
12
  # Features
11
13
 
12
14
  * Programmatic construction of **bond graph models**
15
+ * **Automatic causality assignment** via SCAP (Sequential Causality Assignment Procedure), with optional manual override or mixed mode
13
16
  * Automatic **symbolic equation derivation** using SymPy
14
- * Conversion of models to **state-space systems**
15
- * Example models for electrical and mechanical systems
16
- * Capaility to **store** and **load** bond graph models in JSON format construct bond graphs from loaded sub bond graphs
17
+ * Conversion of models to **linear state-space systems** ($\dot{x} = Ax + Bu$, $y = Cx + Du$)
18
+ * **Composable sub-models** via `SubBondGraph` with deep-copy namespace isolation
19
+ * **Two-port elements**: Transformer and Gyrator with automatic causality propagation
20
+ * **Sensor elements**: `IntegratedEffortSensor` and `IntegratedFlowSensor` for measuring integrated generalized variables (e.g. position from velocity)
21
+ * **Domain-neutral aliases**: `Compliance` = `Capacitor`, `Inertance` = `Inductor`, `Resistance` = `Resistor`
22
+ * Example models for electrical and electromechanical systems
23
+ * Integration with **python-control** for numerical simulation (step response, Bode plots, etc.)
17
24
 
18
25
  ---
19
26
 
@@ -56,12 +63,12 @@ Optional dependencies are used for experimental visualization tools.
56
63
  ---
57
64
 
58
65
  # Basic Usage
59
- A bond graph model is constructed by creating elements and connecting them via bonds.
66
+ A bond graph model is constructed by creating elements and connecting them via the `connect()` convenience method, which creates bonds and adds them to the graph in one step.
60
67
 
61
- Simple RC-Filter circuit:
68
+ ## RC-Filter with automatic causality (SCAP)
62
69
 
63
70
  ```python
64
- from pyBondGraph import BondGraph, SourceEffort, Resistor, Capacitor, OneJunction, Bond, Causality
71
+ from pyBondGraph import BondGraph, SourceEffort, Resistor, Capacitor, OneJunction
65
72
 
66
73
  bg = BondGraph()
67
74
 
@@ -71,19 +78,22 @@ resistor = Resistor("R", "R")
71
78
  capacitor = Capacitor("C", "C")
72
79
  series_junction = OneJunction("J1")
73
80
 
74
- # connect elements
75
- # causalities need to be assigned manually ^
76
- bg.connect(voltage_source, series_junction, Causality.EFFORT_OUT)
77
- bg.connect(series_junction, resistor, Causality.EFFORT_OUT)
78
- bg.connect(series_junction, capacitor, Causality.FLOW_OUT)
81
+ # connect elements --> causality is assigned automatically by SCAP
82
+ bg.connect(voltage_source, series_junction)
83
+ bg.connect(series_junction, resistor)
84
+ bg.connect(series_junction, capacitor)
79
85
 
80
86
  # plot the resulting BondGraph
81
87
  bg.plot()
82
88
 
83
89
  # derive system equations in linear state space form
84
- A, B, C, D, x, n_states, n_inputs, n_outputs = bond_graph.get_state_space()
90
+ A, B, C, D, x, n_states, n_inputs, n_outputs = bg.get_state_space()
91
+
92
+ bg.to_fmu("rc_filter")
85
93
  ```
86
94
 
95
+ Causality can also be assigned **manually** by passing a `Causality` value to `connect()`, or in **mixed mode** where some bonds are fixed and SCAP resolves the rest.
96
+
87
97
  The library automatically derives the **symbolic system equations** describing the dynamics of the model.
88
98
 
89
99
  ---
@@ -101,6 +111,12 @@ Bond graphs represent **power exchange between system components**, where power
101
111
  | Se | Effort source |
102
112
  | Sf | Flow source |
103
113
 
114
+ ## Two-Port Elements
115
+ | Element | Meaning |
116
+ |-------------|------------------------------------------------------------|
117
+ | TF | Transformer — same causality on both bonds |
118
+ | GY | Gyrator — opposite causality on both bonds |
119
+
104
120
  ## Junctions
105
121
  | Junction | Meaning |
106
122
  |----------|---------------|
@@ -114,11 +130,9 @@ Bond graphs represent **power exchange between system components**, where power
114
130
  | IntegratedFlowSensor | Measures integral of the flow at its bond |
115
131
 
116
132
  In mechanical bond graph models:
117
- * **flow** corresponds to **velocity**
133
+ * **flow** corresponds to **velocity**, i.e. an *IntegratedFlowSensor* can be used to compute **position**.
118
134
  * **effort** corresponds to **force**
119
135
 
120
- An **integrated flow sensor** can therefore be used to compute **position**:
121
-
122
136
  ---
123
137
 
124
138
  # Example Systems
@@ -128,7 +142,7 @@ The repository contains example models illustrating typical applications of bond
128
142
  Demonstrates modeling of an electrical circuit using bond graph elements.
129
143
 
130
144
  ### DC Motor
131
- A multi-domain electromechanical system coupling electrical and mechanical dynamics.
145
+ A multi-domain electromechanical system coupling electrical and mechanical dynamics. Also demonstrates integration with the `python-control` package for numerical simulation (step response).
132
146
 
133
147
  ### Transformer
134
148
  Example of energy transformation between two ports.
@@ -138,6 +152,18 @@ Classical mass-spring-damper system with two degrees of freedom.
138
152
 
139
153
  ---
140
154
 
155
+ # Causality Assignment
156
+
157
+ pyBondGraph supports three modes for assigning causality:
158
+
159
+ 1. **Automatic (SCAP)** — omit causality in `connect()` calls; `assign_causality()` is called automatically when solving. The Sequential Causality Assignment Procedure assigns causality in priority order: sources, storage elements (integral causality), resistors, then propagation through junctions and two-port elements.
160
+ 2. **Manual** — pass `Causality.EFFORT_OUT` or `Causality.FLOW_OUT` explicitly to each `connect()` call.
161
+ 3. **Mixed** — fix causality on some bonds, let SCAP resolve the rest.
162
+
163
+ If a storage element cannot receive integral causality (which would imply a DAE rather than an ODE), a `DerivativeCausalityError` is raised with a clear diagnostic message.
164
+
165
+ ---
166
+
141
167
  # Typical Applications
142
168
  Bond graph modeling is particularly useful for:
143
169
 
@@ -145,4 +171,10 @@ Bond graph modeling is particularly useful for:
145
171
  * robotics and mechatronics
146
172
  * multi-domain energy systems
147
173
  * control system modeling
148
- * teaching system dynamics
174
+ * teaching system dynamics
175
+
176
+ ---
177
+
178
+ # Planned Features
179
+
180
+ * **Nonlinear element support**: general nonlinear constitutive laws with Jacobian linearization
@@ -1,4 +1,4 @@
1
- from .core import Bond, Causality
1
+ from .core import Bond, Causality, CausalityError, DerivativeCausalityError, Port # port is a type alias: dict[str, Node]
2
2
  from .elements import (
3
3
  SourceEffort,
4
4
  SourceFlow,
@@ -15,10 +15,13 @@ from .elements import (
15
15
  )
16
16
  from .sensors import IntegratedEffortSensor, IntegratedFlowSensor
17
17
  from .subbondgraph import SubBondGraph
18
- from .core import Port # type alias: dict[str, Node]
19
18
 
20
19
  from .bondgraph import BondGraph
21
20
 
21
+ from .numerics import to_numpy, to_control_ss
22
+
23
+ from .fmu_export import to_fmu
24
+
22
25
  __all__ = [
23
26
  "Bond",
24
27
  "Causality",
@@ -39,4 +42,9 @@ __all__ = [
39
42
  "IntegratedFlowSensor",
40
43
  "Port",
41
44
  "SubBondGraph",
45
+ "CausalityError",
46
+ "DerivativeCausalityError",
47
+ "to_numpy",
48
+ "to_control_ss",
49
+ "to_fmu",
42
50
  ]