musica 0.12.0__cp39-cp39-win_amd64.whl → 0.12.2__cp39-cp39-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.

Files changed (76) hide show
  1. musica/CMakeLists.txt +28 -2
  2. musica/__init__.py +9 -49
  3. musica/_musica.cp39-win_amd64.pyd +0 -0
  4. musica/_version.py +1 -1
  5. musica/backend.py +41 -0
  6. musica/binding_common.cpp +23 -6
  7. musica/carma.cpp +911 -0
  8. musica/carma.py +1729 -0
  9. musica/constants.py +1 -1
  10. musica/cpu_binding.cpp +2 -1
  11. musica/cuda.py +4 -1
  12. musica/examples/__init__.py +1 -0
  13. musica/examples/carma_aluminum.py +124 -0
  14. musica/examples/carma_sulfate.py +246 -0
  15. musica/examples/examples.py +165 -0
  16. musica/examples/sulfate_box_model.py +439 -0
  17. musica/examples/ts1_latin_hypercube.py +245 -0
  18. musica/gpu_binding.cpp +2 -1
  19. musica/main.py +89 -0
  20. musica/mechanism_configuration/__init__.py +1 -1
  21. musica/mechanism_configuration/aqueous_equilibrium.py +227 -54
  22. musica/mechanism_configuration/arrhenius.py +228 -42
  23. musica/mechanism_configuration/branched.py +249 -66
  24. musica/mechanism_configuration/condensed_phase_arrhenius.py +243 -50
  25. musica/mechanism_configuration/condensed_phase_photolysis.py +16 -19
  26. musica/mechanism_configuration/emission.py +10 -6
  27. musica/mechanism_configuration/first_order_loss.py +133 -26
  28. musica/mechanism_configuration/henrys_law.py +7 -48
  29. musica/mechanism_configuration/mechanism_configuration.py +114 -41
  30. musica/mechanism_configuration/phase.py +6 -2
  31. musica/mechanism_configuration/photolysis.py +12 -7
  32. musica/mechanism_configuration/reactions.py +20 -8
  33. musica/mechanism_configuration/simpol_phase_transfer.py +180 -51
  34. musica/mechanism_configuration/species.py +23 -4
  35. musica/mechanism_configuration/surface.py +14 -9
  36. musica/mechanism_configuration/ternary_chemical_activation.py +352 -0
  37. musica/mechanism_configuration/troe.py +259 -44
  38. musica/mechanism_configuration/tunneling.py +196 -49
  39. musica/mechanism_configuration/user_defined.py +9 -4
  40. musica/mechanism_configuration/wet_deposition.py +11 -8
  41. musica/mechanism_configuration.cpp +184 -95
  42. musica/musica.cpp +48 -61
  43. musica/test/examples/v1/full_configuration/full_configuration.json +39 -22
  44. musica/test/examples/v1/full_configuration/full_configuration.yaml +29 -20
  45. musica/test/{test_analytical.py → integration/test_analytical.py} +0 -1
  46. musica/test/integration/test_carma.py +227 -0
  47. musica/test/integration/test_carma_aluminum.py +12 -0
  48. musica/test/integration/test_carma_sulfate.py +17 -0
  49. musica/test/integration/test_sulfate_box_model.py +34 -0
  50. musica/test/integration/test_tuvx.py +62 -0
  51. musica/test/unit/test_parser.py +64 -0
  52. musica/test/{test_serializer.py → unit/test_serializer.py} +2 -2
  53. musica/test/unit/test_state.py +325 -0
  54. musica/test/{test_util_full_mechanism.py → unit/test_util_full_mechanism.py} +152 -122
  55. musica/tools/prepare_build_environment_linux.sh +23 -34
  56. musica/tools/prepare_build_environment_macos.sh +1 -0
  57. musica/tuvx.cpp +93 -0
  58. musica/tuvx.py +199 -0
  59. musica/types.py +120 -73
  60. {musica-0.12.0.dist-info → musica-0.12.2.dist-info}/METADATA +41 -39
  61. musica-0.12.2.dist-info/RECORD +70 -0
  62. {musica-0.12.0.dist-info → musica-0.12.2.dist-info}/WHEEL +1 -1
  63. musica-0.12.2.dist-info/entry_points.txt +3 -0
  64. musica/test/examples/v0/config.json +0 -7
  65. musica/test/examples/v0/config.yaml +0 -3
  66. musica/test/examples/v0/reactions.json +0 -193
  67. musica/test/examples/v0/reactions.yaml +0 -142
  68. musica/test/examples/v0/species.json +0 -40
  69. musica/test/examples/v0/species.yaml +0 -19
  70. musica/test/test_parser.py +0 -57
  71. musica/test/tuvx.py +0 -10
  72. musica/tools/prepare_build_environment_windows.sh +0 -22
  73. musica-0.12.0.dist-info/RECORD +0 -57
  74. /musica/test/{test_chapman.py → integration/test_chapman.py} +0 -0
  75. {musica-0.12.0.dist-info → musica-0.12.2.dist-info}/licenses/AUTHORS.md +0 -0
  76. {musica-0.12.0.dist-info → musica-0.12.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,8 +1,12 @@
1
1
  from typing import Optional, Any, Dict, Union, Tuple
2
- from musica import _HenrysLaw, _ReactionComponent
2
+ from .. import backend
3
3
  from .phase import Phase
4
4
  from .species import Species
5
- from .utils import _add_other_properties, _remove_empty_keys
5
+ from .utils import _add_other_properties
6
+
7
+ _backend = backend.get_backend()
8
+ _HenrysLaw = _backend._mechanism_configuration._HenrysLaw
9
+ _ReactionComponent = _backend._mechanism_configuration._ReactionComponent
6
10
 
7
11
 
8
12
  class HenrysLaw(_HenrysLaw):
@@ -11,22 +15,12 @@ class HenrysLaw(_HenrysLaw):
11
15
 
12
16
  Attributes:
13
17
  name (str): The name of the Henry's law reaction rate constant.
14
- gas_phase (Phase): The gas phase in which the reaction occurs.
15
- gas_phase_species (Union[Species, Tuple[float, Species]]): The gas phase species involved in the reaction.
16
- aerosol_phase (Phase): The aerosol phase in which the reaction occurs.
17
- aerosol_phase_water (Species): The water species in the aerosol phase.
18
- aerosol_phase_species (Union[Species, Tuple[float, Species]]): The aerosol phase species involved in the reaction.
19
18
  other_properties (Dict[str, Any]): A dictionary of other properties of the Henry's law reaction rate constant.
20
19
  """
21
20
 
22
21
  def __init__(
23
22
  self,
24
23
  name: Optional[str] = None,
25
- gas_phase: Optional[Phase] = None,
26
- gas_phase_species: Optional[Union[Species, Tuple[float, Species]]] = None,
27
- aerosol_phase: Optional[Phase] = None,
28
- aerosol_phase_water: Optional[Species] = None,
29
- aerosol_phase_species: Optional[Union[Species, Tuple[float, Species]]] = None,
30
24
  other_properties: Optional[Dict[str, Any]] = None,
31
25
  ):
32
26
  """
@@ -34,40 +28,10 @@ class HenrysLaw(_HenrysLaw):
34
28
 
35
29
  Args:
36
30
  name (str): The name of the Henry's law reaction rate constant.
37
- gas_phase (Phase): The gas phase in which the reaction occurs.
38
- gas_phase_species (Union[Species, Tuple[float, Species]]): The gas phase species involved in the reaction.
39
- aerosol_phase (Phase): The aerosol phase in which the reaction occurs.
40
- aerosol_phase_water (Species): The water species in the aerosol phase.
41
- aerosol_phase_species (Union[Species, Tuple[float, Species]]): The aerosol phase species involved in the reaction.
42
31
  other_properties (Dict[str, Any]): A dictionary of other properties of the Henry's law reaction rate constant.
43
32
  """
44
33
  super().__init__()
45
34
  self.name = name if name is not None else self.name
46
- self.gas_phase = gas_phase.name if gas_phase is not None else self.gas_phase
47
- self.gas_phase_species = (
48
- (
49
- _ReactionComponent(gas_phase_species.name)
50
- if isinstance(gas_phase_species, Species)
51
- else _ReactionComponent(gas_phase_species[1].name, gas_phase_species[0])
52
- )
53
- if gas_phase_species is not None
54
- else self.gas_phase_species
55
- )
56
- self.aerosol_phase = aerosol_phase.name if aerosol_phase is not None else self.aerosol_phase
57
- self.aerosol_phase_water = (
58
- aerosol_phase_water.name if aerosol_phase_water is not None else self.aerosol_phase_water
59
- )
60
- self.aerosol_phase_species = (
61
- (
62
- _ReactionComponent(aerosol_phase_species.name)
63
- if isinstance(aerosol_phase_species, Species)
64
- else _ReactionComponent(
65
- aerosol_phase_species[1].name, aerosol_phase_species[0]
66
- )
67
- )
68
- if aerosol_phase_species is not None
69
- else self.aerosol_phase_species
70
- )
71
35
  self.other_properties = other_properties if other_properties is not None else self.other_properties
72
36
 
73
37
  @staticmethod
@@ -75,11 +39,6 @@ class HenrysLaw(_HenrysLaw):
75
39
  serialize_dict = {
76
40
  "type": "HL_PHASE_TRANSFER",
77
41
  "name": instance.name,
78
- "gas phase": instance.gas_phase,
79
- "gas-phase species": instance.gas_phase_species.species_name,
80
- "aerosol phase": instance.aerosol_phase,
81
- "aerosol-phase water": instance.aerosol_phase_water,
82
- "aerosol-phase species": instance.aerosol_phase_species.species_name,
83
42
  }
84
43
  _add_other_properties(serialize_dict, instance.other_properties)
85
- return _remove_empty_keys(serialize_dict)
44
+ return serialize_dict
@@ -3,29 +3,36 @@
3
3
  #
4
4
  # This file is part of the musica Python package.
5
5
  # For more information, see the LICENSE file in the top-level directory of this distribution.
6
+ from .reactions import Reactions, ReactionType
7
+ from .user_defined import UserDefined, _UserDefined
8
+ from .simpol_phase_transfer import SimpolPhaseTransfer, _SimpolPhaseTransfer
9
+ from .henrys_law import HenrysLaw, _HenrysLaw
10
+ from .wet_deposition import WetDeposition, _WetDeposition
11
+ from .aqueous_equilibrium import AqueousEquilibrium, _AqueousEquilibrium
12
+ from .first_order_loss import FirstOrderLoss, _FirstOrderLoss
13
+ from .emission import Emission, _Emission
14
+ from .condensed_phase_photolysis import CondensedPhasePhotolysis, _CondensedPhasePhotolysis
15
+ from .photolysis import Photolysis, _Photolysis
16
+ from .surface import Surface, _Surface
17
+ from .tunneling import Tunneling, _Tunneling
18
+ from .branched import Branched, _Branched
19
+ from .troe import Troe, _Troe
20
+ from .ternary_chemical_activation import TernaryChemicalActivation, _TernaryChemicalActivation
21
+ from .condensed_phase_arrhenius import CondensedPhaseArrhenius, _CondensedPhaseArrhenius
22
+ from .arrhenius import Arrhenius, _Arrhenius
23
+ from .phase import Phase
24
+ from .species import Species
6
25
  import os
7
26
  import json
8
27
  import yaml
9
28
  from typing import Optional, Any, Dict, List
10
- from musica import _Mechanism, _Version, _Parser
11
- from .species import Species
12
- from .phase import Phase
13
- from .arrhenius import Arrhenius, _Arrhenius
14
- from .condensed_phase_arrhenius import CondensedPhaseArrhenius, _CondensedPhaseArrhenius
15
- from .troe import Troe, _Troe
16
- from .branched import Branched, _Branched
17
- from .tunneling import Tunneling, _Tunneling
18
- from .surface import Surface, _Surface
19
- from .photolysis import Photolysis, _Photolysis
20
- from .condensed_phase_photolysis import CondensedPhasePhotolysis, _CondensedPhasePhotolysis
21
- from .emission import Emission, _Emission
22
- from .first_order_loss import FirstOrderLoss, _FirstOrderLoss
23
- from .aqueous_equilibrium import AqueousEquilibrium, _AqueousEquilibrium
24
- from .wet_deposition import WetDeposition, _WetDeposition
25
- from .henrys_law import HenrysLaw, _HenrysLaw
26
- from .simpol_phase_transfer import SimpolPhaseTransfer, _SimpolPhaseTransfer
27
- from .user_defined import UserDefined, _UserDefined
28
- from .reactions import Reactions, ReactionType
29
+ from .. import backend
30
+
31
+ _backend = backend.get_backend()
32
+ _mc = _backend._mechanism_configuration
33
+ _Mechanism = _mc._Mechanism
34
+ _Version = _mc._Version
35
+ _Parser = _mc._Parser
29
36
 
30
37
 
31
38
  class Version(_Version):
@@ -68,7 +75,8 @@ class Mechanism(_Mechanism):
68
75
  self.name = name
69
76
  self.species = species if species is not None else []
70
77
  self.phases = phases if phases is not None else []
71
- self.reactions = Reactions(reactions=reactions if reactions is not None else [])
78
+ self.reactions = Reactions(
79
+ reactions=reactions if reactions is not None else [])
72
80
  self.version = version if version is not None else Version()
73
81
 
74
82
  def to_dict(self) -> Dict:
@@ -82,22 +90,46 @@ class Mechanism(_Mechanism):
82
90
 
83
91
  reactions_list = []
84
92
  for reaction in self.reactions:
85
- if isinstance(reaction, (_Arrhenius, Arrhenius)):
86
- reactions_list.append(Arrhenius.serialize(reaction))
87
- elif isinstance(reaction, (_Branched, Branched)):
88
- reactions_list.append(Branched.serialize(reaction))
93
+ if isinstance(reaction, _Arrhenius):
94
+ # Handle C++ _Arrhenius objects with static serialize call
95
+ reactions_list.append(Arrhenius.serialize_static(reaction))
96
+ elif isinstance(reaction, Arrhenius):
97
+ # Handle Python Arrhenius objects with instance serialize call
98
+ reactions_list.append(reaction.serialize())
99
+ elif isinstance(reaction, _Branched):
100
+ # Handle C++ _Branched objects with static serialize call
101
+ reactions_list.append(Branched.serialize_static(reaction))
102
+ elif isinstance(reaction, Branched):
103
+ # Handle Python Branched objects with instance serialize call
104
+ reactions_list.append(reaction.serialize())
89
105
  elif isinstance(reaction, (_CondensedPhaseArrhenius, CondensedPhaseArrhenius)):
90
- reactions_list.append(CondensedPhaseArrhenius.serialize(reaction))
106
+ reactions_list.append(
107
+ CondensedPhaseArrhenius.serialize_static(reaction))
91
108
  elif isinstance(reaction, (_CondensedPhasePhotolysis, CondensedPhasePhotolysis)):
92
- reactions_list.append(CondensedPhasePhotolysis.serialize(reaction))
109
+ reactions_list.append(
110
+ CondensedPhasePhotolysis.serialize(reaction))
93
111
  elif isinstance(reaction, (_Emission, Emission)):
94
112
  reactions_list.append(Emission.serialize(reaction))
95
- elif isinstance(reaction, (_FirstOrderLoss, FirstOrderLoss)):
96
- reactions_list.append(FirstOrderLoss.serialize(reaction))
97
- elif isinstance(reaction, (_SimpolPhaseTransfer, SimpolPhaseTransfer)):
98
- reactions_list.append(SimpolPhaseTransfer.serialize(reaction))
99
- elif isinstance(reaction, (_AqueousEquilibrium, AqueousEquilibrium)):
100
- reactions_list.append(AqueousEquilibrium.serialize(reaction))
113
+ elif isinstance(reaction, _FirstOrderLoss):
114
+ # Handle C++ _FirstOrderLoss objects with static serialize call
115
+ reactions_list.append(FirstOrderLoss.serialize_static(reaction))
116
+ elif isinstance(reaction, FirstOrderLoss):
117
+ # Handle Python FirstOrderLoss objects with instance serialize call
118
+ reactions_list.append(reaction.serialize())
119
+ elif isinstance(reaction, _SimpolPhaseTransfer):
120
+ # Handle C++ _SimpolPhaseTransfer objects with static serialize call
121
+ reactions_list.append(
122
+ SimpolPhaseTransfer.serialize_static(reaction))
123
+ elif isinstance(reaction, SimpolPhaseTransfer):
124
+ # Handle Python SimpolPhaseTransfer objects with instance serialize call
125
+ reactions_list.append(reaction.serialize())
126
+ elif isinstance(reaction, _AqueousEquilibrium):
127
+ # Handle C++ _AqueousEquilibrium objects with static serialize call
128
+ reactions_list.append(
129
+ AqueousEquilibrium.serialize_static(reaction))
130
+ elif isinstance(reaction, AqueousEquilibrium):
131
+ # Handle Python AqueousEquilibrium objects with instance serialize call
132
+ reactions_list.append(reaction.serialize())
101
133
  elif isinstance(reaction, (_WetDeposition, WetDeposition)):
102
134
  reactions_list.append(WetDeposition.serialize(reaction))
103
135
  elif isinstance(reaction, (_HenrysLaw, HenrysLaw)):
@@ -106,14 +138,29 @@ class Mechanism(_Mechanism):
106
138
  reactions_list.append(Photolysis.serialize(reaction))
107
139
  elif isinstance(reaction, (_Surface, Surface)):
108
140
  reactions_list.append(Surface.serialize(reaction))
109
- elif isinstance(reaction, (_Troe, Troe)):
110
- reactions_list.append(Troe.serialize(reaction))
111
- elif isinstance(reaction, (_Tunneling, Tunneling)):
112
- reactions_list.append(Tunneling.serialize(reaction))
141
+ elif isinstance(reaction, _Troe):
142
+ # Handle C++ _Troe objects with static serialize call
143
+ reactions_list.append(Troe.serialize_static(reaction))
144
+ elif isinstance(reaction, Troe):
145
+ # Handle Python Troe objects with instance serialize call
146
+ reactions_list.append(reaction.serialize())
147
+ elif isinstance(reaction, _TernaryChemicalActivation):
148
+ # Handle C++ _TernaryChemicalActivation objects with static serialize call
149
+ reactions_list.append(TernaryChemicalActivation.serialize_static(reaction))
150
+ elif isinstance(reaction, TernaryChemicalActivation):
151
+ # Handle Python TernaryChemicalActivation objects with instance serialize call
152
+ reactions_list.append(reaction.serialize())
153
+ elif isinstance(reaction, _Tunneling):
154
+ # Handle C++ _Tunneling objects with static serialize call
155
+ reactions_list.append(Tunneling.serialize_static(reaction))
156
+ elif isinstance(reaction, Tunneling):
157
+ # Handle Python Tunneling objects with instance serialize call
158
+ reactions_list.append(reaction.serialize())
113
159
  elif isinstance(reaction, (_UserDefined, UserDefined)):
114
160
  reactions_list.append(UserDefined.serialize(reaction))
115
161
  else:
116
- raise TypeError(f'Reaction type {type(reaction)} is not supported for export.')
162
+ raise TypeError(
163
+ f'Reaction type {type(reaction)} is not supported for export.')
117
164
 
118
165
  return {
119
166
  "name": self.name,
@@ -139,15 +186,40 @@ class MechanismSerializer():
139
186
  """
140
187
 
141
188
  @staticmethod
142
- def serialize(mechanism: Mechanism, file_path: str = "./mechanism.json") -> None:
143
- if not isinstance(mechanism, Mechanism):
189
+ def _convert_cpp_mechanism_to_python(cpp_mechanism: Any) -> Mechanism:
190
+ """
191
+ Convert a C++ _Mechanism object to a Python Mechanism object.
192
+ """
193
+ reactions_list = []
194
+ for reaction in cpp_mechanism.reactions:
195
+ reactions_list.append(reaction)
196
+
197
+ python_mechanism = Mechanism(
198
+ name=cpp_mechanism.name,
199
+ reactions=reactions_list,
200
+ species=list(cpp_mechanism.species),
201
+ phases=list(cpp_mechanism.phases),
202
+ version=Version() if cpp_mechanism.version is None else cpp_mechanism.version
203
+ )
204
+
205
+ return python_mechanism
206
+
207
+ @staticmethod
208
+ def serialize(mechanism: Mechanism, file_path: str = "./mechanism.json") -> None:
209
+ if not isinstance(mechanism, (Mechanism, _Mechanism)):
144
210
  raise TypeError(f"Object {mechanism} is not of type Mechanism.")
145
211
 
146
212
  directory, file = os.path.split(file_path)
147
213
  if directory:
148
214
  os.makedirs(directory, exist_ok=True)
215
+
216
+ if isinstance(mechanism, _Mechanism) and not isinstance(mechanism, Mechanism):
217
+ mechanism = MechanismSerializer._convert_cpp_mechanism_to_python(
218
+ mechanism)
219
+
220
+ # Now we can use the standard to_dict method
149
221
  dictionary = mechanism.to_dict()
150
-
222
+
151
223
  _, file_ext = os.path.splitext(file)
152
224
  file_ext = file_ext.lower()
153
225
  if file_ext in ['.yaml', '.yml']:
@@ -158,4 +230,5 @@ class MechanismSerializer():
158
230
  with open(file_path, 'w') as file:
159
231
  file.write(json_str)
160
232
  else:
161
- raise Exception('Allowable write formats are .json, .yaml, and .yml')
233
+ raise ValueError(
234
+ 'Allowable write formats are .json, .yaml, and .yml')
@@ -1,8 +1,11 @@
1
1
  from typing import Optional, Any, Dict, List
2
- from musica import _Phase
2
+ from .. import backend
3
3
  from .species import Species
4
4
  from .utils import _add_other_properties, _remove_empty_keys
5
5
 
6
+ _backend = backend.get_backend()
7
+ _Phase = _backend._mechanism_configuration._Phase
8
+
6
9
 
7
10
  class Phase(_Phase):
8
11
  """
@@ -30,7 +33,8 @@ class Phase(_Phase):
30
33
  """
31
34
  super().__init__()
32
35
  self.name = name if name is not None else self.name
33
- self.species = [s.name for s in species] if species is not None else self.species
36
+ self.species = [
37
+ s.name for s in species] if species is not None else self.species
34
38
  self.other_properties = other_properties if other_properties is not None else self.other_properties
35
39
 
36
40
  @staticmethod
@@ -1,9 +1,13 @@
1
- from typing import Optional, Any, Dict, List, Union, Tuple
2
- from musica import _Photolysis, _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 .utils import _add_other_properties, _remove_empty_keys
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
+ _Photolysis = _backend._mechanism_configuration._Photolysis
10
+ _ReactionComponent = _backend._mechanism_configuration._ReactionComponent
7
11
 
8
12
 
9
13
  class Photolysis(_Photolysis):
@@ -23,7 +27,8 @@ class Photolysis(_Photolysis):
23
27
  self,
24
28
  name: Optional[str] = None,
25
29
  scaling_factor: Optional[float] = None,
26
- reactants: Optional[List[Union[Species, Tuple[float, Species]]]] = None,
30
+ reactants: Optional[List[Union[Species,
31
+ Tuple[float, Species]]]] = None,
27
32
  products: Optional[List[Union[Species, Tuple[float, Species]]]] = None,
28
33
  gas_phase: Optional[Phase] = None,
29
34
  other_properties: Optional[Dict[str, Any]] = None,
@@ -80,4 +85,4 @@ class Photolysis(_Photolysis):
80
85
  "gas phase": instance.gas_phase,
81
86
  }
