musica 0.12.2__cp313-cp313-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 (70) hide show
  1. musica/CMakeLists.txt +68 -0
  2. musica/__init__.py +11 -0
  3. musica/_musica.cp313-win_amd64.pyd +0 -0
  4. musica/_version.py +1 -0
  5. musica/backend.py +41 -0
  6. musica/binding_common.cpp +33 -0
  7. musica/binding_common.hpp +7 -0
  8. musica/carma.cpp +911 -0
  9. musica/carma.py +1729 -0
  10. musica/constants.py +3 -0
  11. musica/cpu_binding.cpp +11 -0
  12. musica/cuda.cpp +12 -0
  13. musica/cuda.py +13 -0
  14. musica/examples/__init__.py +1 -0
  15. musica/examples/carma_aluminum.py +124 -0
  16. musica/examples/carma_sulfate.py +246 -0
  17. musica/examples/examples.py +165 -0
  18. musica/examples/sulfate_box_model.py +439 -0
  19. musica/examples/ts1_latin_hypercube.py +245 -0
  20. musica/gpu_binding.cpp +11 -0
  21. musica/main.py +89 -0
  22. musica/mechanism_configuration/__init__.py +1 -0
  23. musica/mechanism_configuration/aqueous_equilibrium.py +274 -0
  24. musica/mechanism_configuration/arrhenius.py +307 -0
  25. musica/mechanism_configuration/branched.py +299 -0
  26. musica/mechanism_configuration/condensed_phase_arrhenius.py +309 -0
  27. musica/mechanism_configuration/condensed_phase_photolysis.py +88 -0
  28. musica/mechanism_configuration/emission.py +71 -0
  29. musica/mechanism_configuration/first_order_loss.py +174 -0
  30. musica/mechanism_configuration/henrys_law.py +44 -0
  31. musica/mechanism_configuration/mechanism_configuration.py +234 -0
  32. musica/mechanism_configuration/phase.py +47 -0
  33. musica/mechanism_configuration/photolysis.py +88 -0
  34. musica/mechanism_configuration/reactions.py +73 -0
  35. musica/mechanism_configuration/simpol_phase_transfer.py +217 -0
  36. musica/mechanism_configuration/species.py +91 -0
  37. musica/mechanism_configuration/surface.py +94 -0
  38. musica/mechanism_configuration/ternary_chemical_activation.py +352 -0
  39. musica/mechanism_configuration/troe.py +352 -0
  40. musica/mechanism_configuration/tunneling.py +250 -0
  41. musica/mechanism_configuration/user_defined.py +88 -0
  42. musica/mechanism_configuration/utils.py +10 -0
  43. musica/mechanism_configuration/wet_deposition.py +52 -0
  44. musica/mechanism_configuration.cpp +607 -0
  45. musica/musica.cpp +201 -0
  46. musica/test/examples/v1/full_configuration/full_configuration.json +466 -0
  47. musica/test/examples/v1/full_configuration/full_configuration.yaml +295 -0
  48. musica/test/integration/test_analytical.py +324 -0
  49. musica/test/integration/test_carma.py +227 -0
  50. musica/test/integration/test_carma_aluminum.py +12 -0
  51. musica/test/integration/test_carma_sulfate.py +17 -0
  52. musica/test/integration/test_chapman.py +139 -0
  53. musica/test/integration/test_sulfate_box_model.py +34 -0
  54. musica/test/integration/test_tuvx.py +62 -0
  55. musica/test/unit/test_parser.py +64 -0
  56. musica/test/unit/test_serializer.py +69 -0
  57. musica/test/unit/test_state.py +325 -0
  58. musica/test/unit/test_util_full_mechanism.py +698 -0
  59. musica/tools/prepare_build_environment_linux.sh +32 -0
  60. musica/tools/prepare_build_environment_macos.sh +1 -0
  61. musica/tools/repair_wheel_gpu.sh +40 -0
  62. musica/tuvx.cpp +93 -0
  63. musica/tuvx.py +199 -0
  64. musica/types.py +407 -0
  65. musica-0.12.2.dist-info/METADATA +473 -0
  66. musica-0.12.2.dist-info/RECORD +70 -0
  67. musica-0.12.2.dist-info/WHEEL +5 -0
  68. musica-0.12.2.dist-info/entry_points.txt +3 -0
  69. musica-0.12.2.dist-info/licenses/AUTHORS.md +59 -0
  70. 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()