musica 0.12.0__cp312-cp312-win_amd64.whl → 0.12.1__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 +123 -0
- musica/examples/carma_sulfate.py +245 -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 +11 -0
- musica/test/integration/test_carma_sulfate.py +16 -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/{test_util_full_mechanism.py → unit/test_util_full_mechanism.py} +152 -122
- musica/tools/prepare_build_environment_linux.sh +39 -32
- musica/tools/prepare_build_environment_macos.sh +1 -0
- musica/tuvx.cpp +93 -0
- musica/tuvx.py +199 -0
- musica/types.py +104 -60
- {musica-0.12.0.dist-info → musica-0.12.1.dist-info}/METADATA +40 -39
- musica-0.12.1.dist-info/RECORD +69 -0
- {musica-0.12.0.dist-info → musica-0.12.1.dist-info}/WHEEL +1 -1
- musica-0.12.1.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.1.dist-info}/licenses/AUTHORS.md +0 -0
- {musica-0.12.0.dist-info → musica-0.12.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
// Copyright (C) 2025 University Corporation for Atmospheric Research
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
#include <
|
|
4
|
-
#include <pybind11/stl.h>
|
|
3
|
+
#include <musica/micm/parse.hpp>
|
|
5
4
|
|
|
6
5
|
#include <mechanism_configuration/constants.hpp>
|
|
7
6
|
#include <mechanism_configuration/v1/parser.hpp>
|
|
7
|
+
#include <mechanism_configuration/v1/reaction_types.hpp>
|
|
8
8
|
#include <mechanism_configuration/v1/types.hpp>
|
|
9
9
|
#include <mechanism_configuration/v1/validation.hpp>
|
|
10
|
+
#include <pybind11/pybind11.h>
|
|
11
|
+
#include <pybind11/stl.h>
|
|
12
|
+
|
|
10
13
|
#include <variant>
|
|
11
14
|
|
|
12
15
|
namespace py = pybind11;
|
|
@@ -29,6 +32,7 @@ enum class ReactionType
|
|
|
29
32
|
Photolysis,
|
|
30
33
|
Surface,
|
|
31
34
|
Troe,
|
|
35
|
+
TernaryChemicalActivation,
|
|
32
36
|
Tunneling,
|
|
33
37
|
UserDefined
|
|
34
38
|
};
|
|
@@ -49,6 +53,7 @@ struct ReactionsIterator
|
|
|
49
53
|
Photolysis,
|
|
50
54
|
Surface,
|
|
51
55
|
Troe,
|
|
56
|
+
TernaryChemicalActivation,
|
|
52
57
|
Tunneling,
|
|
53
58
|
UserDefined>;
|
|
54
59
|
|
|
@@ -57,21 +62,26 @@ struct ReactionsIterator
|
|
|
57
62
|
size_t inner_index = 0;
|
|
58
63
|
|
|
59
64
|
ReactionsIterator(Reactions &reactions)
|
|
60
|
-
: reaction_lists{
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
65
|
+
: reaction_lists{
|
|
66
|
+
std::vector<VariantType>(reactions.arrhenius.begin(), reactions.arrhenius.end()),
|
|
67
|
+
std::vector<VariantType>(reactions.branched.begin(), reactions.branched.end()),
|
|
68
|
+
std::vector<VariantType>(reactions.condensed_phase_arrhenius.begin(), reactions.condensed_phase_arrhenius.end()),
|
|
69
|
+
std::vector<VariantType>(reactions.condensed_phase_photolysis.begin(), reactions.condensed_phase_photolysis.end()),
|
|
70
|
+
std::vector<VariantType>(reactions.emission.begin(), reactions.emission.end()),
|
|
71
|
+
std::vector<VariantType>(reactions.first_order_loss.begin(), reactions.first_order_loss.end()),
|
|
72
|
+
std::vector<VariantType>(reactions.simpol_phase_transfer.begin(), reactions.simpol_phase_transfer.end()),
|
|
73
|
+
std::vector<VariantType>(reactions.aqueous_equilibrium.begin(), reactions.aqueous_equilibrium.end()),
|
|
74
|
+
std::vector<VariantType>(reactions.wet_deposition.begin(), reactions.wet_deposition.end()),
|
|
75
|
+
std::vector<VariantType>(reactions.henrys_law.begin(), reactions.henrys_law.end()),
|
|
76
|
+
std::vector<VariantType>(reactions.photolysis.begin(), reactions.photolysis.end()),
|
|
77
|
+
std::vector<VariantType>(reactions.surface.begin(), reactions.surface.end()),
|
|
78
|
+
std::vector<VariantType>(reactions.troe.begin(), reactions.troe.end()),
|
|
79
|
+
std::vector<VariantType>(
|
|
80
|
+
reactions.ternary_chemical_activation.begin(),
|
|
81
|
+
reactions.ternary_chemical_activation.end()),
|
|
82
|
+
std::vector<VariantType>(reactions.tunneling.begin(), reactions.tunneling.end()),
|
|
83
|
+
std::vector<VariantType>(reactions.user_defined.begin(), reactions.user_defined.end())
|
|
84
|
+
}
|
|
75
85
|
{
|
|
76
86
|
}
|
|
77
87
|
|
|
@@ -91,84 +101,133 @@ struct ReactionsIterator
|
|
|
91
101
|
}
|
|
92
102
|
};
|
|
93
103
|
|
|
94
|
-
std::vector<ReactionComponent> get_reaction_components(const py::list&
|
|
104
|
+
std::vector<ReactionComponent> get_reaction_components(const py::list &components)
|
|
95
105
|
{
|
|
96
106
|
std::vector<ReactionComponent> reaction_components;
|
|
97
|
-
for (const auto &item : components)
|
|
98
|
-
|
|
107
|
+
for (const auto &item : components)
|
|
108
|
+
{
|
|
109
|
+
if (py::isinstance<Species>(item))
|
|
110
|
+
{
|
|
111
|
+
ReactionComponent component;
|
|
112
|
+
component.species_name = item.cast<Species>().name;
|
|
113
|
+
reaction_components.push_back(component);
|
|
114
|
+
}
|
|
115
|
+
else if (py::isinstance<py::tuple>(item) && py::len(item.cast<py::tuple>()) == 2)
|
|
116
|
+
{
|
|
117
|
+
auto item_tuple = item.cast<py::tuple>();
|
|
118
|
+
if (py::isinstance<py::float_>(item_tuple[0]) && py::isinstance<Species>(item_tuple[1]))
|
|
119
|
+
{
|
|
99
120
|
ReactionComponent component;
|
|
100
|
-
component.species_name =
|
|
121
|
+
component.species_name = item_tuple[1].cast<Species>().name;
|
|
122
|
+
component.coefficient = item_tuple[0].cast<double>();
|
|
101
123
|
reaction_components.push_back(component);
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
throw py::value_error("Invalid type for reactant. Expected a Species or a tuple of (float, Species).");
|
|
124
|
+
}
|
|
125
|
+
else if (py::isinstance<py::int_>(item_tuple[0]) && py::isinstance<Species>(item_tuple[1]))
|
|
126
|
+
{
|
|
127
|
+
ReactionComponent component;
|
|
128
|
+
component.species_name = item_tuple[1].cast<Species>().name;
|
|
129
|
+
component.coefficient = item_tuple[0].cast<int>();
|
|
130
|
+
reaction_components.push_back(component);
|
|
131
|
+
}
|
|
132
|
+
else
|
|
133
|
+
{
|
|
134
|
+
throw py::value_error("Invalid tuple format. Expected (float, Species).");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else
|
|
138
|
+
{
|
|
139
|
+
throw py::value_error("Invalid type for reactant. Expected a Species or a tuple of (float, Species).");
|
|
119
140
|
}
|
|
120
141
|
}
|
|
121
142
|
std::unordered_set<std::string> component_names;
|
|
122
|
-
for (const auto &component : reaction_components)
|
|
123
|
-
|
|
124
|
-
|
|
143
|
+
for (const auto &component : reaction_components)
|
|
144
|
+
{
|
|
145
|
+
if (!component_names.insert(component.species_name).second)
|
|
146
|
+
{
|
|
147
|
+
throw py::value_error("Duplicate reaction component name found: " + component.species_name);
|
|
125
148
|
}
|
|
126
149
|
}
|
|
127
150
|
return reaction_components;
|
|
128
151
|
}
|
|
129
152
|
|
|
130
|
-
Reactions create_reactions(const py::list&
|
|
153
|
+
Reactions create_reactions(const py::list &reactions)
|
|
131
154
|
{
|
|
132
155
|
Reactions reaction_obj;
|
|
133
|
-
for (const auto &item : reactions)
|
|
134
|
-
|
|
156
|
+
for (const auto &item : reactions)
|
|
157
|
+
{
|
|
158
|
+
if (py::isinstance<Arrhenius>(item))
|
|
159
|
+
{
|
|
135
160
|
reaction_obj.arrhenius.push_back(item.cast<Arrhenius>());
|
|
136
|
-
}
|
|
161
|
+
}
|
|
162
|
+
else if (py::isinstance<Branched>(item))
|
|
163
|
+
{
|
|
137
164
|
reaction_obj.branched.push_back(item.cast<Branched>());
|
|
138
|
-
}
|
|
165
|
+
}
|
|
166
|
+
else if (py::isinstance<CondensedPhaseArrhenius>(item))
|
|
167
|
+
{
|
|
139
168
|
reaction_obj.condensed_phase_arrhenius.push_back(item.cast<CondensedPhaseArrhenius>());
|
|
140
|
-
}
|
|
169
|
+
}
|
|
170
|
+
else if (py::isinstance<CondensedPhasePhotolysis>(item))
|
|
171
|
+
{
|
|
141
172
|
reaction_obj.condensed_phase_photolysis.push_back(item.cast<CondensedPhasePhotolysis>());
|
|
142
|
-
}
|
|
173
|
+
}
|
|
174
|
+
else if (py::isinstance<Emission>(item))
|
|
175
|
+
{
|
|
143
176
|
reaction_obj.emission.push_back(item.cast<Emission>());
|
|
144
|
-
}
|
|
177
|
+
}
|
|
178
|
+
else if (py::isinstance<FirstOrderLoss>(item))
|
|
179
|
+
{
|
|
145
180
|
reaction_obj.first_order_loss.push_back(item.cast<FirstOrderLoss>());
|
|
146
|
-
}
|
|
181
|
+
}
|
|
182
|
+
else if (py::isinstance<SimpolPhaseTransfer>(item))
|
|
183
|
+
{
|
|
147
184
|
reaction_obj.simpol_phase_transfer.push_back(item.cast<SimpolPhaseTransfer>());
|
|
148
|
-
}
|
|
185
|
+
}
|
|
186
|
+
else if (py::isinstance<AqueousEquilibrium>(item))
|
|
187
|
+
{
|
|
149
188
|
reaction_obj.aqueous_equilibrium.push_back(item.cast<AqueousEquilibrium>());
|
|
150
|
-
}
|
|
189
|
+
}
|
|
190
|
+
else if (py::isinstance<WetDeposition>(item))
|
|
191
|
+
{
|
|
151
192
|
reaction_obj.wet_deposition.push_back(item.cast<WetDeposition>());
|
|
152
|
-
}
|
|
193
|
+
}
|
|
194
|
+
else if (py::isinstance<HenrysLaw>(item))
|
|
195
|
+
{
|
|
153
196
|
reaction_obj.henrys_law.push_back(item.cast<HenrysLaw>());
|
|
154
|
-
}
|
|
197
|
+
}
|
|
198
|
+
else if (py::isinstance<Photolysis>(item))
|
|
199
|
+
{
|
|
155
200
|
reaction_obj.photolysis.push_back(item.cast<Photolysis>());
|
|
156
|
-
}
|
|
201
|
+
}
|
|
202
|
+
else if (py::isinstance<Surface>(item))
|
|
203
|
+
{
|
|
157
204
|
reaction_obj.surface.push_back(item.cast<Surface>());
|
|
158
|
-
}
|
|
205
|
+
}
|
|
206
|
+
else if (py::isinstance<Troe>(item))
|
|
207
|
+
{
|
|
159
208
|
reaction_obj.troe.push_back(item.cast<Troe>());
|
|
160
|
-
}
|
|
209
|
+
}
|
|
210
|
+
else if (py::isinstance<TernaryChemicalActivation>(item))
|
|
211
|
+
{
|
|
212
|
+
reaction_obj.ternary_chemical_activation.push_back(item.cast<TernaryChemicalActivation>());
|
|
213
|
+
}
|
|
214
|
+
else if (py::isinstance<Tunneling>(item))
|
|
215
|
+
{
|
|
161
216
|
reaction_obj.tunneling.push_back(item.cast<Tunneling>());
|
|
162
|
-
}
|
|
217
|
+
}
|
|
218
|
+
else if (py::isinstance<UserDefined>(item))
|
|
219
|
+
{
|
|
163
220
|
reaction_obj.user_defined.push_back(item.cast<UserDefined>());
|
|
164
|
-
}
|
|
165
|
-
|
|
221
|
+
}
|
|
222
|
+
else
|
|
223
|
+
{
|
|
224
|
+
throw py::value_error("Invalid reaction type.");
|
|
166
225
|
}
|
|
167
226
|
}
|
|
168
227
|
return reaction_obj;
|
|
169
228
|
}
|
|
170
229
|
|
|
171
|
-
void bind_mechanism_configuration(py::module_ &
|
|
230
|
+
void bind_mechanism_configuration(py::module_ &mechanism_configuration)
|
|
172
231
|
{
|
|
173
232
|
py::enum_<ReactionType>(mechanism_configuration, "_ReactionType")
|
|
174
233
|
.value("Arrhenius", ReactionType::Arrhenius)
|
|
@@ -184,6 +243,7 @@ void bind_mechanism_configuration(py::module_ & mechanism_configuration)
|
|
|
184
243
|
.value("Photolysis", ReactionType::Photolysis)
|
|
185
244
|
.value("Surface", ReactionType::Surface)
|
|
186
245
|
.value("Troe", ReactionType::Troe)
|
|
246
|
+
.value("TernaryChemicalActivation", ReactionType::TernaryChemicalActivation)
|
|
187
247
|
.value("Tunneling", ReactionType::Tunneling)
|
|
188
248
|
.value("UserDefined", ReactionType::UserDefined);
|
|
189
249
|
|
|
@@ -198,6 +258,9 @@ void bind_mechanism_configuration(py::module_ & mechanism_configuration)
|
|
|
198
258
|
.def_readwrite("N_star", &Species::n_star)
|
|
199
259
|
.def_readwrite("density_kg_m3", &Species::density)
|
|
200
260
|
.def_readwrite("tracer_type", &Species::tracer_type)
|
|
261
|
+
.def_readwrite("constant_concentration_mol_m3", &Species::constant_concentration)
|
|
262
|
+
.def_readwrite("constant_mixing_ratio_mol_mol", &Species::constant_mixing_ratio)
|
|
263
|
+
.def_readwrite("is_third_body", &Species::is_third_body)
|
|
201
264
|
.def_readwrite("other_properties", &Species::unknown_properties)
|
|
202
265
|
.def("__str__", [](const Species &s) { return s.name; })
|
|
203
266
|
.def("__repr__", [](const Species &s) { return "<Species: " + s.name + ">"; });
|
|
@@ -212,17 +275,21 @@ void bind_mechanism_configuration(py::module_ & mechanism_configuration)
|
|
|
212
275
|
|
|
213
276
|
py::class_<ReactionComponent>(mechanism_configuration, "_ReactionComponent")
|
|
214
277
|
.def(py::init<>())
|
|
215
|
-
.def(py::init(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
278
|
+
.def(py::init(
|
|
279
|
+
[](const std::string &species_name)
|
|
280
|
+
{
|
|
281
|
+
ReactionComponent rc;
|
|
282
|
+
rc.species_name = species_name;
|
|
283
|
+
return rc;
|
|
284
|
+
}))
|
|
285
|
+
.def(py::init(
|
|
286
|
+
[](const std::string &species_name, double coefficient)
|
|
287
|
+
{
|
|
288
|
+
ReactionComponent rc;
|
|
289
|
+
rc.species_name = species_name;
|
|
290
|
+
rc.coefficient = coefficient;
|
|
291
|
+
return rc;
|
|
292
|
+
}))
|
|
226
293
|
.def_readwrite("species_name", &ReactionComponent::species_name)
|
|
227
294
|
.def_readwrite("coefficient", &ReactionComponent::coefficient)
|
|
228
295
|
.def_readwrite("other_properties", &ReactionComponent::unknown_properties)
|
|
@@ -255,8 +322,7 @@ void bind_mechanism_configuration(py::module_ & mechanism_configuration)
|
|
|
255
322
|
.def_readwrite("reactants", &CondensedPhaseArrhenius::reactants)
|
|
256
323
|
.def_readwrite("products", &CondensedPhaseArrhenius::products)
|
|
257
324
|
.def_readwrite("name", &CondensedPhaseArrhenius::name)
|
|
258
|
-
.def_readwrite("
|
|
259
|
-
.def_readwrite("aerosol_phase_water", &CondensedPhaseArrhenius::aerosol_phase_water)
|
|
325
|
+
.def_readwrite("condensed_phase", &CondensedPhaseArrhenius::condensed_phase)
|
|
260
326
|
.def_readwrite("other_properties", &CondensedPhaseArrhenius::unknown_properties)
|
|
261
327
|
.def("__str__", [](const CondensedPhaseArrhenius &cpa) { return cpa.name; })
|
|
262
328
|
.def("__repr__", [](const CondensedPhaseArrhenius &cpa) { return "<CondensedPhaseArrhenius: " + cpa.name + ">"; })
|
|
@@ -281,6 +347,26 @@ void bind_mechanism_configuration(py::module_ & mechanism_configuration)
|
|
|
281
347
|
.def("__repr__", [](const Troe &t) { return "<Troe: " + t.name + ">"; })
|
|
282
348
|
.def_property_readonly("type", [](const Troe &) { return ReactionType::Troe; });
|
|
283
349
|
|
|
350
|
+
py::class_<TernaryChemicalActivation>(mechanism_configuration, "_TernaryChemicalActivation")
|
|
351
|
+
.def(py::init<>())
|
|
352
|
+
.def_readwrite("k0_A", &TernaryChemicalActivation::k0_A)
|
|
353
|
+
.def_readwrite("k0_B", &TernaryChemicalActivation::k0_B)
|
|
354
|
+
.def_readwrite("k0_C", &TernaryChemicalActivation::k0_C)
|
|
355
|
+
.def_readwrite("kinf_A", &TernaryChemicalActivation::kinf_A)
|
|
356
|
+
.def_readwrite("kinf_B", &TernaryChemicalActivation::kinf_B)
|
|
357
|
+
.def_readwrite("kinf_C", &TernaryChemicalActivation::kinf_C)
|
|
358
|
+
.def_readwrite("Fc", &TernaryChemicalActivation::Fc)
|
|
359
|
+
.def_readwrite("N", &TernaryChemicalActivation::N)
|
|
360
|
+
.def_readwrite("reactants", &TernaryChemicalActivation::reactants)
|
|
361
|
+
.def_readwrite("products", &TernaryChemicalActivation::products)
|
|
362
|
+
.def_readwrite("name", &TernaryChemicalActivation::name)
|
|
363
|
+
.def_readwrite("gas_phase", &TernaryChemicalActivation::gas_phase)
|
|
364
|
+
.def_readwrite("other_properties", &TernaryChemicalActivation::unknown_properties)
|
|
365
|
+
.def("__str__", [](const TernaryChemicalActivation &t) { return t.name; })
|
|
366
|
+
.def("__repr__", [](const TernaryChemicalActivation &t) { return "<TernaryChemicalActivation: " + t.name + ">"; })
|
|
367
|
+
.def_property_readonly(
|
|
368
|
+
"type", [](const TernaryChemicalActivation &) { return ReactionType::TernaryChemicalActivation; });
|
|
369
|
+
|
|
284
370
|
py::class_<Branched>(mechanism_configuration, "_Branched")
|
|
285
371
|
.def(py::init<>())
|
|
286
372
|
.def_readwrite("X", &Branched::X)
|
|
@@ -318,7 +404,7 @@ void bind_mechanism_configuration(py::module_ & mechanism_configuration)
|
|
|
318
404
|
.def_readwrite("gas_phase_products", &Surface::gas_phase_products)
|
|
319
405
|
.def_readwrite("name", &Surface::name)
|
|
320
406
|
.def_readwrite("gas_phase", &Surface::gas_phase)
|
|
321
|
-
.def_readwrite("
|
|
407
|
+
.def_readwrite("condensed_phase", &Surface::condensed_phase)
|
|
322
408
|
.def_readwrite("other_properties", &Surface::unknown_properties)
|
|
323
409
|
.def("__str__", [](const Surface &s) { return s.name; })
|
|
324
410
|
.def("__repr__", [](const Surface &s) { return "<Surface: " + s.name + ">"; })
|
|
@@ -342,12 +428,12 @@ void bind_mechanism_configuration(py::module_ & mechanism_configuration)
|
|
|
342
428
|
.def_readwrite("reactants", &CondensedPhasePhotolysis::reactants)
|
|
343
429
|
.def_readwrite("products", &CondensedPhasePhotolysis::products)
|
|
344
430
|
.def_readwrite("name", &CondensedPhasePhotolysis::name)
|
|
345
|
-
.def_readwrite("
|
|
346
|
-
.def_readwrite("aerosol_phase_water", &CondensedPhasePhotolysis::aerosol_phase_water)
|
|
431
|
+
.def_readwrite("condensed_phase", &CondensedPhasePhotolysis::condensed_phase)
|
|
347
432
|
.def_readwrite("other_properties", &CondensedPhasePhotolysis::unknown_properties)
|
|
348
433
|
.def("__str__", [](const CondensedPhasePhotolysis &cpp) { return cpp.name; })
|
|
349
434
|
.def("__repr__", [](const CondensedPhasePhotolysis &cpp) { return "<CondensedPhasePhotolysis: " + cpp.name + ">"; })
|
|
350
|
-
.def_property_readonly(
|
|
435
|
+
.def_property_readonly(
|
|
436
|
+
"type", [](const CondensedPhasePhotolysis &) { return ReactionType::CondensedPhasePhotolysis; });
|
|
351
437
|
|
|
352
438
|
py::class_<Emission>(mechanism_configuration, "_Emission")
|
|
353
439
|
.def(py::init<>())
|
|
@@ -374,8 +460,8 @@ void bind_mechanism_configuration(py::module_ & mechanism_configuration)
|
|
|
374
460
|
py::class_<AqueousEquilibrium>(mechanism_configuration, "_AqueousEquilibrium")
|
|
375
461
|
.def(py::init<>())
|
|
376
462
|
.def_readwrite("name", &AqueousEquilibrium::name)
|
|
377
|
-
.def_readwrite("
|
|
378
|
-
.def_readwrite("
|
|
463
|
+
.def_readwrite("condensed_phase", &AqueousEquilibrium::condensed_phase)
|
|
464
|
+
.def_readwrite("condensed_phase_water", &AqueousEquilibrium::condensed_phase_water)
|
|
379
465
|
.def_readwrite("reactants", &AqueousEquilibrium::reactants)
|
|
380
466
|
.def_readwrite("products", &AqueousEquilibrium::products)
|
|
381
467
|
.def_readwrite("A", &AqueousEquilibrium::A)
|
|
@@ -390,7 +476,7 @@ void bind_mechanism_configuration(py::module_ & mechanism_configuration)
|
|
|
390
476
|
.def(py::init<>())
|
|
391
477
|
.def_readwrite("scaling_factor", &WetDeposition::scaling_factor)
|
|
392
478
|
.def_readwrite("name", &WetDeposition::name)
|
|
393
|
-
.def_readwrite("
|
|
479
|
+
.def_readwrite("condensed_phase", &WetDeposition::condensed_phase)
|
|
394
480
|
.def_readwrite("other_properties", &WetDeposition::unknown_properties)
|
|
395
481
|
.def("__str__", [](const WetDeposition &wd) { return wd.name; })
|
|
396
482
|
.def("__repr__", [](const WetDeposition &wd) { return "<WetDeposition: " + wd.name + ">"; })
|
|
@@ -399,11 +485,6 @@ void bind_mechanism_configuration(py::module_ & mechanism_configuration)
|
|
|
399
485
|
py::class_<HenrysLaw>(mechanism_configuration, "_HenrysLaw")
|
|
400
486
|
.def(py::init<>())
|
|
401
487
|
.def_readwrite("name", &HenrysLaw::name)
|
|
402
|
-
.def_readwrite("gas_phase", &HenrysLaw::gas_phase)
|
|
403
|
-
.def_readwrite("gas_phase_species", &HenrysLaw::gas_phase_species)
|
|
404
|
-
.def_readwrite("aerosol_phase", &HenrysLaw::aerosol_phase)
|
|
405
|
-
.def_readwrite("aerosol_phase_water", &HenrysLaw::aerosol_phase_water)
|
|
406
|
-
.def_readwrite("aerosol_phase_species", &HenrysLaw::aerosol_phase_species)
|
|
407
488
|
.def_readwrite("other_properties", &HenrysLaw::unknown_properties)
|
|
408
489
|
.def("__str__", [](const HenrysLaw &hl) { return hl.name; })
|
|
409
490
|
.def("__repr__", [](const HenrysLaw &hl) { return "<HenrysLaw: " + hl.name + ">"; })
|
|
@@ -413,8 +494,8 @@ void bind_mechanism_configuration(py::module_ & mechanism_configuration)
|
|
|
413
494
|
.def(py::init<>())
|
|
414
495
|
.def_readwrite("gas_phase", &SimpolPhaseTransfer::gas_phase)
|
|
415
496
|
.def_readwrite("gas_phase_species", &SimpolPhaseTransfer::gas_phase_species)
|
|
416
|
-
.def_readwrite("
|
|
417
|
-
.def_readwrite("
|
|
497
|
+
.def_readwrite("condensed_phase", &SimpolPhaseTransfer::condensed_phase)
|
|
498
|
+
.def_readwrite("condensed_phase_species", &SimpolPhaseTransfer::condensed_phase_species)
|
|
418
499
|
.def_readwrite("name", &SimpolPhaseTransfer::name)
|
|
419
500
|
.def_readwrite("B", &SimpolPhaseTransfer::B)
|
|
420
501
|
.def_readwrite("other_properties", &SimpolPhaseTransfer::unknown_properties)
|
|
@@ -436,9 +517,7 @@ void bind_mechanism_configuration(py::module_ & mechanism_configuration)
|
|
|
436
517
|
|
|
437
518
|
py::class_<Reactions>(mechanism_configuration, "_Reactions")
|
|
438
519
|
.def(py::init<>())
|
|
439
|
-
.def(py::init([](const py::list &reactions) {
|
|
440
|
-
return create_reactions(reactions);
|
|
441
|
-
}))
|
|
520
|
+
.def(py::init([](const py::list &reactions) { return create_reactions(reactions); }))
|
|
442
521
|
.def_readwrite("arrhenius", &Reactions::arrhenius)
|
|
443
522
|
.def_readwrite("branched", &Reactions::branched)
|
|
444
523
|
.def_readwrite("condensed_phase_arrhenius", &Reactions::condensed_phase_arrhenius)
|
|
@@ -452,15 +531,17 @@ void bind_mechanism_configuration(py::module_ & mechanism_configuration)
|
|
|
452
531
|
.def_readwrite("photolysis", &Reactions::photolysis)
|
|
453
532
|
.def_readwrite("surface", &Reactions::surface)
|
|
454
533
|
.def_readwrite("troe", &Reactions::troe)
|
|
534
|
+
.def_readwrite("ternary_chemical_activation", &Reactions::ternary_chemical_activation)
|
|
455
535
|
.def_readwrite("tunneling", &Reactions::tunneling)
|
|
456
536
|
.def_readwrite("user_defined", &Reactions::user_defined)
|
|
457
537
|
.def(
|
|
458
538
|
"__len__",
|
|
459
539
|
[](const Reactions &r)
|
|
460
540
|
{
|
|
461
|
-
return r.arrhenius.size() + r.branched.size() + r.condensed_phase_arrhenius.size() +
|
|
462
|
-
r.
|
|
463
|
-
r.
|
|
541
|
+
return r.arrhenius.size() + r.branched.size() + r.condensed_phase_arrhenius.size() +
|
|
542
|
+
r.condensed_phase_photolysis.size() + r.emission.size() + r.first_order_loss.size() +
|
|
543
|
+
r.simpol_phase_transfer.size() + r.aqueous_equilibrium.size() + r.wet_deposition.size() +
|
|
544
|
+
r.henrys_law.size() + r.photolysis.size() + r.surface.size() + r.troe.size() + r.tunneling.size() +
|
|
464
545
|
r.user_defined.size();
|
|
465
546
|
})
|
|
466
547
|
.def("__str__", [](const Reactions &r) { return "Reactions"; })
|
|
@@ -514,5 +595,13 @@ void bind_mechanism_configuration(py::module_ & mechanism_configuration)
|
|
|
514
595
|
}
|
|
515
596
|
throw std::runtime_error(error);
|
|
516
597
|
}
|
|
517
|
-
})
|
|
598
|
+
})
|
|
599
|
+
.def(
|
|
600
|
+
"parse_and_convert_v0",
|
|
601
|
+
[](V1Parser &self, const std::string &path)
|
|
602
|
+
{
|
|
603
|
+
mechanism_configuration::v1::types::Mechanism mechanism = musica::ConvertV0MechanismToV1(path);
|
|
604
|
+
return mechanism;
|
|
605
|
+
},
|
|
606
|
+
"Parse a v0 mechanism configuration file");
|
|
518
607
|
}
|
musica/musica.cpp
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// Copyright (C) 2023-2025 University Corporation for Atmospheric Research
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#include <musica/micm/cuda_availability.hpp>
|
|
3
4
|
#include <musica/micm/micm.hpp>
|
|
4
5
|
#include <musica/micm/micm_c_interface.hpp>
|
|
5
|
-
#include <musica/micm/state_c_interface.hpp>
|
|
6
6
|
#include <musica/micm/state.hpp>
|
|
7
|
-
#include <
|
|
8
|
-
#include <musica/micm/cuda_availability.hpp>
|
|
7
|
+
#include <musica/micm/state_c_interface.hpp>
|
|
9
8
|
|
|
9
|
+
#include <mechanism_configuration/v1/types.hpp>
|
|
10
10
|
#include <pybind11/pybind11.h>
|
|
11
11
|
#include <pybind11/stl.h>
|
|
12
12
|
#include <pybind11/stl_bind.h>
|
|
@@ -21,7 +21,7 @@ void bind_musica(py::module_ &core)
|
|
|
21
21
|
{
|
|
22
22
|
py::bind_vector<std::vector<double>>(core, "VectorDouble");
|
|
23
23
|
py::bind_vector<std::vector<micm::Conditions>>(core, "VectorConditions");
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
py::class_<micm::Conditions>(core, "_Conditions")
|
|
26
26
|
.def(py::init<>())
|
|
27
27
|
.def_readwrite("temperature", &micm::Conditions::temperature_)
|
|
@@ -30,40 +30,27 @@ void bind_musica(py::module_ &core)
|
|
|
30
30
|
|
|
31
31
|
py::class_<musica::State>(core, "_State")
|
|
32
32
|
.def(py::init<>())
|
|
33
|
-
.def("__del__", [](musica::State &state) {
|
|
34
|
-
.def("number_of_grid_cells",
|
|
35
|
-
[](musica::State &state) {
|
|
36
|
-
return state.NumberOfGridCells();
|
|
37
|
-
})
|
|
33
|
+
.def("__del__", [](musica::State &state) {})
|
|
34
|
+
.def("number_of_grid_cells", [](musica::State &state) { return state.NumberOfGridCells(); })
|
|
38
35
|
.def_property(
|
|
39
36
|
"conditions",
|
|
40
|
-
[](musica::State &state) -> std::vector<micm::Conditions
|
|
41
|
-
return state.GetConditions();
|
|
42
|
-
},
|
|
37
|
+
[](musica::State &state) -> std::vector<micm::Conditions> & { return state.GetConditions(); },
|
|
43
38
|
nullptr,
|
|
44
39
|
"list of conditions structs for each grid cell")
|
|
45
40
|
.def_property(
|
|
46
41
|
"concentrations",
|
|
47
|
-
[](musica::State &state) -> std::vector<double
|
|
48
|
-
return state.GetOrderedConcentrations();
|
|
49
|
-
},
|
|
42
|
+
[](musica::State &state) -> std::vector<double> & { return state.GetOrderedConcentrations(); },
|
|
50
43
|
nullptr,
|
|
51
44
|
"native 1D list of concentrations, ordered by species and grid cell according to matrix type")
|
|
52
45
|
.def_property(
|
|
53
46
|
"user_defined_rate_parameters",
|
|
54
|
-
[](musica::State &state) -> std::vector<double
|
|
55
|
-
return state.GetOrderedRateParameters();
|
|
56
|
-
},
|
|
47
|
+
[](musica::State &state) -> std::vector<double> & { return state.GetOrderedRateParameters(); },
|
|
57
48
|
nullptr,
|
|
58
49
|
"native 1D list of user-defined rate parameters, ordered by parameter and grid cell according to matrix type")
|
|
59
|
-
.def("concentration_strides",
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
})
|
|
63
|
-
.def("user_defined_rate_parameter_strides",
|
|
64
|
-
[](musica::State &state) {
|
|
65
|
-
return state.GetUserDefinedRateParametersStrides();
|
|
66
|
-
});
|
|
50
|
+
.def("concentration_strides", [](musica::State &state) { return state.GetConcentrationsStrides(); })
|
|
51
|
+
.def(
|
|
52
|
+
"user_defined_rate_parameter_strides",
|
|
53
|
+
[](musica::State &state) { return state.GetUserDefinedRateParametersStrides(); });
|
|
67
54
|
|
|
68
55
|
py::enum_<musica::MICMSolver>(core, "_SolverType")
|
|
69
56
|
.value("rosenbrock", musica::MICMSolver::Rosenbrock)
|
|
@@ -74,20 +61,18 @@ void bind_musica(py::module_ &core)
|
|
|
74
61
|
|
|
75
62
|
py::class_<musica::MICM>(core, "_Solver");
|
|
76
63
|
|
|
77
|
-
core.def(
|
|
64
|
+
core.def(
|
|
65
|
+
"_vector_size",
|
|
78
66
|
[](const musica::MICMSolver solver_type)
|
|
79
67
|
{
|
|
80
68
|
switch (solver_type)
|
|
81
69
|
{
|
|
82
70
|
case musica::MICMSolver::Rosenbrock:
|
|
83
71
|
case musica::MICMSolver::BackwardEuler:
|
|
84
|
-
case musica::MICMSolver::CudaRosenbrock:
|
|
85
|
-
return musica::MUSICA_VECTOR_SIZE;
|
|
72
|
+
case musica::MICMSolver::CudaRosenbrock: return musica::MUSICA_VECTOR_SIZE;
|
|
86
73
|
case musica::MICMSolver::RosenbrockStandardOrder:
|
|
87
|
-
case musica::MICMSolver::BackwardEulerStandardOrder:
|
|
88
|
-
|
|
89
|
-
default:
|
|
90
|
-
throw py::value_error("Invalid MICM solver type.");
|
|
74
|
+
case musica::MICMSolver::BackwardEulerStandardOrder: return static_cast<std::size_t>(0);
|
|
75
|
+
default: throw py::value_error("Invalid MICM solver type.");
|
|
91
76
|
}
|
|
92
77
|
},
|
|
93
78
|
"Returns the vector dimension for vector-ordered solvers, 0 otherwise.");
|
|
@@ -111,10 +96,10 @@ void bind_musica(py::module_ &core)
|
|
|
111
96
|
|
|
112
97
|
core.def(
|
|
113
98
|
"_create_solver_from_mechanism",
|
|
114
|
-
[](const v1::Mechanism &mechanism, musica::MICMSolver solver_type)
|
|
99
|
+
[](const v1::Mechanism &mechanism, musica::MICMSolver solver_type, bool ignore_non_gas_phases)
|
|
115
100
|
{
|
|
116
101
|
musica::Error error;
|
|
117
|
-
musica::Chemistry chemistry = musica::ConvertV1Mechanism(mechanism);
|
|
102
|
+
musica::Chemistry chemistry = musica::ConvertV1Mechanism(mechanism, ignore_non_gas_phases);
|
|
118
103
|
musica::MICM *micm = musica::CreateMicmFromChemistryMechanism(&chemistry, solver_type, &error);
|
|
119
104
|
if (!musica::IsSuccess(error))
|
|
120
105
|
{
|
|
@@ -124,7 +109,7 @@ void bind_musica(py::module_ &core)
|
|
|
124
109
|
}
|
|
125
110
|
return micm;
|
|
126
111
|
});
|
|
127
|
-
|
|
112
|
+
|
|
128
113
|
core.def(
|
|
129
114
|
"_create_state",
|
|
130
115
|
[](musica::MICM *micm, std::size_t number_of_grid_cells)
|
|
@@ -184,31 +169,33 @@ void bind_musica(py::module_ &core)
|
|
|
184
169
|
"_print_state",
|
|
185
170
|
[](musica::State *state, const double current_time)
|
|
186
171
|
{
|
|
187
|
-
std::visit(
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
172
|
+
std::visit(
|
|
173
|
+
[¤t_time](auto &state)
|
|
174
|
+
{
|
|
175
|
+
std::cout << "Current time: " << current_time << std::endl;
|
|
176
|
+
std::cout << "State variables: " << std::endl;
|
|
177
|
+
std::vector<std::string> species_names(state.variable_map_.size());
|
|
178
|
+
for (const auto &species : state.variable_map_)
|
|
179
|
+
species_names[species.second] = species.first;
|
|
180
|
+
for (const auto &name : species_names)
|
|
181
|
+
std::cout << name << ",";
|
|
182
|
+
std::cout << std::endl << state.variables_ << std::endl;
|
|
183
|
+
std::cout << "User-defined rate parameters: " << std::endl;
|
|
184
|
+
std::vector<std::string> rate_param_names(state.custom_rate_parameter_map_.size());
|
|
185
|
+
for (const auto &rate : state.custom_rate_parameter_map_)
|
|
186
|
+
rate_param_names[rate.second] = rate.first;
|
|
187
|
+
for (const auto &name : rate_param_names)
|
|
188
|
+
std::cout << name << ",";
|
|
189
|
+
std::cout << std::endl << state.custom_rate_parameters_ << std::endl;
|
|
190
|
+
std::cout << "Conditions: " << std::endl;
|
|
191
|
+
std::cout << "Temperature,Pressure,Air density" << std::endl;
|
|
192
|
+
for (const auto &condition : state.conditions_)
|
|
193
|
+
{
|
|
194
|
+
std::cout << condition.temperature_ << "," << condition.pressure_ << "," << condition.air_density_
|
|
195
|
+
<< std::endl;
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
state->state_variant_);
|
|
212
199
|
},
|
|
213
200
|
"Print the state to stdout with the current time");
|
|
214
201
|
}
|