musica 0.12.2__cp39-cp39-macosx_15_0_x86_64.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/.dylibs/libaec.0.1.4.dylib +0 -0
- musica/.dylibs/libgcc_s.1.1.dylib +0 -0
- musica/.dylibs/libgfortran.5.dylib +0 -0
- musica/.dylibs/libhdf5.310.5.1.dylib +0 -0
- musica/.dylibs/libhdf5_hl.310.0.6.dylib +0 -0
- musica/.dylibs/libnetcdf.22.dylib +0 -0
- musica/.dylibs/libnetcdff.7.1.0.dylib +0 -0
- musica/.dylibs/libquadmath.0.dylib +0 -0
- musica/.dylibs/libsz.2.0.1.dylib +0 -0
- musica/.dylibs/libzstd.1.5.7.dylib +0 -0
- musica/CMakeLists.txt +68 -0
- musica/__init__.py +11 -0
- musica/_musica.cpython-39-darwin.so +0 -0
- musica/_version.py +1 -0
- musica/backend.py +41 -0
- musica/binding_common.cpp +33 -0
- musica/binding_common.hpp +7 -0
- musica/carma.cpp +911 -0
- musica/carma.py +1729 -0
- musica/constants.py +3 -0
- musica/cpu_binding.cpp +11 -0
- musica/cuda.cpp +12 -0
- musica/cuda.py +13 -0
- 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 +11 -0
- musica/main.py +89 -0
- musica/mechanism_configuration/__init__.py +1 -0
- musica/mechanism_configuration/aqueous_equilibrium.py +274 -0
- musica/mechanism_configuration/arrhenius.py +307 -0
- musica/mechanism_configuration/branched.py +299 -0
- musica/mechanism_configuration/condensed_phase_arrhenius.py +309 -0
- musica/mechanism_configuration/condensed_phase_photolysis.py +88 -0
- musica/mechanism_configuration/emission.py +71 -0
- musica/mechanism_configuration/first_order_loss.py +174 -0
- musica/mechanism_configuration/henrys_law.py +44 -0
- musica/mechanism_configuration/mechanism_configuration.py +234 -0
- musica/mechanism_configuration/phase.py +47 -0
- musica/mechanism_configuration/photolysis.py +88 -0
- musica/mechanism_configuration/reactions.py +73 -0
- musica/mechanism_configuration/simpol_phase_transfer.py +217 -0
- musica/mechanism_configuration/species.py +91 -0
- musica/mechanism_configuration/surface.py +94 -0
- musica/mechanism_configuration/ternary_chemical_activation.py +352 -0
- musica/mechanism_configuration/troe.py +352 -0
- musica/mechanism_configuration/tunneling.py +250 -0
- musica/mechanism_configuration/user_defined.py +88 -0
- musica/mechanism_configuration/utils.py +10 -0
- musica/mechanism_configuration/wet_deposition.py +52 -0
- musica/mechanism_configuration.cpp +607 -0
- musica/musica.cpp +201 -0
- musica/test/examples/v1/full_configuration/full_configuration.json +466 -0
- musica/test/examples/v1/full_configuration/full_configuration.yaml +295 -0
- musica/test/integration/test_analytical.py +324 -0
- 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_chapman.py +139 -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/unit/test_serializer.py +69 -0
- musica/test/unit/test_state.py +325 -0
- musica/test/unit/test_util_full_mechanism.py +698 -0
- musica/tools/prepare_build_environment_linux.sh +32 -0
- musica/tools/prepare_build_environment_macos.sh +1 -0
- musica/tools/repair_wheel_gpu.sh +40 -0
- musica/tuvx.cpp +93 -0
- musica/tuvx.py +199 -0
- musica/types.py +407 -0
- musica-0.12.2.dist-info/METADATA +473 -0
- musica-0.12.2.dist-info/RECORD +80 -0
- musica-0.12.2.dist-info/WHEEL +6 -0
- musica-0.12.2.dist-info/entry_points.txt +3 -0
- musica-0.12.2.dist-info/licenses/AUTHORS.md +59 -0
- musica-0.12.2.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.0.0
|
|
3
|
+
name: Full Configuration
|
|
4
|
+
species:
|
|
5
|
+
- name: A
|
|
6
|
+
__absolute tolerance: 1.0e-30
|
|
7
|
+
- name: B
|
|
8
|
+
tracer type: AEROSOL
|
|
9
|
+
- name: C
|
|
10
|
+
tracer type: THIRD_BODY
|
|
11
|
+
- name: M
|
|
12
|
+
- name: H2O2
|
|
13
|
+
HLC(298K) [mol m-3 Pa-1]: 1.011596348
|
|
14
|
+
HLC exponential factor [K]: 6340
|
|
15
|
+
diffusion coefficient [m2 s-1]: 1.46e-05
|
|
16
|
+
N star: 1.74
|
|
17
|
+
molecular weight [kg mol-1]: 0.0340147
|
|
18
|
+
density [kg m-3]: 1000
|
|
19
|
+
__absolute tolerance: 1.0e-10
|
|
20
|
+
- name: ethanol
|
|
21
|
+
diffusion coefficient [m2 s-1]: 9.5e-06
|
|
22
|
+
N star: 2.55
|
|
23
|
+
molecular weight [kg mol-1]: 0.04607
|
|
24
|
+
__absolute tolerance: 1.0e-20
|
|
25
|
+
- name: ethanol_aq
|
|
26
|
+
molecular weight [kg mol-1]: 0.04607
|
|
27
|
+
density [kg m-3]: 1000
|
|
28
|
+
__absolute tolerance: 1.0e-20
|
|
29
|
+
- name: H2O2_aq
|
|
30
|
+
molecular weight [kg mol-1]: 0.0340147
|
|
31
|
+
density [kg m-3]: 1000
|
|
32
|
+
__absolute tolerance: 1.0e-10
|
|
33
|
+
- name: H2O_aq
|
|
34
|
+
density [kg m-3]: 1000
|
|
35
|
+
molecular weight [kg mol-1]: 0.01801
|
|
36
|
+
- name: aerosol stuff
|
|
37
|
+
molecular weight [kg mol-1]: 0.5
|
|
38
|
+
density [kg m-3]: 1000
|
|
39
|
+
__absolute tolerance: 1.0e-20
|
|
40
|
+
- name: more aerosol stuff
|
|
41
|
+
molecular weight [kg mol-1]: 0.2
|
|
42
|
+
density [kg m-3]: 1000
|
|
43
|
+
__absolute tolerance: 1.0e-20
|
|
44
|
+
phases:
|
|
45
|
+
- name: gas
|
|
46
|
+
species:
|
|
47
|
+
- A
|
|
48
|
+
- B
|
|
49
|
+
- C
|
|
50
|
+
- ethanol
|
|
51
|
+
- name: aqueous aerosol
|
|
52
|
+
species:
|
|
53
|
+
- H2O2_aq
|
|
54
|
+
- H2O_aq
|
|
55
|
+
- ethanol_aq
|
|
56
|
+
- A
|
|
57
|
+
- B
|
|
58
|
+
- C
|
|
59
|
+
- name: surface reacting phase
|
|
60
|
+
species:
|
|
61
|
+
- aerosol stuff
|
|
62
|
+
- more aerosol stuff
|
|
63
|
+
- name: cloud
|
|
64
|
+
species:
|
|
65
|
+
- B
|
|
66
|
+
- C
|
|
67
|
+
reactions:
|
|
68
|
+
- type: SIMPOL_PHASE_TRANSFER
|
|
69
|
+
gas phase: gas
|
|
70
|
+
gas-phase species: ethanol
|
|
71
|
+
condensed phase: aqueous aerosol
|
|
72
|
+
condensed-phase species: ethanol_aq
|
|
73
|
+
B:
|
|
74
|
+
- -1970
|
|
75
|
+
- 2.91
|
|
76
|
+
- 0.00196
|
|
77
|
+
- -0.496
|
|
78
|
+
name: my simpol
|
|
79
|
+
__irrelevant: "2"
|
|
80
|
+
- type: AQUEOUS_EQUILIBRIUM
|
|
81
|
+
condensed phase: aqueous aerosol
|
|
82
|
+
condensed-phase water: H2O_aq
|
|
83
|
+
A: 0.0114
|
|
84
|
+
C: 2300
|
|
85
|
+
k_reverse: 0.32
|
|
86
|
+
reactants:
|
|
87
|
+
- species name: A
|
|
88
|
+
coefficient: 2
|
|
89
|
+
products:
|
|
90
|
+
- species name: B
|
|
91
|
+
coefficient: 1
|
|
92
|
+
- species name: C
|
|
93
|
+
coefficient: 1
|
|
94
|
+
name: my aqueous eq
|
|
95
|
+
__irrelevant: "2"
|
|
96
|
+
- type: CONDENSED_PHASE_ARRHENIUS
|
|
97
|
+
condensed phase: aqueous aerosol
|
|
98
|
+
A: 123.45
|
|
99
|
+
Ea: 123.45
|
|
100
|
+
B: 1.3
|
|
101
|
+
D: 300
|
|
102
|
+
E: 6.0e-06
|
|
103
|
+
reactants:
|
|
104
|
+
- species name: H2O2_aq
|
|
105
|
+
coefficient: 1
|
|
106
|
+
- species name: H2O_aq
|
|
107
|
+
coefficient: 1
|
|
108
|
+
products:
|
|
109
|
+
- species name: ethanol_aq
|
|
110
|
+
coefficient: 1
|
|
111
|
+
name: my condensed arrhenius
|
|
112
|
+
__irrelevant: "2"
|
|
113
|
+
- type: CONDENSED_PHASE_ARRHENIUS
|
|
114
|
+
condensed phase: aqueous aerosol
|
|
115
|
+
A: 123.45
|
|
116
|
+
C: 123.45
|
|
117
|
+
B: 1.3
|
|
118
|
+
D: 300
|
|
119
|
+
E: 6.0e-06
|
|
120
|
+
reactants:
|
|
121
|
+
- species name: H2O2_aq
|
|
122
|
+
coefficient: 1
|
|
123
|
+
- species name: H2O_aq
|
|
124
|
+
coefficient: 1
|
|
125
|
+
products:
|
|
126
|
+
- species name: ethanol_aq
|
|
127
|
+
coefficient: 1
|
|
128
|
+
name: my other condensed arrhenius
|
|
129
|
+
- type: CONDENSED_PHASE_PHOTOLYSIS
|
|
130
|
+
condensed phase: aqueous aerosol
|
|
131
|
+
reactants:
|
|
132
|
+
- species name: H2O2_aq
|
|
133
|
+
coefficient: 1
|
|
134
|
+
products:
|
|
135
|
+
- species name: ethanol_aq
|
|
136
|
+
coefficient: 1
|
|
137
|
+
scaling factor: 12.3
|
|
138
|
+
name: condensed photo B
|
|
139
|
+
__irrelevant: "2"
|
|
140
|
+
- type: EMISSION
|
|
141
|
+
gas phase: gas
|
|
142
|
+
products:
|
|
143
|
+
- species name: B
|
|
144
|
+
coefficient: 1
|
|
145
|
+
name: my emission
|
|
146
|
+
scaling factor: 12.3
|
|
147
|
+
__irrelevant: "2"
|
|
148
|
+
- type: FIRST_ORDER_LOSS
|
|
149
|
+
gas phase: gas
|
|
150
|
+
reactants:
|
|
151
|
+
- species name: C
|
|
152
|
+
coefficient: 1
|
|
153
|
+
name: my first order loss
|
|
154
|
+
scaling factor: 12.3
|
|
155
|
+
__irrelevant: "2"
|
|
156
|
+
- type: PHOTOLYSIS
|
|
157
|
+
gas phase: gas
|
|
158
|
+
reactants:
|
|
159
|
+
- species name: B
|
|
160
|
+
coefficient: 1
|
|
161
|
+
products:
|
|
162
|
+
- species name: C
|
|
163
|
+
coefficient: 1
|
|
164
|
+
name: photo B
|
|
165
|
+
scaling factor: 12.3
|
|
166
|
+
__irrelevant: "2"
|
|
167
|
+
- type: SURFACE
|
|
168
|
+
gas phase: gas
|
|
169
|
+
gas-phase species: A
|
|
170
|
+
reaction probability: 0.02
|
|
171
|
+
gas-phase products:
|
|
172
|
+
- species name: B
|
|
173
|
+
coefficient: 1
|
|
174
|
+
- species name: C
|
|
175
|
+
coefficient: 1
|
|
176
|
+
condensed phase: surface reacting phase
|
|
177
|
+
name: my surface
|
|
178
|
+
__irrelevant: "2"
|
|
179
|
+
- type: TROE
|
|
180
|
+
gas phase: gas
|
|
181
|
+
reactants:
|
|
182
|
+
- species name: B
|
|
183
|
+
coefficient: 1
|
|
184
|
+
- species name: M
|
|
185
|
+
coefficient: 1
|
|
186
|
+
products:
|
|
187
|
+
- species name: C
|
|
188
|
+
coefficient: 1
|
|
189
|
+
k0_A: 1.2e-12
|
|
190
|
+
k0_B: 167
|
|
191
|
+
k0_C: 3
|
|
192
|
+
kinf_A: 136
|
|
193
|
+
kinf_B: 5
|
|
194
|
+
kinf_C: 24
|
|
195
|
+
Fc: 0.9
|
|
196
|
+
N: 0.8
|
|
197
|
+
name: my troe
|
|
198
|
+
__irrelevant: "2"
|
|
199
|
+
- type: TERNARY_CHEMICAL_ACTIVATION
|
|
200
|
+
gas phase: gas
|
|
201
|
+
name: my ternary chemical activation
|
|
202
|
+
reactants:
|
|
203
|
+
- species name: B
|
|
204
|
+
coefficient: 1
|
|
205
|
+
- species name: M
|
|
206
|
+
coefficient: 1
|
|
207
|
+
products:
|
|
208
|
+
- species name: C
|
|
209
|
+
coefficient: 1
|
|
210
|
+
k0_A: 32.1
|
|
211
|
+
k0_B: -2.3
|
|
212
|
+
k0_C: 102.3
|
|
213
|
+
kinf_A: 63.4
|
|
214
|
+
kinf_B: -1.3
|
|
215
|
+
kinf_C: 908.5
|
|
216
|
+
Fc: 1.3
|
|
217
|
+
"N": 32.1
|
|
218
|
+
__irrelevant: "2"
|
|
219
|
+
- type: BRANCHED_NO_RO2
|
|
220
|
+
gas phase: gas
|
|
221
|
+
reactants:
|
|
222
|
+
- species name: A
|
|
223
|
+
coefficient: 1
|
|
224
|
+
alkoxy products:
|
|
225
|
+
- species name: B
|
|
226
|
+
coefficient: 1
|
|
227
|
+
nitrate products:
|
|
228
|
+
- species name: C
|
|
229
|
+
coefficient: 1
|
|
230
|
+
X: 0.00012
|
|
231
|
+
Y: 167
|
|
232
|
+
a0: 0.15
|
|
233
|
+
"n": 9
|
|
234
|
+
name: my branched
|
|
235
|
+
__irrelevant: "2"
|
|
236
|
+
- gas phase: gas
|
|
237
|
+
type: TUNNELING
|
|
238
|
+
name: "my tunneling"
|
|
239
|
+
A: 123.45
|
|
240
|
+
B: 1200
|
|
241
|
+
C: 100000000
|
|
242
|
+
reactants:
|
|
243
|
+
- species name: B
|
|
244
|
+
coefficient: 1
|
|
245
|
+
products:
|
|
246
|
+
- species name: C
|
|
247
|
+
coefficient: 1
|
|
248
|
+
__irrelevant: "2"
|
|
249
|
+
- type: WET_DEPOSITION
|
|
250
|
+
condensed phase: cloud
|
|
251
|
+
name: rxn cloud
|
|
252
|
+
scaling factor: 12.3
|
|
253
|
+
__irrelevant: "2"
|
|
254
|
+
- type: ARRHENIUS
|
|
255
|
+
gas phase: gas
|
|
256
|
+
reactants:
|
|
257
|
+
- species name: B
|
|
258
|
+
coefficient: 1
|
|
259
|
+
products:
|
|
260
|
+
- species name: C
|
|
261
|
+
coefficient: 1
|
|
262
|
+
A: 32.1
|
|
263
|
+
B: -2.3
|
|
264
|
+
C: 102.3
|
|
265
|
+
D: 63.4
|
|
266
|
+
E: -1.3
|
|
267
|
+
name: my arrhenius
|
|
268
|
+
__irrelevant: "2"
|
|
269
|
+
- type: ARRHENIUS
|
|
270
|
+
gas phase: gas
|
|
271
|
+
reactants:
|
|
272
|
+
- species name: A
|
|
273
|
+
coefficient: 1
|
|
274
|
+
products:
|
|
275
|
+
- species name: B
|
|
276
|
+
coefficient: 1.2
|
|
277
|
+
A: 29.3
|
|
278
|
+
B: -1.5
|
|
279
|
+
Ea: 101.2
|
|
280
|
+
D: 82.6
|
|
281
|
+
E: -0.98
|
|
282
|
+
name: my other arrhenius
|
|
283
|
+
- type: USER_DEFINED
|
|
284
|
+
gas phase: gas
|
|
285
|
+
reactants:
|
|
286
|
+
- species name: A
|
|
287
|
+
coefficient: 1
|
|
288
|
+
- species name: B
|
|
289
|
+
coefficient: 1
|
|
290
|
+
products:
|
|
291
|
+
- species name: C
|
|
292
|
+
coefficient: 1.3
|
|
293
|
+
name: my user defined
|
|
294
|
+
scaling factor: 12.3
|
|
295
|
+
__irrelevant: "2"
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import numpy as np
|
|
3
|
+
import musica
|
|
4
|
+
import random
|
|
5
|
+
import musica.mechanism_configuration as mc
|
|
6
|
+
from musica.cuda import is_cuda_available
|
|
7
|
+
from musica.constants import GAS_CONSTANT
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def TestSingleGridCell(solver, state, time_step, places=5):
|
|
11
|
+
temperature = 272.5
|
|
12
|
+
pressure = 101253.3
|
|
13
|
+
air_density = pressure / (GAS_CONSTANT * temperature)
|
|
14
|
+
|
|
15
|
+
rate_constants = {
|
|
16
|
+
"USER.reaction 1": 0.001,
|
|
17
|
+
"USER.reaction 2": 0.002
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
concentrations = {
|
|
21
|
+
"A": 0.75,
|
|
22
|
+
"B": 0,
|
|
23
|
+
"C": 0.4,
|
|
24
|
+
"D": 0.8,
|
|
25
|
+
"E": 0,
|
|
26
|
+
"F": 0.1
|
|
27
|
+
}
|
|
28
|
+
state.set_conditions(temperature, pressure, air_density)
|
|
29
|
+
state.set_concentrations(concentrations)
|
|
30
|
+
state.set_user_defined_rate_parameters(rate_constants)
|
|
31
|
+
|
|
32
|
+
# test to make sure a second call to set_conditions with an empty dictionary does not change the values
|
|
33
|
+
state.set_concentrations({})
|
|
34
|
+
state.set_user_defined_rate_parameters({})
|
|
35
|
+
|
|
36
|
+
initial_concentrations = state.get_concentrations()
|
|
37
|
+
initial_rate_parameters = state.get_user_defined_rate_parameters()
|
|
38
|
+
initial_temperatures = state.get_conditions()["temperature"]
|
|
39
|
+
initial_pressures = state.get_conditions()["pressure"]
|
|
40
|
+
initial_air_density = state.get_conditions()["air_density"]
|
|
41
|
+
assert np.isclose(initial_concentrations["A"][0], concentrations["A"], atol=1e-13)
|
|
42
|
+
assert np.isclose(initial_concentrations["B"][0], concentrations["B"], atol=1e-13)
|
|
43
|
+
assert np.isclose(initial_concentrations["C"][0], concentrations["C"], atol=1e-13)
|
|
44
|
+
assert np.isclose(initial_concentrations["D"][0], concentrations["D"], atol=1e-13)
|
|
45
|
+
assert np.isclose(initial_concentrations["E"][0], concentrations["E"], atol=1e-13)
|
|
46
|
+
assert np.isclose(initial_concentrations["F"][0], concentrations["F"], atol=1e-13)
|
|
47
|
+
assert np.isclose(initial_rate_parameters["USER.reaction 1"][0], rate_constants["USER.reaction 1"], atol=1e-13)
|
|
48
|
+
assert np.isclose(initial_rate_parameters["USER.reaction 2"][0], rate_constants["USER.reaction 2"], atol=1e-13)
|
|
49
|
+
assert np.isclose(initial_temperatures[0], temperature, atol=1e-13)
|
|
50
|
+
assert np.isclose(initial_pressures[0], pressure, atol=1e-13)
|
|
51
|
+
assert np.isclose(initial_air_density[0], air_density, atol=1e-13)
|
|
52
|
+
|
|
53
|
+
time_step = 1
|
|
54
|
+
sim_length = 100
|
|
55
|
+
|
|
56
|
+
curr_time = time_step
|
|
57
|
+
initial_A = initial_concentrations["A"][0]
|
|
58
|
+
initial_C = initial_concentrations["C"][0]
|
|
59
|
+
initial_D = initial_concentrations["D"][0]
|
|
60
|
+
initial_F = initial_concentrations["F"][0]
|
|
61
|
+
# Gets analytical concentrations
|
|
62
|
+
while curr_time <= sim_length:
|
|
63
|
+
solver.solve(state, time_step)
|
|
64
|
+
concentrations = state.get_concentrations()
|
|
65
|
+
k1 = rate_constants["USER.reaction 1"]
|
|
66
|
+
k2 = rate_constants["USER.reaction 2"]
|
|
67
|
+
k3 = 0.004 * np.exp(50.0 / temperature)
|
|
68
|
+
k4 = 0.012 * np.exp(75.0 / temperature) * \
|
|
69
|
+
(temperature / 50.0)**(-2) * (1.0 + 1.0e-6 * pressure)
|
|
70
|
+
A_conc = initial_A * np.exp(-(k3) * curr_time)
|
|
71
|
+
B_conc = initial_A * (k3 / (k4 - k3)) * \
|
|
72
|
+
(np.exp(-k3 * curr_time) - np.exp(-k4 * curr_time))
|
|
73
|
+
C_conc = initial_C + initial_A * \
|
|
74
|
+
(1.0 + (k3 * np.exp(-k4 * curr_time) - k4 * np.exp(-k3 * curr_time)) / (k4 - k3))
|
|
75
|
+
D_conc = initial_D * np.exp(-(k1) * curr_time)
|
|
76
|
+
E_conc = initial_D * (k1 / (k2 - k1)) * \
|
|
77
|
+
(np.exp(-k1 * curr_time) - np.exp(-k2 * curr_time))
|
|
78
|
+
F_conc = initial_F + initial_D * \
|
|
79
|
+
(1.0 + (k1 * np.exp(-k2 * curr_time) - k2 * np.exp(-k1 * curr_time)) / (k2 - k1))
|
|
80
|
+
|
|
81
|
+
assert np.isclose(concentrations["A"][0], A_conc, atol=10**-places)
|
|
82
|
+
assert np.isclose(concentrations["B"][0], B_conc, atol=10**-places)
|
|
83
|
+
assert np.isclose(concentrations["C"][0], C_conc, atol=10**-places)
|
|
84
|
+
assert np.isclose(concentrations["D"][0], D_conc, atol=10**-places)
|
|
85
|
+
assert np.isclose(concentrations["E"][0], E_conc, atol=10**-places)
|
|
86
|
+
assert np.isclose(concentrations["F"][0], F_conc, atol=10**-places)
|
|
87
|
+
|
|
88
|
+
curr_time += time_step
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def TestMultipleGridCell(solver, state, num_grid_cells, time_step, places=5):
|
|
92
|
+
concentrations = {
|
|
93
|
+
"A": [],
|
|
94
|
+
"B": [],
|
|
95
|
+
"C": [],
|
|
96
|
+
"D": [],
|
|
97
|
+
"E": [],
|
|
98
|
+
"F": []
|
|
99
|
+
}
|
|
100
|
+
rate_constants = {
|
|
101
|
+
"USER.reaction 1": [],
|
|
102
|
+
"USER.reaction 2": []
|
|
103
|
+
}
|
|
104
|
+
temperatures = []
|
|
105
|
+
pressures = []
|
|
106
|
+
|
|
107
|
+
for i in range(num_grid_cells):
|
|
108
|
+
temperatures.append(275.0 + random.uniform(-50.0, 50.0))
|
|
109
|
+
pressures.append(101253.3 + random.uniform(-500.0, 500.0))
|
|
110
|
+
concentrations["A"].append(0.75 + random.uniform(-0.05, 0.05))
|
|
111
|
+
concentrations["B"].append(0)
|
|
112
|
+
concentrations["C"].append(0.4 + random.uniform(-0.05, 0.05))
|
|
113
|
+
concentrations["D"].append(0.8 + random.uniform(-0.05, 0.05))
|
|
114
|
+
concentrations["E"].append(0)
|
|
115
|
+
concentrations["F"].append(0.1 + random.uniform(-0.05, 0.05))
|
|
116
|
+
rate_constants["USER.reaction 1"].append(
|
|
117
|
+
0.001 + random.uniform(-0.0001, 0.0001))
|
|
118
|
+
rate_constants["USER.reaction 2"].append(
|
|
119
|
+
0.002 + random.uniform(-0.0001, 0.0001))
|
|
120
|
+
|
|
121
|
+
state.set_conditions(temperatures, pressures) # Air density should be calculated in the state
|
|
122
|
+
state.set_concentrations(concentrations)
|
|
123
|
+
state.set_user_defined_rate_parameters(rate_constants)
|
|
124
|
+
|
|
125
|
+
initial_concentrations = state.get_concentrations()
|
|
126
|
+
initial_rate_parameters = state.get_user_defined_rate_parameters()
|
|
127
|
+
initial_temperatures = state.get_conditions()["temperature"]
|
|
128
|
+
initial_pressures = state.get_conditions()["pressure"]
|
|
129
|
+
initial_air_density = state.get_conditions()["air_density"]
|
|
130
|
+
|
|
131
|
+
for i in range(num_grid_cells):
|
|
132
|
+
assert np.isclose(initial_concentrations["A"][i], concentrations["A"][i], atol=1e-13)
|
|
133
|
+
assert np.isclose(initial_concentrations["B"][i], concentrations["B"][i], atol=1e-13)
|
|
134
|
+
assert np.isclose(initial_concentrations["C"][i], concentrations["C"][i], atol=1e-13)
|
|
135
|
+
assert np.isclose(initial_concentrations["D"][i], concentrations["D"][i], atol=1e-13)
|
|
136
|
+
assert np.isclose(initial_concentrations["E"][i], concentrations["E"][i], atol=1e-13)
|
|
137
|
+
assert np.isclose(initial_concentrations["F"][i], concentrations["F"][i], atol=1e-13)
|
|
138
|
+
assert np.isclose(
|
|
139
|
+
initial_rate_parameters["USER.reaction 1"][i],
|
|
140
|
+
rate_constants["USER.reaction 1"][i],
|
|
141
|
+
atol=1e-13)
|
|
142
|
+
assert np.isclose(
|
|
143
|
+
initial_rate_parameters["USER.reaction 2"][i],
|
|
144
|
+
rate_constants["USER.reaction 2"][i],
|
|
145
|
+
atol=1e-13)
|
|
146
|
+
assert np.isclose(initial_temperatures[i], temperatures[i], atol=1e-13)
|
|
147
|
+
assert np.isclose(initial_pressures[i], pressures[i], atol=1e-13)
|
|
148
|
+
assert np.isclose(initial_air_density[i], pressures[i] / (8.31446261815324 * temperatures[i]), atol=1e-13)
|
|
149
|
+
|
|
150
|
+
time_step = 1
|
|
151
|
+
sim_length = 100
|
|
152
|
+
|
|
153
|
+
curr_time = time_step
|
|
154
|
+
initial_A = num_grid_cells * [0.0]
|
|
155
|
+
initial_C = num_grid_cells * [0.0]
|
|
156
|
+
initial_D = num_grid_cells * [0.0]
|
|
157
|
+
initial_F = num_grid_cells * [0.0]
|
|
158
|
+
for i in range(num_grid_cells):
|
|
159
|
+
initial_A[i] = initial_concentrations["A"][i]
|
|
160
|
+
initial_C[i] = initial_concentrations["C"][i]
|
|
161
|
+
initial_D[i] = initial_concentrations["D"][i]
|
|
162
|
+
initial_F[i] = initial_concentrations["F"][i]
|
|
163
|
+
|
|
164
|
+
k1 = num_grid_cells * [0.0]
|
|
165
|
+
k2 = num_grid_cells * [0.0]
|
|
166
|
+
k3 = num_grid_cells * [0.0]
|
|
167
|
+
k4 = num_grid_cells * [0.0]
|
|
168
|
+
for i in range(num_grid_cells):
|
|
169
|
+
k1[i] = rate_constants["USER.reaction 1"][i]
|
|
170
|
+
k2[i] = rate_constants["USER.reaction 2"][i]
|
|
171
|
+
k3[i] = 0.004 * np.exp(50.0 / temperatures[i])
|
|
172
|
+
k4[i] = 0.012 * np.exp(75.0 / temperatures[i]) * \
|
|
173
|
+
(temperatures[i] / 50.0)**(-2) * (1.0 + 1.0e-6 * pressures[i])
|
|
174
|
+
|
|
175
|
+
while curr_time <= sim_length:
|
|
176
|
+
solver.solve(state, time_step)
|
|
177
|
+
concentrations = state.get_concentrations()
|
|
178
|
+
|
|
179
|
+
for i in range(num_grid_cells):
|
|
180
|
+
A_conc = initial_A[i] * np.exp(-(k3[i]) * curr_time)
|
|
181
|
+
B_conc = initial_A[i] * (k3[i] / (k4[i] - k3[i])) * \
|
|
182
|
+
(np.exp(-k3[i] * curr_time) - np.exp(-k4[i] * curr_time))
|
|
183
|
+
C_conc = initial_C[i] + initial_A[i] * (1.0 + (
|
|
184
|
+
k3[i] * np.exp(-k4[i] * curr_time) - k4[i] * np.exp(-k3[i] * curr_time)) / (k4[i] - k3[i]))
|
|
185
|
+
D_conc = initial_D[i] * np.exp(-(k1[i]) * curr_time)
|
|
186
|
+
E_conc = initial_D[i] * (k1[i] / (k2[i] - k1[i])) * \
|
|
187
|
+
(np.exp(-k1[i] * curr_time) - np.exp(-k2[i] * curr_time))
|
|
188
|
+
F_conc = initial_F[i] + initial_D[i] * (1.0 + (
|
|
189
|
+
k1[i] * np.exp(-k2[i] * curr_time) - k2[i] * np.exp(-k1[i] * curr_time)) / (k2[i] - k1[i]))
|
|
190
|
+
|
|
191
|
+
assert np.isclose(
|
|
192
|
+
concentrations["A"][i],
|
|
193
|
+
A_conc,
|
|
194
|
+
atol=10**-places), f"Grid cell {i} of {num_grid_cells}: A concentration mismatch. Initial A: {initial_concentrations['A'][i]}"
|
|
195
|
+
assert np.isclose(
|
|
196
|
+
concentrations["B"][i],
|
|
197
|
+
B_conc,
|
|
198
|
+
atol=10**-places), f"Grid cell {i} of {num_grid_cells}: B concentration mismatch. Initial B: {initial_concentrations['B'][i]}"
|
|
199
|
+
assert np.isclose(
|
|
200
|
+
concentrations["C"][i],
|
|
201
|
+
C_conc,
|
|
202
|
+
atol=10**-places), f"Grid cell {i} of {num_grid_cells}: C concentration mismatch. Initial C: {initial_concentrations['C'][i]}"
|
|
203
|
+
assert np.isclose(
|
|
204
|
+
concentrations["D"][i],
|
|
205
|
+
D_conc,
|
|
206
|
+
atol=10**-places), f"Grid cell {i} of {num_grid_cells}: D concentration mismatch. Initial D: {initial_concentrations['D'][i]}"
|
|
207
|
+
assert np.isclose(
|
|
208
|
+
concentrations["E"][i],
|
|
209
|
+
E_conc,
|
|
210
|
+
atol=10**-places), f"Grid cell {i} of {num_grid_cells}: E concentration mismatch. Initial E: {initial_concentrations['E'][i]}"
|
|
211
|
+
assert np.isclose(
|
|
212
|
+
concentrations["F"][i],
|
|
213
|
+
F_conc,
|
|
214
|
+
atol=10**-places), f"Grid cell {i} of {num_grid_cells}: F concentration mismatch. Initial F: {initial_concentrations['F'][i]}"
|
|
215
|
+
|
|
216
|
+
curr_time += time_step
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def GetMechanism():
|
|
220
|
+
A = mc.Species(name="A")
|
|
221
|
+
B = mc.Species(name="B")
|
|
222
|
+
C = mc.Species(name="C")
|
|
223
|
+
D = mc.Species(name="D")
|
|
224
|
+
E = mc.Species(name="E")
|
|
225
|
+
F = mc.Species(name="F")
|
|
226
|
+
gas = mc.Phase(name="gas", species=[A, B, C, D, E, F])
|
|
227
|
+
arr1 = mc.Arrhenius(name="A->B", A=0.004, C=50,
|
|
228
|
+
gas_phase=gas, reactants=[A], products=[B])
|
|
229
|
+
arr2 = mc.Arrhenius(name="B->C", A=0.012, B=-2, C=75, D=50, E=1.0e-6,
|
|
230
|
+
gas_phase=gas, reactants=[B], products=[C])
|
|
231
|
+
user1 = mc.UserDefined(name="reaction 1", gas_phase=gas,
|
|
232
|
+
reactants=[D], products=[E])
|
|
233
|
+
user2 = mc.UserDefined(name="reaction 2", gas_phase=gas,
|
|
234
|
+
reactants=[E], products=[F])
|
|
235
|
+
mechanism = mc.Mechanism(
|
|
236
|
+
name="analytical test",
|
|
237
|
+
species=[A, B, C, D, E, F],
|
|
238
|
+
phases=[gas],
|
|
239
|
+
reactions=[arr1, arr2, user1, user2],
|
|
240
|
+
)
|
|
241
|
+
return mechanism
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def test_single_grid_cell_standard_rosenbrock():
|
|
245
|
+
solver = musica.MICM(
|
|
246
|
+
config_path="configs/v0/analytical",
|
|
247
|
+
solver_type=musica.SolverType.rosenbrock_standard_order)
|
|
248
|
+
state = solver.create_state()
|
|
249
|
+
TestSingleGridCell(solver, state, 200.0, 5)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def test_multiple_grid_cells_standard_rosenbrock():
|
|
253
|
+
for i in range(1, 11):
|
|
254
|
+
solver = musica.MICM(
|
|
255
|
+
config_path="configs/v0/analytical",
|
|
256
|
+
solver_type=musica.SolverType.rosenbrock_standard_order)
|
|
257
|
+
state = solver.create_state(i)
|
|
258
|
+
TestMultipleGridCell(solver, state, i, 200.0, 5)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def test_cuda_rosenbrock():
|
|
262
|
+
if is_cuda_available():
|
|
263
|
+
solver = musica.MICM(
|
|
264
|
+
config_path="configs/v0/analytical",
|
|
265
|
+
solver_type=musica.SolverType.cuda_rosenbrock)
|
|
266
|
+
state = solver.create_state()
|
|
267
|
+
TestSingleGridCell(solver, state, 200.0, 5)
|
|
268
|
+
else:
|
|
269
|
+
pytest.skip("CUDA is not available.")
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def test_single_grid_cell_backward_euler():
|
|
273
|
+
solver = musica.MICM(
|
|
274
|
+
config_path="configs/v0/analytical",
|
|
275
|
+
solver_type=musica.SolverType.backward_euler_standard_order)
|
|
276
|
+
state = solver.create_state()
|
|
277
|
+
TestSingleGridCell(solver, state, 10.0, places=2)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def test_multiple_grid_cells_backward_euler():
|
|
281
|
+
for i in range(1, 11):
|
|
282
|
+
solver = musica.MICM(
|
|
283
|
+
config_path="configs/v0/analytical",
|
|
284
|
+
solver_type=musica.SolverType.backward_euler_standard_order)
|
|
285
|
+
state = solver.create_state(i)
|
|
286
|
+
TestMultipleGridCell(solver, state, i, 10.0, places=2)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def test_single_grid_cell_rosenbrock():
|
|
290
|
+
solver = musica.MICM(
|
|
291
|
+
config_path="configs/v0/analytical",
|
|
292
|
+
solver_type=musica.SolverType.rosenbrock)
|
|
293
|
+
state = solver.create_state()
|
|
294
|
+
TestSingleGridCell(solver, state, 200.0, 5)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def test_multiple_grid_cells_rosenbrock():
|
|
298
|
+
for i in range(1, 11):
|
|
299
|
+
solver = musica.MICM(
|
|
300
|
+
config_path="configs/v0/analytical",
|
|
301
|
+
solver_type=musica.SolverType.rosenbrock)
|
|
302
|
+
state = solver.create_state(i)
|
|
303
|
+
TestMultipleGridCell(solver, state, i, 200.0, 5)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def test_single_grid_cell_backward_euler_standard_order():
|
|
307
|
+
solver = musica.MICM(
|
|
308
|
+
config_path="configs/v0/analytical",
|
|
309
|
+
solver_type=musica.SolverType.backward_euler_standard_order)
|
|
310
|
+
state = solver.create_state()
|
|
311
|
+
TestSingleGridCell(solver, state, 10.0, places=2)
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def test_multiple_grid_cells_backward_euler_standard_order():
|
|
315
|
+
for i in range(1, 11):
|
|
316
|
+
solver = musica.MICM(
|
|
317
|
+
config_path="configs/v0/analytical",
|
|
318
|
+
solver_type=musica.SolverType.backward_euler_standard_order)
|
|
319
|
+
state = solver.create_state(i)
|
|
320
|
+
TestMultipleGridCell(solver, state, i, 10.0, places=2)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
if __name__ == '__main__':
|
|
324
|
+
pytest.main()
|