musica 0.12.0__cp312-cp312-win_amd64.whl → 0.12.2__cp312-cp312-win_amd64.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.
Potentially problematic release.
This version of musica might be problematic. Click here for more details.
- musica/CMakeLists.txt +28 -2
- musica/__init__.py +9 -49
- musica/_musica.cp312-win_amd64.pyd +0 -0
- musica/_version.py +1 -1
- musica/backend.py +41 -0
- musica/binding_common.cpp +23 -6
- musica/carma.cpp +911 -0
- musica/carma.py +1729 -0
- musica/constants.py +1 -1
- musica/cpu_binding.cpp +2 -1
- musica/cuda.py +4 -1
- musica/examples/__init__.py +1 -0
- musica/examples/carma_aluminum.py +124 -0
- musica/examples/carma_sulfate.py +246 -0
- musica/examples/examples.py +165 -0
- musica/examples/sulfate_box_model.py +439 -0
- musica/examples/ts1_latin_hypercube.py +245 -0
- musica/gpu_binding.cpp +2 -1
- musica/main.py +89 -0
- musica/mechanism_configuration/__init__.py +1 -1
- musica/mechanism_configuration/aqueous_equilibrium.py +227 -54
- musica/mechanism_configuration/arrhenius.py +228 -42
- musica/mechanism_configuration/branched.py +249 -66
- musica/mechanism_configuration/condensed_phase_arrhenius.py +243 -50
- musica/mechanism_configuration/condensed_phase_photolysis.py +16 -19
- musica/mechanism_configuration/emission.py +10 -6
- musica/mechanism_configuration/first_order_loss.py +133 -26
- musica/mechanism_configuration/henrys_law.py +7 -48
- musica/mechanism_configuration/mechanism_configuration.py +114 -41
- musica/mechanism_configuration/phase.py +6 -2
- musica/mechanism_configuration/photolysis.py +12 -7
- musica/mechanism_configuration/reactions.py +20 -8
- musica/mechanism_configuration/simpol_phase_transfer.py +180 -51
- musica/mechanism_configuration/species.py +23 -4
- musica/mechanism_configuration/surface.py +14 -9
- musica/mechanism_configuration/ternary_chemical_activation.py +352 -0
- musica/mechanism_configuration/troe.py +259 -44
- musica/mechanism_configuration/tunneling.py +196 -49
- musica/mechanism_configuration/user_defined.py +9 -4
- musica/mechanism_configuration/wet_deposition.py +11 -8
- musica/mechanism_configuration.cpp +184 -95
- musica/musica.cpp +48 -61
- musica/test/examples/v1/full_configuration/full_configuration.json +39 -22
- musica/test/examples/v1/full_configuration/full_configuration.yaml +29 -20
- musica/test/{test_analytical.py → integration/test_analytical.py} +0 -1
- musica/test/integration/test_carma.py +227 -0
- musica/test/integration/test_carma_aluminum.py +12 -0
- musica/test/integration/test_carma_sulfate.py +17 -0
- musica/test/integration/test_sulfate_box_model.py +34 -0
- musica/test/integration/test_tuvx.py +62 -0
- musica/test/unit/test_parser.py +64 -0
- musica/test/{test_serializer.py → unit/test_serializer.py} +2 -2
- musica/test/unit/test_state.py +325 -0
- musica/test/{test_util_full_mechanism.py → unit/test_util_full_mechanism.py} +152 -122
- musica/tools/prepare_build_environment_linux.sh +23 -34
- musica/tools/prepare_build_environment_macos.sh +1 -0
- musica/tuvx.cpp +93 -0
- musica/tuvx.py +199 -0
- musica/types.py +120 -73
- {musica-0.12.0.dist-info → musica-0.12.2.dist-info}/METADATA +41 -39
- musica-0.12.2.dist-info/RECORD +70 -0
- {musica-0.12.0.dist-info → musica-0.12.2.dist-info}/WHEEL +1 -1
- musica-0.12.2.dist-info/entry_points.txt +3 -0
- musica/test/examples/v0/config.json +0 -7
- musica/test/examples/v0/config.yaml +0 -3
- musica/test/examples/v0/reactions.json +0 -193
- musica/test/examples/v0/reactions.yaml +0 -142
- musica/test/examples/v0/species.json +0 -40
- musica/test/examples/v0/species.yaml +0 -19
- musica/test/test_parser.py +0 -57
- musica/test/tuvx.py +0 -10
- musica/tools/prepare_build_environment_windows.sh +0 -22
- musica-0.12.0.dist-info/RECORD +0 -57
- /musica/test/{test_chapman.py → integration/test_chapman.py} +0 -0
- {musica-0.12.0.dist-info → musica-0.12.2.dist-info}/licenses/AUTHORS.md +0 -0
- {musica-0.12.0.dist-info → musica-0.12.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
from typing import Optional, Any, Dict, List, Union, Tuple
|
|
2
|
-
from
|
|
2
|
+
from .. import backend
|
|
3
3
|
from .phase import Phase
|
|
4
4
|
from .species import Species
|
|
5
5
|
from .reactions import ReactionComponentSerializer
|
|
6
|
-
from .utils import _add_other_properties
|
|
7
|
-
from
|
|
6
|
+
from .utils import _add_other_properties
|
|
7
|
+
from ..constants import BOLTZMANN
|
|
8
8
|
|
|
9
|
+
_backend = backend.get_backend()
|
|
10
|
+
_Arrhenius = _backend._mechanism_configuration._Arrhenius
|
|
11
|
+
_ReactionComponent = _backend._mechanism_configuration._ReactionComponent
|
|
12
|
+
ReactionType = _backend._mechanism_configuration._ReactionType
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
|
|
15
|
+
class Arrhenius:
|
|
11
16
|
"""
|
|
12
17
|
A class representing an Arrhenius rate constant.
|
|
13
18
|
|
|
@@ -46,7 +51,8 @@ class Arrhenius(_Arrhenius):
|
|
|
46
51
|
Ea: Optional[float] = None,
|
|
47
52
|
D: Optional[float] = None,
|
|
48
53
|
E: Optional[float] = None,
|
|
49
|
-
reactants: Optional[List[Union[Species,
|
|
54
|
+
reactants: Optional[List[Union[Species,
|
|
55
|
+
Tuple[float, Species]]]] = None,
|
|
50
56
|
products: Optional[List[Union[Species, Tuple[float, Species]]]] = None,
|
|
51
57
|
gas_phase: Optional[Phase] = None,
|
|
52
58
|
other_properties: Optional[Dict[str, Any]] = None,
|
|
@@ -67,45 +73,199 @@ class Arrhenius(_Arrhenius):
|
|
|
67
73
|
gas_phase (Phase): The gas phase in which the reaction occurs.
|
|
68
74
|
other_properties (Dict[str, Any]): A dictionary of other properties of the Arrhenius rate constant.
|
|
69
75
|
"""
|
|
70
|
-
|
|
71
|
-
self.
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
# Create the internal C++ instance
|
|
77
|
+
self._instance = _Arrhenius()
|
|
78
|
+
|
|
79
|
+
# Validate mutually exclusive parameters
|
|
74
80
|
if C is not None and Ea is not None:
|
|
75
81
|
raise ValueError("Cannot specify both C and Ea.")
|
|
76
|
-
self.C = -Ea / BOLTZMANN if Ea is not None else C if C is not None else self.C
|
|
77
|
-
self.D = D if D is not None else self.D
|
|
78
|
-
self.E = E if E is not None else self.E
|
|
79
|
-
self.reactants = (
|
|
80
|
-
[
|
|
81
|
-
(
|
|
82
|
-
_ReactionComponent(r.name)
|
|
83
|
-
if isinstance(r, Species)
|
|
84
|
-
else _ReactionComponent(r[1].name, r[0])
|
|
85
|
-
)
|
|
86
|
-
for r in reactants
|
|
87
|
-
]
|
|
88
|
-
if reactants is not None
|
|
89
|
-
else self.reactants
|
|
90
|
-
)
|
|
91
|
-
self.products = (
|
|
92
|
-
[
|
|
93
|
-
(
|
|
94
|
-
_ReactionComponent(p.name)
|
|
95
|
-
if isinstance(p, Species)
|
|
96
|
-
else _ReactionComponent(p[1].name, p[0])
|
|
97
|
-
)
|
|
98
|
-
for p in products
|
|
99
|
-
]
|
|
100
|
-
if products is not None
|
|
101
|
-
else self.products
|
|
102
|
-
)
|
|
103
|
-
self.gas_phase = gas_phase.name if gas_phase is not None else self.gas_phase
|
|
104
|
-
self.other_properties = other_properties if other_properties is not None else self.other_properties
|
|
105
82
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
83
|
+
# Set all parameters
|
|
84
|
+
if name is not None:
|
|
85
|
+
self.name = name
|
|
86
|
+
if A is not None:
|
|
87
|
+
self.A = A
|
|
88
|
+
if B is not None:
|
|
89
|
+
self.B = B
|
|
90
|
+
if Ea is not None:
|
|
91
|
+
self.C = -Ea / BOLTZMANN
|
|
92
|
+
elif C is not None:
|
|
93
|
+
self.C = C
|
|
94
|
+
if D is not None:
|
|
95
|
+
self.D = D
|
|
96
|
+
if E is not None:
|
|
97
|
+
self.E = E
|
|
98
|
+
if reactants is not None:
|
|
99
|
+
self.reactants = reactants
|
|
100
|
+
if products is not None:
|
|
101
|
+
self.products = products
|
|
102
|
+
if gas_phase is not None:
|
|
103
|
+
self.gas_phase = gas_phase
|
|
104
|
+
if other_properties is not None:
|
|
105
|
+
self.other_properties = other_properties
|
|
106
|
+
|
|
107
|
+
# Property delegation to self._instance
|
|
108
|
+
@property
|
|
109
|
+
def name(self) -> str:
|
|
110
|
+
"""Get the name of the Arrhenius rate constant."""
|
|
111
|
+
return self._instance.name
|
|
112
|
+
|
|
113
|
+
@name.setter
|
|
114
|
+
def name(self, value: str):
|
|
115
|
+
"""Set the name of the Arrhenius rate constant."""
|
|
116
|
+
self._instance.name = value
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def A(self) -> float:
|
|
120
|
+
"""Get the pre-exponential factor."""
|
|
121
|
+
return self._instance.A
|
|
122
|
+
|
|
123
|
+
@A.setter
|
|
124
|
+
def A(self, value: float):
|
|
125
|
+
"""Set the pre-exponential factor."""
|
|
126
|
+
self._instance.A = value
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def B(self) -> float:
|
|
130
|
+
"""Get the temperature exponent."""
|
|
131
|
+
return self._instance.B
|
|
132
|
+
|
|
133
|
+
@B.setter
|
|
134
|
+
def B(self, value: float):
|
|
135
|
+
"""Set the temperature exponent."""
|
|
136
|
+
self._instance.B = value
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def C(self) -> float:
|
|
140
|
+
"""Get the exponential term."""
|
|
141
|
+
return self._instance.C
|
|
142
|
+
|
|
143
|
+
@C.setter
|
|
144
|
+
def C(self, value: float):
|
|
145
|
+
"""Set the exponential term."""
|
|
146
|
+
self._instance.C = value
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def D(self) -> float:
|
|
150
|
+
"""Get the reference temperature."""
|
|
151
|
+
return self._instance.D
|
|
152
|
+
|
|
153
|
+
@D.setter
|
|
154
|
+
def D(self, value: float):
|
|
155
|
+
"""Set the reference temperature."""
|
|
156
|
+
self._instance.D = value
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def E(self) -> float:
|
|
160
|
+
"""Get the pressure scaling term."""
|
|
161
|
+
return self._instance.E
|
|
162
|
+
|
|
163
|
+
@E.setter
|
|
164
|
+
def E(self, value: float):
|
|
165
|
+
"""Set the pressure scaling term."""
|
|
166
|
+
self._instance.E = value
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def reactants(self) -> List[Union[Species, Tuple[float, Species]]]:
|
|
170
|
+
"""Get the reactants as Python objects."""
|
|
171
|
+
# Convert from C++ _ReactionComponent objects to Python Species objects
|
|
172
|
+
result = []
|
|
173
|
+
for rc in self._instance.reactants:
|
|
174
|
+
if hasattr(rc, 'coefficient') and rc.coefficient != 1.0:
|
|
175
|
+
# Create a tuple with coefficient and species
|
|
176
|
+
species = Species(name=rc.species_name)
|
|
177
|
+
result.append((rc.coefficient, species))
|
|
178
|
+
else:
|
|
179
|
+
# Just the species
|
|
180
|
+
species = Species(name=rc.species_name)
|
|
181
|
+
result.append(species)
|
|
182
|
+
return result
|
|
183
|
+
|
|
184
|
+
@reactants.setter
|
|
185
|
+
def reactants(self, value: List[Union[Species, Tuple[float, Species]]]):
|
|
186
|
+
"""Set the reactants, converting from Python to C++ objects."""
|
|
187
|
+
cpp_reactants = []
|
|
188
|
+
for r in value:
|
|
189
|
+
if isinstance(r, Species):
|
|
190
|
+
cpp_reactants.append(_ReactionComponent(r.name))
|
|
191
|
+
elif isinstance(r, tuple) and len(r) == 2:
|
|
192
|
+
coefficient, species = r
|
|
193
|
+
cpp_reactants.append(_ReactionComponent(species.name, coefficient))
|
|
194
|
+
else:
|
|
195
|
+
raise ValueError(f"Invalid reactant format: {r}")
|
|
196
|
+
self._instance.reactants = cpp_reactants
|
|
197
|
+
|
|
198
|
+
@property
|
|
199
|
+
def products(self) -> List[Union[Species, Tuple[float, Species]]]:
|
|
200
|
+
"""Get the products as Python objects."""
|
|
201
|
+
# Convert from C++ _ReactionComponent objects to Python Species objects
|
|
202
|
+
result = []
|
|
203
|
+
for rc in self._instance.products:
|
|
204
|
+
if hasattr(rc, 'coefficient') and rc.coefficient != 1.0:
|
|
205
|
+
# Create a tuple with coefficient and species
|
|
206
|
+
species = Species(name=rc.species_name)
|
|
207
|
+
result.append((rc.coefficient, species))
|
|
208
|
+
else:
|
|
209
|
+
# Just the species
|
|
210
|
+
species = Species(name=rc.species_name)
|
|
211
|
+
result.append(species)
|
|
212
|
+
return result
|
|
213
|
+
|
|
214
|
+
@products.setter
|
|
215
|
+
def products(self, value: List[Union[Species, Tuple[float, Species]]]):
|
|
216
|
+
"""Set the products, converting from Python to C++ objects."""
|
|
217
|
+
cpp_products = []
|
|
218
|
+
for p in value:
|
|
219
|
+
if isinstance(p, Species):
|
|
220
|
+
cpp_products.append(_ReactionComponent(p.name))
|
|
221
|
+
elif isinstance(p, tuple) and len(p) == 2:
|
|
222
|
+
coefficient, species = p
|
|
223
|
+
cpp_products.append(_ReactionComponent(species.name, coefficient))
|
|
224
|
+
else:
|
|
225
|
+
raise ValueError(f"Invalid product format: {p}")
|
|
226
|
+
self._instance.products = cpp_products
|
|
227
|
+
|
|
228
|
+
@property
|
|
229
|
+
def gas_phase(self) -> str:
|
|
230
|
+
"""Get the gas phase name."""
|
|
231
|
+
return self._instance.gas_phase
|
|
232
|
+
|
|
233
|
+
@gas_phase.setter
|
|
234
|
+
def gas_phase(self, value: Union[Phase, str]):
|
|
235
|
+
"""Set the gas phase."""
|
|
236
|
+
if isinstance(value, Phase):
|
|
237
|
+
self._instance.gas_phase = value.name
|
|
238
|
+
elif isinstance(value, str):
|
|
239
|
+
self._instance.gas_phase = value
|
|
240
|
+
else:
|
|
241
|
+
raise ValueError(f"Invalid gas_phase type: {type(value)}")
|
|
242
|
+
|
|
243
|
+
@property
|
|
244
|
+
def other_properties(self) -> Dict[str, Any]:
|
|
245
|
+
"""Get the other properties."""
|
|
246
|
+
return self._instance.other_properties
|
|
247
|
+
|
|
248
|
+
@other_properties.setter
|
|
249
|
+
def other_properties(self, value: Dict[str, Any]):
|
|
250
|
+
"""Set the other properties."""
|
|
251
|
+
self._instance.other_properties = value
|
|
252
|
+
|
|
253
|
+
@property
|
|
254
|
+
def type(self):
|
|
255
|
+
"""Get the reaction type."""
|
|
256
|
+
return ReactionType.Arrhenius
|
|
257
|
+
|
|
258
|
+
def _create_serialize_dict(self, instance) -> Dict:
|
|
259
|
+
"""
|
|
260
|
+
Helper method to create the serialization dictionary.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
instance: The instance to serialize (either self._instance or a _Arrhenius object).
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
Dict: Base serialization dictionary.
|
|
267
|
+
"""
|
|
268
|
+
return {
|
|
109
269
|
"type": "ARRHENIUS",
|
|
110
270
|
"name": instance.name,
|
|
111
271
|
"A": instance.A,
|
|
@@ -117,5 +277,31 @@ class Arrhenius(_Arrhenius):
|
|
|
117
277
|
"products": ReactionComponentSerializer.serialize_list_reaction_components(instance.products),
|
|
118
278
|
"gas phase": instance.gas_phase,
|
|
119
279
|
}
|
|
280
|
+
|
|
281
|
+
def serialize(self) -> Dict:
|
|
282
|
+
"""
|
|
283
|
+
Serialize the Arrhenius object to a dictionary using only Python-visible data.
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
Dict: A dictionary representation of the Arrhenius object.
|
|
287
|
+
"""
|
|
288
|
+
serialize_dict = self._create_serialize_dict(self._instance)
|
|
289
|
+
_add_other_properties(serialize_dict, self.other_properties)
|
|
290
|
+
return serialize_dict
|
|
291
|
+
|
|
292
|
+
@staticmethod
|
|
293
|
+
def serialize_static(instance) -> Dict:
|
|
294
|
+
"""
|
|
295
|
+
Static serialize method for compatibility with C++ _Arrhenius objects.
|
|
296
|
+
|
|
297
|
+
Args:
|
|
298
|
+
instance: The _Arrhenius instance to serialize.
|
|
299
|
+
|
|
300
|
+
Returns:
|
|
301
|
+
Dict: A dictionary representation of the Arrhenius object.
|
|
302
|
+
"""
|
|
303
|
+
# Create a temporary Arrhenius object to use the helper method
|
|
304
|
+
temp_arrhenius = Arrhenius()
|
|
305
|
+
serialize_dict = temp_arrhenius._create_serialize_dict(instance)
|
|
120
306
|
_add_other_properties(serialize_dict, instance.other_properties)
|
|
121
|
-
return
|
|
307
|
+
return serialize_dict
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
from
|
|
2
|
-
from musica import _Branched, _ReactionComponent
|
|
3
|
-
from .phase import Phase
|
|
4
|
-
from .species import Species
|
|
1
|
+
from .utils import _add_other_properties
|
|
5
2
|
from .reactions import ReactionComponentSerializer
|
|
6
|
-
from .
|
|
3
|
+
from .species import Species
|
|
4
|
+
from .phase import Phase
|
|
5
|
+
from typing import Optional, Any, Dict, List, Union, Tuple
|
|
6
|
+
from .. import backend
|
|
7
|
+
|
|
8
|
+
_backend = backend.get_backend()
|
|
9
|
+
_Branched = _backend._mechanism_configuration._Branched
|
|
10
|
+
_ReactionComponent = _backend._mechanism_configuration._ReactionComponent
|
|
11
|
+
ReactionType = _backend._mechanism_configuration._ReactionType
|
|
7
12
|
|
|
8
13
|
|
|
9
|
-
class Branched
|
|
14
|
+
class Branched:
|
|
10
15
|
"""
|
|
11
16
|
A class representing a branched reaction rate constant.
|
|
12
17
|
|
|
@@ -32,9 +37,12 @@ class Branched(_Branched):
|
|
|
32
37
|
Y: Optional[float] = None,
|
|
33
38
|
a0: Optional[float] = None,
|
|
34
39
|
n: Optional[float] = None,
|
|
35
|
-
reactants: Optional[List[Union[Species,
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
reactants: Optional[List[Union[Species,
|
|
41
|
+
Tuple[float, Species]]]] = None,
|
|
42
|
+
nitrate_products: Optional[List[Union[Species,
|
|
43
|
+
Tuple[float, Species]]]] = None,
|
|
44
|
+
alkoxy_products: Optional[List[Union[Species,
|
|
45
|
+
Tuple[float, Species]]]] = None,
|
|
38
46
|
gas_phase: Optional[Phase] = None,
|
|
39
47
|
other_properties: Optional[Dict[str, Any]] = None,
|
|
40
48
|
):
|
|
@@ -53,64 +61,239 @@ class Branched(_Branched):
|
|
|
53
61
|
gas_phase (Phase): The gas phase in which the reaction occurs.
|
|
54
62
|
other_properties (Dict[str, Any]): A dictionary of other properties of the branched reaction rate constant.
|
|
55
63
|
"""
|
|
56
|
-
|
|
57
|
-
self.
|
|
58
|
-
self.X = X if X is not None else self.X
|
|
59
|
-
self.Y = Y if Y is not None else self.Y
|
|
60
|
-
self.a0 = a0 if a0 is not None else self.a0
|
|
61
|
-
self.n = n if n is not None else self.n
|
|
62
|
-
self.reactants = (
|
|
63
|
-
[
|
|
64
|
-
(
|
|
65
|
-
_ReactionComponent(r.name)
|
|
66
|
-
if isinstance(r, Species)
|
|
67
|
-
else _ReactionComponent(r[1].name, r[0])
|
|
68
|
-
)
|
|
69
|
-
for r in reactants
|
|
70
|
-
]
|
|
71
|
-
if reactants is not None
|
|
72
|
-
else self.reactants
|
|
73
|
-
)
|
|
74
|
-
self.nitrate_products = (
|
|
75
|
-
[
|
|
76
|
-
(
|
|
77
|
-
_ReactionComponent(p.name)
|
|
78
|
-
if isinstance(p, Species)
|
|
79
|
-
else _ReactionComponent(p[1].name, p[0])
|
|
80
|
-
)
|
|
81
|
-
for p in nitrate_products
|
|
82
|
-
]
|
|
83
|
-
if nitrate_products is not None
|
|
84
|
-
else self.nitrate_products
|
|
85
|
-
)
|
|
86
|
-
self.alkoxy_products = (
|
|
87
|
-
[
|
|
88
|
-
(
|
|
89
|
-
_ReactionComponent(p.name)
|
|
90
|
-
if isinstance(p, Species)
|
|
91
|
-
else _ReactionComponent(p[1].name, p[0])
|
|
92
|
-
)
|
|
93
|
-
for p in alkoxy_products
|
|
94
|
-
]
|
|
95
|
-
if alkoxy_products is not None
|
|
96
|
-
else self.alkoxy_products
|
|
97
|
-
)
|
|
98
|
-
self.gas_phase = gas_phase.name if gas_phase is not None else self.gas_phase
|
|
99
|
-
self.other_properties = other_properties if other_properties is not None else self.other_properties
|
|
64
|
+
# Create the internal C++ instance
|
|
65
|
+
self._instance = _Branched()
|
|
100
66
|
|
|
101
|
-
|
|
102
|
-
|
|
67
|
+
# Set all parameters
|
|
68
|
+
if name is not None:
|
|
69
|
+
self.name = name
|
|
70
|
+
if X is not None:
|
|
71
|
+
self.X = X
|
|
72
|
+
if Y is not None:
|
|
73
|
+
self.Y = Y
|
|
74
|
+
if a0 is not None:
|
|
75
|
+
self.a0 = a0
|
|
76
|
+
if n is not None:
|
|
77
|
+
self.n = n
|
|
78
|
+
if reactants is not None:
|
|
79
|
+
self.reactants = reactants
|
|
80
|
+
if nitrate_products is not None:
|
|
81
|
+
self.nitrate_products = nitrate_products
|
|
82
|
+
if alkoxy_products is not None:
|
|
83
|
+
self.alkoxy_products = alkoxy_products
|
|
84
|
+
if gas_phase is not None:
|
|
85
|
+
self.gas_phase = gas_phase
|
|
86
|
+
if other_properties is not None:
|
|
87
|
+
self.other_properties = other_properties
|
|
88
|
+
|
|
89
|
+
# Property delegation to self._instance
|
|
90
|
+
@property
|
|
91
|
+
def name(self) -> str:
|
|
92
|
+
"""Get the name of the branched reaction rate constant."""
|
|
93
|
+
return self._instance.name
|
|
94
|
+
|
|
95
|
+
@name.setter
|
|
96
|
+
def name(self, value: str):
|
|
97
|
+
"""Set the name of the branched reaction rate constant."""
|
|
98
|
+
self._instance.name = value
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def X(self) -> float:
|
|
102
|
+
"""Get the pre-exponential branching factor."""
|
|
103
|
+
return self._instance.X
|
|
104
|
+
|
|
105
|
+
@X.setter
|
|
106
|
+
def X(self, value: float):
|
|
107
|
+
"""Set the pre-exponential branching factor."""
|
|
108
|
+
self._instance.X = value
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def Y(self) -> float:
|
|
112
|
+
"""Get the exponential branching factor."""
|
|
113
|
+
return self._instance.Y
|
|
114
|
+
|
|
115
|
+
@Y.setter
|
|
116
|
+
def Y(self, value: float):
|
|
117
|
+
"""Set the exponential branching factor."""
|
|
118
|
+
self._instance.Y = value
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def a0(self) -> float:
|
|
122
|
+
"""Get the Z parameter."""
|
|
123
|
+
return self._instance.a0
|
|
124
|
+
|
|
125
|
+
@a0.setter
|
|
126
|
+
def a0(self, value: float):
|
|
127
|
+
"""Set the Z parameter."""
|
|
128
|
+
self._instance.a0 = value
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def n(self) -> float:
|
|
132
|
+
"""Get the A parameter."""
|
|
133
|
+
return self._instance.n
|
|
134
|
+
|
|
135
|
+
@n.setter
|
|
136
|
+
def n(self, value: float):
|
|
137
|
+
"""Set the A parameter."""
|
|
138
|
+
self._instance.n = value
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def reactants(self) -> List[Union[Species, Tuple[float, Species]]]:
|
|
142
|
+
"""Get the reactants as Python objects."""
|
|
143
|
+
# Convert from C++ _ReactionComponent objects to Python Species objects
|
|
144
|
+
result = []
|
|
145
|
+
for rc in self._instance.reactants:
|
|
146
|
+
if hasattr(rc, 'coefficient') and rc.coefficient != 1.0:
|
|
147
|
+
# Create a tuple with coefficient and species
|
|
148
|
+
species = Species(name=rc.species_name)
|
|
149
|
+
result.append((rc.coefficient, species))
|
|
150
|
+
else:
|
|
151
|
+
# Just the species
|
|
152
|
+
species = Species(name=rc.species_name)
|
|
153
|
+
result.append(species)
|
|
154
|
+
return result
|
|
155
|
+
|
|
156
|
+
@reactants.setter
|
|
157
|
+
def reactants(self, value: List[Union[Species, Tuple[float, Species]]]):
|
|
158
|
+
"""Set the reactants, converting from Python to C++ objects."""
|
|
159
|
+
cpp_reactants = []
|
|
160
|
+
for r in value:
|
|
161
|
+
if isinstance(r, Species):
|
|
162
|
+
cpp_reactants.append(_ReactionComponent(r.name))
|
|
163
|
+
elif isinstance(r, tuple) and len(r) == 2:
|
|
164
|
+
coefficient, species = r
|
|
165
|
+
cpp_reactants.append(_ReactionComponent(species.name, coefficient))
|
|
166
|
+
else:
|
|
167
|
+
raise ValueError(f"Invalid reactant format: {r}")
|
|
168
|
+
self._instance.reactants = cpp_reactants
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def nitrate_products(self) -> List[Union[Species, Tuple[float, Species]]]:
|
|
172
|
+
"""Get the nitrate products as Python objects."""
|
|
173
|
+
# Convert from C++ _ReactionComponent objects to Python Species objects
|
|
174
|
+
result = []
|
|
175
|
+
for rc in self._instance.nitrate_products:
|
|
176
|
+
if hasattr(rc, 'coefficient') and rc.coefficient != 1.0:
|
|
177
|
+
# Create a tuple with coefficient and species
|
|
178
|
+
species = Species(name=rc.species_name)
|
|
179
|
+
result.append((rc.coefficient, species))
|
|
180
|
+
else:
|
|
181
|
+
# Just the species
|
|
182
|
+
species = Species(name=rc.species_name)
|
|
183
|
+
result.append(species)
|
|
184
|
+
return result
|
|
185
|
+
|
|
186
|
+
@nitrate_products.setter
|
|
187
|
+
def nitrate_products(self, value: List[Union[Species, Tuple[float, Species]]]):
|
|
188
|
+
"""Set the nitrate products, converting from Python to C++ objects."""
|
|
189
|
+
cpp_products = []
|
|
190
|
+
for p in value:
|
|
191
|
+
if isinstance(p, Species):
|
|
192
|
+
cpp_products.append(_ReactionComponent(p.name))
|
|
193
|
+
elif isinstance(p, tuple) and len(p) == 2:
|
|
194
|
+
coefficient, species = p
|
|
195
|
+
cpp_products.append(_ReactionComponent(species.name, coefficient))
|
|
196
|
+
else:
|
|
197
|
+
raise ValueError(f"Invalid nitrate product format: {p}")
|
|
198
|
+
self._instance.nitrate_products = cpp_products
|
|
199
|
+
|
|
200
|
+
@property
|
|
201
|
+
def alkoxy_products(self) -> List[Union[Species, Tuple[float, Species]]]:
|
|
202
|
+
"""Get the alkoxy products as Python objects."""
|
|
203
|
+
# Convert from C++ _ReactionComponent objects to Python Species objects
|
|
204
|
+
result = []
|
|
205
|
+
for rc in self._instance.alkoxy_products:
|
|
206
|
+
if hasattr(rc, 'coefficient') and rc.coefficient != 1.0:
|
|
207
|
+
# Create a tuple with coefficient and species
|
|
208
|
+
species = Species(name=rc.species_name)
|
|
209
|
+
result.append((rc.coefficient, species))
|
|
210
|
+
else:
|
|
211
|
+
# Just the species
|
|
212
|
+
species = Species(name=rc.species_name)
|
|
213
|
+
result.append(species)
|
|
214
|
+
return result
|
|
215
|
+
|
|
216
|
+
@alkoxy_products.setter
|
|
217
|
+
def alkoxy_products(self, value: List[Union[Species, Tuple[float, Species]]]):
|
|
218
|
+
"""Set the alkoxy products, converting from Python to C++ objects."""
|
|
219
|
+
cpp_products = []
|
|
220
|
+
for p in value:
|
|
221
|
+
if isinstance(p, Species):
|
|
222
|
+
cpp_products.append(_ReactionComponent(p.name))
|
|
223
|
+
elif isinstance(p, tuple) and len(p) == 2:
|
|
224
|
+
coefficient, species = p
|
|
225
|
+
cpp_products.append(_ReactionComponent(species.name, coefficient))
|
|
226
|
+
else:
|
|
227
|
+
raise ValueError(f"Invalid alkoxy product format: {p}")
|
|
228
|
+
self._instance.alkoxy_products = cpp_products
|
|
229
|
+
|
|
230
|
+
@property
|
|
231
|
+
def gas_phase(self) -> str:
|
|
232
|
+
"""Get the gas phase name."""
|
|
233
|
+
return self._instance.gas_phase
|
|
234
|
+
|
|
235
|
+
@gas_phase.setter
|
|
236
|
+
def gas_phase(self, value: Union[Phase, str]):
|
|
237
|
+
"""Set the gas phase."""
|
|
238
|
+
if isinstance(value, Phase):
|
|
239
|
+
self._instance.gas_phase = value.name
|
|
240
|
+
elif isinstance(value, str):
|
|
241
|
+
self._instance.gas_phase = value
|
|
242
|
+
else:
|
|
243
|
+
raise ValueError(f"Invalid gas_phase type: {type(value)}")
|
|
244
|
+
|
|
245
|
+
@property
|
|
246
|
+
def other_properties(self) -> Dict[str, Any]:
|
|
247
|
+
"""Get the other properties."""
|
|
248
|
+
return self._instance.other_properties
|
|
249
|
+
|
|
250
|
+
@other_properties.setter
|
|
251
|
+
def other_properties(self, value: Dict[str, Any]):
|
|
252
|
+
"""Set the other properties."""
|
|
253
|
+
self._instance.other_properties = value
|
|
254
|
+
|
|
255
|
+
@property
|
|
256
|
+
def type(self):
|
|
257
|
+
"""Get the reaction type."""
|
|
258
|
+
return ReactionType.Branched
|
|
259
|
+
|
|
260
|
+
def serialize(self) -> Dict:
|
|
261
|
+
"""
|
|
262
|
+
Serialize the Branched object to a dictionary using only Python-visible data.
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
Dict: A dictionary representation of the Branched object.
|
|
266
|
+
"""
|
|
103
267
|
serialize_dict = {
|
|
104
268
|
"type": "BRANCHED_NO_RO2",
|
|
105
|
-
"name":
|
|
106
|
-
"X":
|
|
107
|
-
"Y":
|
|
108
|
-
"a0":
|
|
109
|
-
"n":
|
|
110
|
-
"reactants": ReactionComponentSerializer.serialize_list_reaction_components(
|
|
111
|
-
|
|
112
|
-
"
|
|
113
|
-
|
|
269
|
+
"name": self.name,
|
|
270
|
+
"X": self.X,
|
|
271
|
+
"Y": self.Y,
|
|
272
|
+
"a0": self.a0,
|
|
273
|
+
"n": self.n,
|
|
274
|
+
"reactants": ReactionComponentSerializer.serialize_list_reaction_components(
|
|
275
|
+
self._instance.reactants),
|
|
276
|
+
"nitrate products": ReactionComponentSerializer.serialize_list_reaction_components(
|
|
277
|
+
self._instance.nitrate_products),
|
|
278
|
+
"alkoxy products": ReactionComponentSerializer.serialize_list_reaction_components(
|
|
279
|
+
self._instance.alkoxy_products),
|
|
280
|
+
"gas phase": self.gas_phase,
|
|
114
281
|
}
|
|
115
|
-
_add_other_properties(serialize_dict,
|
|
116
|
-
return
|
|
282
|
+
_add_other_properties(serialize_dict, self.other_properties)
|
|
283
|
+
return serialize_dict
|
|
284
|
+
|
|
285
|
+
@staticmethod
|
|
286
|
+
def serialize_static(instance) -> Dict:
|
|
287
|
+
"""
|
|
288
|
+
Static serialize method for compatibility with C++ _Branched objects.
|
|
289
|
+
|
|
290
|
+
Args:
|
|
291
|
+
instance: The _Branched instance to serialize.
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
Dict: A dictionary representation of the Branched object.
|
|
295
|
+
"""
|
|
296
|
+
# Create a temporary Branched object and use its instance serialize method
|
|
297
|
+
temp_branched = Branched()
|
|
298
|
+
temp_branched._instance = instance
|
|
299
|
+
return temp_branched.serialize()
|