82
87
  _add_other_properties(serialize_dict, instance.other_properties)
83
- return _remove_empty_keys(serialize_dict)
88
+ return serialize_dict
@@ -1,13 +1,12 @@
1
1
  from typing import Optional, Any, Dict, List, Union
2
- from musica import _ReactionType, _Reactions, _ReactionsIterator
2
+ from .. import backend
3
3
  from .species import Species, _Species
4
4
  from .utils import _remove_empty_keys
5
5
 
6
-
7
- class ReactionType(_ReactionType):
8
- """
9
- A enum class representing a reaction type in a chemical mechanism.
10
- """
6
+ _backend = backend.get_backend()
7
+ ReactionType = _backend._mechanism_configuration._ReactionType
8
+ _Reactions = _backend._mechanism_configuration._Reactions
9
+ _ReactionsIterator = _backend._mechanism_configuration._ReactionsIterator
11
10
 
12
11
 
13
12
  class Reactions(_Reactions):
@@ -28,7 +27,19 @@ class Reactions(_Reactions):
28
27
  Args:
29
28
  reactions (List[]): A list of reactions in the mechanism.
30
29
  """
31
- super().__init__(reactions)
30
+ # Convert Python Arrhenius objects to C++ _Arrhenius objects for the C++ constructor
31
+ if reactions is not None:
32
+ cpp_reactions = []
33
+ for reaction in reactions:
34
+ if hasattr(reaction, '_instance'):
35
+ # This is a Python wrapper around a C++ object, use the internal instance
36
+ cpp_reactions.append(reaction._instance)
37
+ else:
38
+ # This is already a C++ object or other supported type
39
+ cpp_reactions.append(reaction)
40
+ super().__init__(cpp_reactions)
41
+ else:
42
+ super().__init__(reactions)
32
43
 
33
44
 
34
45
  class ReactionsIterator(_ReactionsIterator):
@@ -57,5 +68,6 @@ class ReactionComponentSerializer():
57
68
  def serialize_list_reaction_components(reaction_component_list) -> List[Union[Dict, str]]:
58
69
  ret = []
59
70
  for rc in reaction_component_list:
60
- ret.append(ReactionComponentSerializer.serialize_reaction_component(rc))
71
+ ret.append(
72
+ ReactionComponentSerializer.serialize_reaction_component(rc))
61
73
  return ret