ltbams 0.9.9__py3-none-any.whl → 1.0.2__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 (191) hide show
  1. ams/__init__.py +4 -11
  2. ams/_version.py +3 -3
  3. ams/cases/5bus/pjm5bus_demo.xlsx +0 -0
  4. ams/cases/5bus/pjm5bus_jumper.xlsx +0 -0
  5. ams/cases/5bus/pjm5bus_uced.json +1062 -0
  6. ams/cases/5bus/pjm5bus_uced.xlsx +0 -0
  7. ams/cases/5bus/pjm5bus_uced_esd1.xlsx +0 -0
  8. ams/cases/5bus/pjm5bus_uced_ev.xlsx +0 -0
  9. ams/cases/ieee123/ieee123.xlsx +0 -0
  10. ams/cases/ieee123/ieee123_regcv1.xlsx +0 -0
  11. ams/cases/ieee14/ieee14.json +1166 -0
  12. ams/cases/ieee14/ieee14.raw +92 -0
  13. ams/cases/ieee14/ieee14_conn.xlsx +0 -0
  14. ams/cases/ieee14/ieee14_uced.xlsx +0 -0
  15. ams/cases/ieee39/ieee39.xlsx +0 -0
  16. ams/cases/ieee39/ieee39_uced.xlsx +0 -0
  17. ams/cases/ieee39/ieee39_uced_esd1.xlsx +0 -0
  18. ams/cases/ieee39/ieee39_uced_pvd1.xlsx +0 -0
  19. ams/cases/ieee39/ieee39_uced_vis.xlsx +0 -0
  20. ams/cases/matpower/benchmark.json +1594 -0
  21. ams/cases/matpower/case118.m +787 -0
  22. ams/cases/matpower/case14.m +129 -0
  23. ams/cases/matpower/case300.m +1315 -0
  24. ams/cases/matpower/case39.m +205 -0
  25. ams/cases/matpower/case5.m +62 -0
  26. ams/cases/matpower/case_ACTIVSg2000.m +9460 -0
  27. ams/cases/npcc/npcc.m +644 -0
  28. ams/cases/npcc/npcc_uced.xlsx +0 -0
  29. ams/cases/pglib/pglib_opf_case39_epri__api.m +243 -0
  30. ams/cases/wecc/wecc.m +714 -0
  31. ams/cases/wecc/wecc_uced.xlsx +0 -0
  32. ams/cli.py +6 -0
  33. ams/core/__init__.py +2 -0
  34. ams/core/documenter.py +652 -0
  35. ams/core/matprocessor.py +782 -0
  36. ams/core/model.py +330 -0
  37. ams/core/param.py +322 -0
  38. ams/core/service.py +918 -0
  39. ams/core/symprocessor.py +224 -0
  40. ams/core/var.py +59 -0
  41. ams/extension/__init__.py +5 -0
  42. ams/extension/eva.py +401 -0
  43. ams/interface.py +1085 -0
  44. ams/io/__init__.py +133 -0
  45. ams/io/json.py +82 -0
  46. ams/io/matpower.py +406 -0
  47. ams/io/psse.py +6 -0
  48. ams/io/pypower.py +103 -0
  49. ams/io/xlsx.py +80 -0
  50. ams/main.py +81 -4
  51. ams/models/__init__.py +24 -0
  52. ams/models/area.py +40 -0
  53. ams/models/bus.py +52 -0
  54. ams/models/cost.py +169 -0
  55. ams/models/distributed/__init__.py +3 -0
  56. ams/models/distributed/esd1.py +71 -0
  57. ams/models/distributed/ev.py +60 -0
  58. ams/models/distributed/pvd1.py +67 -0
  59. ams/models/group.py +231 -0
  60. ams/models/info.py +26 -0
  61. ams/models/line.py +238 -0
  62. ams/models/renewable/__init__.py +5 -0
  63. ams/models/renewable/regc.py +119 -0
  64. ams/models/reserve.py +94 -0
  65. ams/models/shunt.py +14 -0
  66. ams/models/static/__init__.py +2 -0
  67. ams/models/static/gen.py +165 -0
  68. ams/models/static/pq.py +61 -0
  69. ams/models/timeslot.py +69 -0
  70. ams/models/zone.py +49 -0
  71. ams/opt/__init__.py +12 -0
  72. ams/opt/constraint.py +175 -0
  73. ams/opt/exprcalc.py +127 -0
  74. ams/opt/expression.py +188 -0
  75. ams/opt/objective.py +174 -0
  76. ams/opt/omodel.py +432 -0
  77. ams/opt/optzbase.py +192 -0
  78. ams/opt/param.py +156 -0
  79. ams/opt/var.py +233 -0
  80. ams/pypower/__init__.py +8 -0
  81. ams/pypower/_compat.py +9 -0
  82. ams/pypower/core/__init__.py +8 -0
  83. ams/pypower/core/pips.py +894 -0
  84. ams/pypower/core/ppoption.py +244 -0
  85. ams/pypower/core/ppver.py +18 -0
  86. ams/pypower/core/solver.py +2451 -0
  87. ams/pypower/eps.py +6 -0
  88. ams/pypower/idx.py +174 -0
  89. ams/pypower/io.py +604 -0
  90. ams/pypower/make/__init__.py +11 -0
  91. ams/pypower/make/matrices.py +665 -0
  92. ams/pypower/make/pdv.py +506 -0
  93. ams/pypower/routines/__init__.py +7 -0
  94. ams/pypower/routines/cpf.py +513 -0
  95. ams/pypower/routines/cpf_callbacks.py +114 -0
  96. ams/pypower/routines/opf.py +1803 -0
  97. ams/pypower/routines/opffcns.py +1946 -0
  98. ams/pypower/routines/pflow.py +852 -0
  99. ams/pypower/toggle.py +1098 -0
  100. ams/pypower/utils.py +293 -0
  101. ams/report.py +212 -50
  102. ams/routines/__init__.py +23 -0
  103. ams/routines/acopf.py +117 -0
  104. ams/routines/cpf.py +65 -0
  105. ams/routines/dcopf.py +241 -0
  106. ams/routines/dcpf.py +209 -0
  107. ams/routines/dcpf0.py +196 -0
  108. ams/routines/dopf.py +150 -0
  109. ams/routines/ed.py +312 -0
  110. ams/routines/pflow.py +255 -0
  111. ams/routines/pflow0.py +113 -0
  112. ams/routines/routine.py +1033 -0
  113. ams/routines/rted.py +519 -0
  114. ams/routines/type.py +160 -0
  115. ams/routines/uc.py +376 -0
  116. ams/shared.py +63 -9
  117. ams/system.py +61 -22
  118. ams/utils/__init__.py +3 -0
  119. ams/utils/misc.py +77 -0
  120. ams/utils/paths.py +257 -0
  121. docs/Makefile +21 -0
  122. docs/make.bat +35 -0
  123. docs/source/_templates/autosummary/base.rst +5 -0
  124. docs/source/_templates/autosummary/class.rst +35 -0
  125. docs/source/_templates/autosummary/module.rst +65 -0
  126. docs/source/_templates/autosummary/module_toctree.rst +66 -0
  127. docs/source/api.rst +102 -0
  128. docs/source/conf.py +206 -0
  129. docs/source/examples/index.rst +34 -0
  130. docs/source/genmodelref.py +61 -0
  131. docs/source/genroutineref.py +47 -0
  132. docs/source/getting_started/copyright.rst +20 -0
  133. docs/source/getting_started/formats/index.rst +20 -0
  134. docs/source/getting_started/formats/matpower.rst +183 -0
  135. docs/source/getting_started/formats/psse.rst +46 -0
  136. docs/source/getting_started/formats/pypower.rst +223 -0
  137. docs/source/getting_started/formats/xlsx.png +0 -0
  138. docs/source/getting_started/formats/xlsx.rst +23 -0
  139. docs/source/getting_started/index.rst +76 -0
  140. docs/source/getting_started/install.rst +231 -0
  141. docs/source/getting_started/overview.rst +26 -0
  142. docs/source/getting_started/testcase.rst +45 -0
  143. docs/source/getting_started/verification.rst +13 -0
  144. docs/source/images/curent.ico +0 -0
  145. docs/source/images/dcopf_time.png +0 -0
  146. docs/source/images/sponsors/CURENT_Logo_NameOnTrans.png +0 -0
  147. docs/source/images/sponsors/CURENT_Logo_Transparent.png +0 -0
  148. docs/source/images/sponsors/CURENT_Logo_Transparent_Name.png +0 -0
  149. docs/source/images/sponsors/doe.png +0 -0
  150. docs/source/index.rst +108 -0
  151. docs/source/modeling/example.rst +159 -0
  152. docs/source/modeling/index.rst +17 -0
  153. docs/source/modeling/model.rst +210 -0
  154. docs/source/modeling/routine.rst +122 -0
  155. docs/source/modeling/system.rst +51 -0
  156. docs/source/release-notes.rst +398 -0
  157. ltbams-1.0.2.dist-info/METADATA +215 -0
  158. ltbams-1.0.2.dist-info/RECORD +188 -0
  159. {ltbams-0.9.9.dist-info → ltbams-1.0.2.dist-info}/WHEEL +1 -1
  160. ltbams-1.0.2.dist-info/top_level.txt +3 -0
  161. tests/__init__.py +0 -0
  162. tests/test_1st_system.py +33 -0
  163. tests/test_addressing.py +40 -0
  164. tests/test_andes_mats.py +61 -0
  165. tests/test_case.py +266 -0
  166. tests/test_cli.py +34 -0
  167. tests/test_export_csv.py +89 -0
  168. tests/test_group.py +83 -0
  169. tests/test_interface.py +216 -0
  170. tests/test_io.py +32 -0
  171. tests/test_jumper.py +27 -0
  172. tests/test_known_good.py +267 -0
  173. tests/test_matp.py +437 -0
  174. tests/test_model.py +54 -0
  175. tests/test_omodel.py +119 -0
  176. tests/test_paths.py +22 -0
  177. tests/test_report.py +251 -0
  178. tests/test_repr.py +21 -0
  179. tests/test_routine.py +178 -0
  180. tests/test_rtn_dcopf.py +101 -0
  181. tests/test_rtn_dcpf.py +77 -0
  182. tests/test_rtn_ed.py +279 -0
  183. tests/test_rtn_pflow.py +219 -0
  184. tests/test_rtn_rted.py +273 -0
  185. tests/test_rtn_uc.py +248 -0
  186. tests/test_service.py +73 -0
  187. ltbams-0.9.9.dist-info/LICENSE +0 -692
  188. ltbams-0.9.9.dist-info/METADATA +0 -859
  189. ltbams-0.9.9.dist-info/RECORD +0 -14
  190. ltbams-0.9.9.dist-info/top_level.txt +0 -1
  191. {ltbams-0.9.9.dist-info → ltbams-1.0.2.dist-info}/entry_points.txt +0 -0
ams/routines/pflow.py ADDED
@@ -0,0 +1,255 @@
1
+ """
2
+ Power flow routines using ANDES.
3
+ """
4
+ import logging
5
+ from typing import Optional, Union, Type
6
+ from collections import OrderedDict
7
+
8
+ import numpy as np
9
+
10
+ from andes.utils.misc import elapsed
11
+
12
+ from ams.core.param import RParam
13
+ from ams.routines.routine import RoutineBase
14
+ from ams.opt import Var, Expression, Objective
15
+ from ams.interface import _to_andes_pflow, sync_adsys
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class PFlow(RoutineBase):
21
+ """
22
+ Power flow analysis using ANDES PFlow routine.
23
+
24
+ More settings can be changed via ``PFlow2._adsys.config`` and ``PFlow2._adsys.PFlow.config``.
25
+
26
+ All generator output powers, bus voltages, and angles are included in the variable definitions.
27
+ However, not all of these are unknowns; the definitions are provided for easy access.
28
+
29
+ References
30
+ ----------
31
+ [1] M. L. Crow, Computational methods for electric power systems. 2015.
32
+
33
+ [2] ANDES Documentation - Simulation and Plot. [Online]. Available:
34
+ https://docs.andes.app/en/latest/_examples/ex1.html
35
+ """
36
+
37
+ def __init__(self, system, config):
38
+ RoutineBase.__init__(self, system, config)
39
+ self.info = 'AC Power Flow'
40
+ self.type = 'PF'
41
+ self._adsys = None
42
+
43
+ self.config.add(OrderedDict((('tol', 1e-6),
44
+ ('max_iter', 25),
45
+ ('method', 'NR'),
46
+ ('check_conn', 1),
47
+ ('n_factorize', 4),
48
+ )))
49
+ self.config.add_extra("_help",
50
+ tol="convergence tolerance",
51
+ max_iter="max. number of iterations",
52
+ method="calculation method",
53
+ check_conn='check connectivity before power flow',
54
+ n_factorize="first N iterations to factorize Jacobian in dishonest method",
55
+ )
56
+ self.config.add_extra("_alt",
57
+ tol="float",
58
+ method=("NR", "dishonest", "NK"),
59
+ check_conn=(0, 1),
60
+ max_iter=">=10",
61
+ n_factorize=">0",
62
+ )
63
+
64
+ self.Bf = RParam(info='Bf matrix',
65
+ name='Bf', tex_name=r'B_{f}',
66
+ model='mats', src='Bf',
67
+ no_parse=True, sparse=True,)
68
+ self.Pfinj = RParam(info='Line power injection vector',
69
+ name='Pfinj', tex_name=r'P_{f}^{inj}',
70
+ model='mats', src='Pfinj',
71
+ no_parse=True,)
72
+
73
+ self.pg = Var(info='Gen active power',
74
+ unit='p.u.',
75
+ name='pg', tex_name=r'p_g',
76
+ model='StaticGen', src='p')
77
+ self.qg = Var(info='Gen reactive power',
78
+ unit='p.u.',
79
+ name='qg', tex_name=r'q_g',
80
+ model='StaticGen', src='q')
81
+ self.aBus = Var(info='Bus voltage angle',
82
+ unit='rad',
83
+ name='aBus', tex_name=r'\theta_{bus}',
84
+ model='Bus', src='a',)
85
+ self.vBus = Var(info='Bus voltage magnitude',
86
+ unit='p.u.',
87
+ name='vBus', tex_name=r'V_{bus}',
88
+ model='Bus', src='v',)
89
+ self.plf = Expression(info='Line flow',
90
+ name='plf', tex_name=r'p_{lf}',
91
+ unit='p.u.',
92
+ e_str='Bf@aBus + Pfinj',
93
+ model='Line', src=None,)
94
+
95
+ self.obj = Objective(name='obj',
96
+ info='place holder', unit='$',
97
+ sense='min', e_str='0',)
98
+
99
+ def init(self, **kwargs):
100
+ """
101
+ Initialize the ANDES PFlow routine.
102
+
103
+ kwargs go to andes.system.System().
104
+ """
105
+ self._adsys = _to_andes_pflow(self.system,
106
+ no_output=self.system.files.no_output,
107
+ config=self.config.as_dict(),
108
+ **kwargs)
109
+ self._adsys.setup()
110
+ self.om.init()
111
+ self.initialized = True
112
+ return self.initialized
113
+
114
+ def solve(self, **kwargs):
115
+ """
116
+ Placeholder.
117
+ """
118
+ return True
119
+
120
+ def run(self, **kwargs):
121
+ """
122
+ Run the routine.
123
+ """
124
+ if not self.initialized:
125
+ self.init()
126
+
127
+ t0, _ = elapsed()
128
+ _ = self._adsys.PFlow.run()
129
+ self.exit_code = self._adsys.exit_code
130
+ self.converged = self.exit_code == 0
131
+ _, s = elapsed(t0)
132
+ self.exec_time = float(s.split(" ")[0])
133
+
134
+ self.unpack()
135
+ return True
136
+
137
+ def _post_solve(self):
138
+ """
139
+ Placeholder.
140
+ """
141
+ return True
142
+
143
+ def unpack(self, **kwargs):
144
+ """
145
+ Unpack the results from ANDES PFlow routine.
146
+ """
147
+ # TODO: maybe also include the DC devices results
148
+ sys = self.system
149
+ # --- device results ---
150
+ bus_idx = sys.Bus.idx.v
151
+ sys.Bus.set(src='v', attr='v', idx=bus_idx,
152
+ value=self._adsys.Bus.get(src='v', attr='v', idx=bus_idx))
153
+ sys.Bus.set(src='a', attr='v', idx=bus_idx,
154
+ value=self._adsys.Bus.get(src='a', attr='v', idx=bus_idx))
155
+ pv_idx = sys.PV.idx.v
156
+ pv_u = sys.PV.get(src='u', attr='v', idx=pv_idx)
157
+ # NOTE: for p, we should consider the online status as p0 is a param
158
+ sys.PV.set(src='p', attr='v', idx=pv_idx,
159
+ value=pv_u * sys.PV.get(src='p0', attr='v', idx=pv_idx))
160
+ sys.PV.set(src='q', attr='v', idx=pv_idx,
161
+ value=self._adsys.PV.get(src='q', attr='v', idx=pv_idx))
162
+ slack_idx = sys.Slack.idx.v
163
+ sys.Slack.set(src='p', attr='v', idx=slack_idx,
164
+ value=self._adsys.Slack.get(src='p', attr='v', idx=slack_idx))
165
+ sys.Slack.set(src='q', attr='v', idx=slack_idx,
166
+ value=self._adsys.Slack.get(src='q', attr='v', idx=slack_idx))
167
+ # --- routine results ---
168
+ self.pg.optz.value = sys.StaticGen.get(src='p', attr='v', idx=self.pg.get_all_idxes())
169
+ self.qg.optz.value = sys.StaticGen.get(src='q', attr='v', idx=self.qg.get_all_idxes())
170
+ self.aBus.optz.value = sys.Bus.get(src='a', attr='v', idx=self.aBus.get_all_idxes())
171
+ self.vBus.optz.value = sys.Bus.get(src='v', attr='v', idx=self.vBus.get_all_idxes())
172
+ return True
173
+
174
+ def update(self, params=None, build_mats=False):
175
+ """
176
+ This method updates the parameters in the optimization model. In this routine,
177
+ the `params` and `build_mats` arguments are not used because the parameters
178
+ are updated directly to the ANDES system.
179
+ """
180
+ if not self.initialized:
181
+ self.init()
182
+
183
+ sync_adsys(self.system, self._adsys)
184
+
185
+ return True
186
+
187
+ def enable(self, name):
188
+ raise NotImplementedError
189
+
190
+ def disable(self, name):
191
+ raise NotImplementedError
192
+
193
+ def addRParam(self,
194
+ name: str,
195
+ tex_name: Optional[str] = None,
196
+ info: Optional[str] = None,
197
+ src: Optional[str] = None,
198
+ unit: Optional[str] = None,
199
+ model: Optional[str] = None,
200
+ v: Optional[np.ndarray] = None,
201
+ indexer: Optional[str] = None,
202
+ imodel: Optional[str] = None,):
203
+ """
204
+ Not supported!
205
+ """
206
+ raise NotImplementedError
207
+
208
+ def addService(self,
209
+ name: str,
210
+ value: np.ndarray,
211
+ tex_name: str = None,
212
+ unit: str = None,
213
+ info: str = None,
214
+ vtype: Type = None,):
215
+ """
216
+ Not supported!
217
+ """
218
+ raise NotImplementedError
219
+
220
+ def addConstrs(self,
221
+ name: str,
222
+ e_str: str,
223
+ info: Optional[str] = None,
224
+ is_eq: Optional[str] = False,):
225
+ """
226
+ Not supported!
227
+ """
228
+ raise NotImplementedError
229
+
230
+ def addVars(self,
231
+ name: str,
232
+ model: Optional[str] = None,
233
+ shape: Optional[Union[int, tuple]] = None,
234
+ tex_name: Optional[str] = None,
235
+ info: Optional[str] = None,
236
+ src: Optional[str] = None,
237
+ unit: Optional[str] = None,
238
+ horizon: Optional[RParam] = None,
239
+ nonneg: Optional[bool] = False,
240
+ nonpos: Optional[bool] = False,
241
+ cplx: Optional[bool] = False,
242
+ imag: Optional[bool] = False,
243
+ symmetric: Optional[bool] = False,
244
+ diag: Optional[bool] = False,
245
+ psd: Optional[bool] = False,
246
+ nsd: Optional[bool] = False,
247
+ hermitian: Optional[bool] = False,
248
+ boolean: Optional[bool] = False,
249
+ integer: Optional[bool] = False,
250
+ pos: Optional[bool] = False,
251
+ neg: Optional[bool] = False,):
252
+ """
253
+ Not supported!
254
+ """
255
+ raise NotImplementedError
ams/routines/pflow0.py ADDED
@@ -0,0 +1,113 @@
1
+ """
2
+ Power flow routines using PYPOWER.
3
+ """
4
+ import logging
5
+ from collections import OrderedDict
6
+
7
+ from ams.pypower import runpf
8
+
9
+ from ams.io.pypower import system2ppc
10
+ from ams.pypower.core import ppoption
11
+ from ams.core.param import RParam
12
+
13
+ from ams.routines.dcpf0 import DCPF0
14
+ from ams.opt import Var
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class PFlow0(DCPF0):
20
+ """
21
+ AC Power Flow using PYPOWER.
22
+
23
+ This class is deprecated as of version 0.9.12 and will be removed in 1.1.0.
24
+
25
+ Notes
26
+ -----
27
+ 1. AC pwoer flow is solved with PYPOWER ``runpf`` function.
28
+ 2. AC power flow formulation in AMS style is NOT DONE YET,
29
+ but this does not affect the results
30
+ because the data are passed to PYPOWER for solving.
31
+ """
32
+
33
+ def __init__(self, system, config):
34
+ DCPF0.__init__(self, system, config)
35
+ self.info = "AC Power Flow"
36
+ self.type = "PF"
37
+
38
+ self.config.add(OrderedDict((('qlim', 0),
39
+ )))
40
+ self.config.add_extra("_help",
41
+ qlim="Enforce generator q limits",
42
+ )
43
+ self.config.add_extra("_alt",
44
+ qlim=(0, 1, 2),
45
+ )
46
+
47
+ self.qd = RParam(info="reactive power load in system base",
48
+ name="qd", tex_name=r"q_{d}",
49
+ unit="p.u.",
50
+ model="StaticLoad", src="q0",)
51
+
52
+ # --- bus ---
53
+ self.vBus = Var(info="bus voltage magnitude",
54
+ unit="p.u.",
55
+ name="vBus", tex_name=r"v_{Bus}",
56
+ model="Bus", src="v",)
57
+ # --- gen ---
58
+ self.qg = Var(info="reactive power generation",
59
+ unit="p.u.",
60
+ name="qg", tex_name=r"q_{g}",
61
+ model="StaticGen", src="q",)
62
+ # NOTE: omit AC power flow formulation here
63
+
64
+ def solve(self, method="newton", **kwargs):
65
+ """
66
+ Solve the AC power flow using PYPOWER.
67
+ """
68
+ ppc = system2ppc(self.system)
69
+
70
+ method_map = dict(newton=1, fdxb=2, fdbx=3, gauss=4)
71
+ alg = method_map.get(method)
72
+ if alg == 4:
73
+ msg = "Gauss method is not fully tested yet, not recommended!"
74
+ logger.warning(msg)
75
+ if alg is None:
76
+ msg = f"Invalid method `{method}` for PFlow."
77
+ raise ValueError(msg)
78
+ ppopt = ppoption(PF_ALG=alg, ENFORCE_Q_LIMS=self.config.qlim, **kwargs)
79
+
80
+ res, sstats = runpf(casedata=ppc, ppopt=ppopt)
81
+ return res, sstats
82
+
83
+ def run(self, **kwargs):
84
+ """
85
+ Run AC power flow using PYPOWER.
86
+
87
+ Currently, four methods are supported: 'newton', 'fdxb', 'fdbx', 'gauss',
88
+ for Newton's method, fast-decoupled, XB, fast-decoupled, BX, and Gauss-Seidel,
89
+ respectively.
90
+
91
+ Note that gauss method is not recommended because it seems to be much
92
+ more slower than the other three methods and not fully tested yet.
93
+
94
+ Examples
95
+ --------
96
+ >>> ss = ams.load(ams.get_case('matpower/case14.m'))
97
+ >>> ss.PFlow.run()
98
+
99
+ Parameters
100
+ ----------
101
+ force_init : bool
102
+ Force initialization.
103
+ no_code : bool
104
+ Disable showing code.
105
+ method : str
106
+ Method for solving the power flow.
107
+
108
+ Returns
109
+ -------
110
+ exit_code : int
111
+ Exit code of the routine.
112
+ """
113
+ return super().run(**kwargs,)