musica 0.12.1__cp39-cp39-win32.whl → 0.12.2__cp39-cp39-win32.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/_musica.cp39-win32.pyd +0 -0
- musica/_version.py +1 -1
- musica/examples/__init__.py +1 -1
- musica/examples/carma_aluminum.py +1 -0
- musica/examples/carma_sulfate.py +1 -0
- musica/examples/sulfate_box_model.py +2 -2
- musica/examples/ts1_latin_hypercube.py +1 -1
- musica/test/integration/test_carma_aluminum.py +2 -1
- musica/test/integration/test_carma_sulfate.py +2 -1
- musica/test/integration/test_sulfate_box_model.py +1 -1
- musica/test/unit/test_state.py +325 -0
- musica/tools/prepare_build_environment_linux.sh +7 -25
- musica/types.py +17 -14
- {musica-0.12.1.dist-info → musica-0.12.2.dist-info}/METADATA +2 -1
- {musica-0.12.1.dist-info → musica-0.12.2.dist-info}/RECORD +19 -18
- {musica-0.12.1.dist-info → musica-0.12.2.dist-info}/WHEEL +1 -1
- {musica-0.12.1.dist-info → musica-0.12.2.dist-info}/entry_points.txt +0 -0
- {musica-0.12.1.dist-info → musica-0.12.2.dist-info}/licenses/AUTHORS.md +0 -0
- {musica-0.12.1.dist-info → musica-0.12.2.dist-info}/licenses/LICENSE +0 -0
musica/_musica.cp39-win32.pyd
CHANGED
|
Binary file
|
musica/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
version = "0.12.
|
|
1
|
+
version = "0.12.2"
|
musica/examples/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
from .examples import Examples
|
|
1
|
+
from .examples import Examples
|
musica/examples/carma_sulfate.py
CHANGED
|
@@ -272,8 +272,8 @@ def run_box_model():
|
|
|
272
272
|
state.set_concentrations(initial_concentrations)
|
|
273
273
|
state.set_user_defined_rate_parameters({"EMIS.SO2": np.full(NUMBER_OF_GRID_CELLS, 1.0e-8, dtype=np.float64)})
|
|
274
274
|
|
|
275
|
-
# Run the simulation for
|
|
276
|
-
time_hours =
|
|
275
|
+
# Run the simulation for 30 minutes with a timestep of 30 seconds
|
|
276
|
+
time_hours = 0.5
|
|
277
277
|
time_seconds = time_hours * np.float64(3600.0)
|
|
278
278
|
dt = np.float64(30.0)
|
|
279
279
|
num_steps = int(time_seconds / dt)
|
|
@@ -5,7 +5,8 @@ available = musica.backend.carma_available()
|
|
|
5
5
|
pytestmark = pytest.mark.skipif(
|
|
6
6
|
not available, reason="CARMA backend is not available")
|
|
7
7
|
|
|
8
|
+
|
|
8
9
|
def test_carma_aluminum():
|
|
9
10
|
from musica.examples import carma_aluminum
|
|
10
11
|
state = carma_aluminum.run_carma_aluminum_example()
|
|
11
|
-
assert state is not None, "State should not be None"
|
|
12
|
+
assert state is not None, "State should not be None"
|
|
@@ -5,6 +5,7 @@ available = musica.backend.carma_available()
|
|
|
5
5
|
pytestmark = pytest.mark.skipif(
|
|
6
6
|
not available, reason="CARMA backend is not available")
|
|
7
7
|
|
|
8
|
+
|
|
8
9
|
def test_carma_sulfate():
|
|
9
10
|
from musica.examples import carma_sulfate
|
|
10
11
|
env_state, gas_state, bin_state = carma_sulfate.run_carma_sulfate_example()
|
|
@@ -13,4 +14,4 @@ def test_carma_sulfate():
|
|
|
13
14
|
assert gas_state is not None, "Gas state should not be None"
|
|
14
15
|
assert bin_state is not None, "Bin state should not be None"
|
|
15
16
|
# Optionally, check expected dimensions or variables
|
|
16
|
-
assert hasattr(bin_state, "mass_mixing_ratio"), "Bin state should have mass_mixing_ratio"
|
|
17
|
+
assert hasattr(bin_state, "mass_mixing_ratio"), "Bin state should have mass_mixing_ratio"
|
|
@@ -5,6 +5,7 @@ available = musica.backend.carma_available()
|
|
|
5
5
|
pytestmark = pytest.mark.skipif(
|
|
6
6
|
not available, reason="CARMA backend is not available")
|
|
7
7
|
|
|
8
|
+
|
|
8
9
|
def test_sulfate_box_model():
|
|
9
10
|
"""Test the sulfate box model implementation."""
|
|
10
11
|
from musica.examples import sulfate_box_model
|
|
@@ -31,4 +32,3 @@ def test_sulfate_box_model():
|
|
|
31
32
|
print(f" Chemical species tracked: {list(concentrations.columns)}")
|
|
32
33
|
print(f" CARMA bins: {len(sulfate_data.bin)}")
|
|
33
34
|
print(f" Vertical levels: {len(sulfate_data.vertical_center)}")
|
|
34
|
-
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
"""Tests for the State class."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
import pytest # type: ignore # pylint: disable=import-error
|
|
4
|
+
import numpy as np # type: ignore # pylint: disable=import-error
|
|
5
|
+
from musica.types import State, MICM
|
|
6
|
+
import musica.mechanism_configuration as mc
|
|
7
|
+
from musica.mechanism_configuration import Mechanism
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def create_test_mechanism() -> Mechanism:
|
|
11
|
+
"""Helper function to create a test mechanism."""
|
|
12
|
+
# Chemical species
|
|
13
|
+
A = mc.Species(
|
|
14
|
+
name="A",
|
|
15
|
+
diffusion_coefficient_m2_s=20.3,
|
|
16
|
+
molecular_weight_kg_mol=13.2,
|
|
17
|
+
other_properties={
|
|
18
|
+
"__absolute tolerance": "1.0e-30"})
|
|
19
|
+
B = mc.Species(name="B")
|
|
20
|
+
C = mc.Species(name="C")
|
|
21
|
+
M = mc.Species(name="M", is_third_body=True)
|
|
22
|
+
|
|
23
|
+
# Chemical phases
|
|
24
|
+
gas = mc.Phase(name="gas", species=[A, B, C, M])
|
|
25
|
+
|
|
26
|
+
# Reactions
|
|
27
|
+
my_arrhenius = mc.Arrhenius(
|
|
28
|
+
name="my arrhenius",
|
|
29
|
+
A=32.1, B=-2.3, C=102.3, D=63.4, E=-1.3,
|
|
30
|
+
gas_phase=gas,
|
|
31
|
+
reactants=[B],
|
|
32
|
+
products=[C],
|
|
33
|
+
other_properties={"__irrelevant": "2"},
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
my_other_arrhenius = mc.Arrhenius(
|
|
37
|
+
name="my other arrhenius",
|
|
38
|
+
A=29.3, B=-1.5, Ea=101.2, D=82.6, E=-0.98,
|
|
39
|
+
gas_phase=gas,
|
|
40
|
+
reactants=[A],
|
|
41
|
+
products=[(1.2, B)]
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
my_troe = mc.Troe(
|
|
45
|
+
name="my troe",
|
|
46
|
+
gas_phase=gas,
|
|
47
|
+
k0_A=1.2e-12,
|
|
48
|
+
k0_B=167,
|
|
49
|
+
k0_C=3,
|
|
50
|
+
kinf_A=136,
|
|
51
|
+
kinf_B=5,
|
|
52
|
+
kinf_C=24,
|
|
53
|
+
Fc=0.9,
|
|
54
|
+
N=0.8,
|
|
55
|
+
reactants=[B, A],
|
|
56
|
+
products=[C],
|
|
57
|
+
other_properties={"__irrelevant": "2"},
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
my_ternary = mc.TernaryChemicalActivation(
|
|
61
|
+
name="my ternary chemical activation",
|
|
62
|
+
gas_phase=gas,
|
|
63
|
+
k0_A=32.1,
|
|
64
|
+
k0_B=-2.3,
|
|
65
|
+
k0_C=102.3,
|
|
66
|
+
kinf_A=63.4,
|
|
67
|
+
kinf_B=-1.3,
|
|
68
|
+
kinf_C=908.5,
|
|
69
|
+
Fc=1.3,
|
|
70
|
+
N=32.1,
|
|
71
|
+
reactants=[B, A],
|
|
72
|
+
products=[C],
|
|
73
|
+
other_properties={"__irrelevant": "2"},
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
my_branched = mc.Branched(
|
|
77
|
+
name="my branched",
|
|
78
|
+
gas_phase=gas,
|
|
79
|
+
reactants=[A],
|
|
80
|
+
alkoxy_products=[B],
|
|
81
|
+
nitrate_products=[C],
|
|
82
|
+
X=1.2e-4,
|
|
83
|
+
Y=167,
|
|
84
|
+
a0=0.15,
|
|
85
|
+
n=9,
|
|
86
|
+
other_properties={"__irrelevant": "2"},
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
my_tunneling = mc.Tunneling(
|
|
90
|
+
name="my tunneling",
|
|
91
|
+
gas_phase=gas,
|
|
92
|
+
reactants=[B],
|
|
93
|
+
products=[C],
|
|
94
|
+
A=123.45,
|
|
95
|
+
B=1200.0,
|
|
96
|
+
C=1.0e8,
|
|
97
|
+
other_properties={"__irrelevant": "2"},
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
my_surface = mc.Surface(
|
|
101
|
+
name="my surface",
|
|
102
|
+
gas_phase=gas,
|
|
103
|
+
gas_phase_species=A,
|
|
104
|
+
reaction_probability=2.0e-2,
|
|
105
|
+
gas_phase_products=[B, C],
|
|
106
|
+
other_properties={"__irrelevant": "2"},
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
photo_b = mc.Photolysis(
|
|
110
|
+
name="photo B",
|
|
111
|
+
gas_phase=gas,
|
|
112
|
+
reactants=[B],
|
|
113
|
+
products=[C],
|
|
114
|
+
scaling_factor=12.3,
|
|
115
|
+
other_properties={"__irrelevant": "2"},
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
my_emission = mc.Emission(
|
|
119
|
+
name="my emission",
|
|
120
|
+
gas_phase=gas,
|
|
121
|
+
products=[B],
|
|
122
|
+
scaling_factor=12.3,
|
|
123
|
+
other_properties={"__irrelevant": "2"},
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
my_first_order_loss = mc.FirstOrderLoss(
|
|
127
|
+
name="my first order loss",
|
|
128
|
+
gas_phase=gas,
|
|
129
|
+
reactants=[C],
|
|
130
|
+
scaling_factor=12.3,
|
|
131
|
+
other_properties={"__irrelevant": "2"},
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
user_defined = mc.UserDefined(
|
|
135
|
+
name="my user defined",
|
|
136
|
+
gas_phase=gas,
|
|
137
|
+
reactants=[A, B],
|
|
138
|
+
products=[(1.3, C)],
|
|
139
|
+
scaling_factor=12.3,
|
|
140
|
+
other_properties={"__irrelevant": "2"}
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# Mechanism
|
|
144
|
+
return mc.Mechanism(
|
|
145
|
+
name="Full Configuration",
|
|
146
|
+
species=[A, B, C, M],
|
|
147
|
+
phases=[gas],
|
|
148
|
+
reactions=[my_arrhenius, my_other_arrhenius, my_troe, my_ternary,
|
|
149
|
+
my_branched, my_tunneling, my_surface, photo_b,
|
|
150
|
+
my_emission, my_first_order_loss, user_defined],
|
|
151
|
+
version=mc.Version(1, 0, 0),
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def get_test_solver(mech: Mechanism) -> MICM:
|
|
156
|
+
"""Helper function to create a test solver."""
|
|
157
|
+
return MICM(mechanism=mech)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def test_state_initialization():
|
|
161
|
+
"""Test State initialization with various grid cell configurations."""
|
|
162
|
+
# Use the test mechanism
|
|
163
|
+
mech = create_test_mechanism()
|
|
164
|
+
|
|
165
|
+
# Create MICM instance
|
|
166
|
+
solver = get_test_solver(mech)
|
|
167
|
+
|
|
168
|
+
# Test with valid input
|
|
169
|
+
state = solver.create_state(number_of_grid_cells=1)
|
|
170
|
+
assert isinstance(state, State)
|
|
171
|
+
|
|
172
|
+
# Test with multiple grid cells
|
|
173
|
+
state_multi = solver.create_state(number_of_grid_cells=3)
|
|
174
|
+
assert isinstance(state_multi, State)
|
|
175
|
+
|
|
176
|
+
# Test with invalid input
|
|
177
|
+
with pytest.raises(ValueError, match="number_of_grid_cells must be greater than 0"):
|
|
178
|
+
solver.create_state(number_of_grid_cells=0)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def test_set_get_concentrations():
|
|
182
|
+
"""Test setting and getting concentrations."""
|
|
183
|
+
# Use the test mechanism
|
|
184
|
+
mech = create_test_mechanism()
|
|
185
|
+
solver = get_test_solver(mech)
|
|
186
|
+
|
|
187
|
+
# Test single grid cell
|
|
188
|
+
state = solver.create_state(number_of_grid_cells=1)
|
|
189
|
+
concentrations = {"A": 1.0, "B": 2.0, "C": 3.0}
|
|
190
|
+
state.set_concentrations(concentrations)
|
|
191
|
+
result = state.get_concentrations()
|
|
192
|
+
assert result["A"][0] == 1.0
|
|
193
|
+
assert result["B"][0] == 2.0
|
|
194
|
+
assert result["C"][0] == 3.0
|
|
195
|
+
|
|
196
|
+
# Test multiple grid cells
|
|
197
|
+
state_multi = solver.create_state(number_of_grid_cells=2)
|
|
198
|
+
concentrations_multi = {"A": [1.0, 2.0], "B": [3.0, 4.0], "C": [5.0, 6.0]}
|
|
199
|
+
state_multi.set_concentrations(concentrations_multi)
|
|
200
|
+
result_multi = state_multi.get_concentrations()
|
|
201
|
+
assert result_multi["A"] == [1.0, 2.0]
|
|
202
|
+
assert result_multi["B"] == [3.0, 4.0]
|
|
203
|
+
assert result_multi["C"] == [5.0, 6.0]
|
|
204
|
+
|
|
205
|
+
# Test invalid species
|
|
206
|
+
with pytest.raises(ValueError, match="Species D not found in the mechanism"):
|
|
207
|
+
state.set_concentrations({"D": 1.0})
|
|
208
|
+
|
|
209
|
+
# Test invalid length
|
|
210
|
+
with pytest.raises(ValueError, match="must have length"):
|
|
211
|
+
state_multi.set_concentrations({"A": [1.0]})
|
|
212
|
+
|
|
213
|
+
# Test cannot set third-body species
|
|
214
|
+
with pytest.raises(ValueError, match="Species M not found in the mechanism"):
|
|
215
|
+
state.set_concentrations({"M": 1.0})
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def test_set_get_conditions():
|
|
219
|
+
"""Test setting and getting environmental conditions."""
|
|
220
|
+
# Use the test mechanism
|
|
221
|
+
mech = create_test_mechanism()
|
|
222
|
+
solver = get_test_solver(mech)
|
|
223
|
+
|
|
224
|
+
# Test single grid cell
|
|
225
|
+
state = solver.create_state(number_of_grid_cells=1)
|
|
226
|
+
state.set_conditions(temperatures=300.0, pressures=101325.0)
|
|
227
|
+
conditions = state.get_conditions()
|
|
228
|
+
assert conditions["temperature"][0] == 300.0
|
|
229
|
+
assert conditions["pressure"][0] == 101325.0
|
|
230
|
+
assert np.isclose(conditions["air_density"][0], 40.9, rtol=0.1) # Approximate value from ideal gas law
|
|
231
|
+
|
|
232
|
+
# Test multiple grid cells
|
|
233
|
+
state_multi = solver.create_state(number_of_grid_cells=2)
|
|
234
|
+
state_multi.set_conditions(
|
|
235
|
+
temperatures=[300.0, 310.0],
|
|
236
|
+
pressures=[101325.0, 101325.0],
|
|
237
|
+
air_densities=[40.9, 39.5]
|
|
238
|
+
)
|
|
239
|
+
conditions_multi = state_multi.get_conditions()
|
|
240
|
+
assert conditions_multi["temperature"] == [300.0, 310.0]
|
|
241
|
+
assert conditions_multi["pressure"] == [101325.0, 101325.0]
|
|
242
|
+
assert conditions_multi["air_density"] == [40.9, 39.5]
|
|
243
|
+
|
|
244
|
+
# Test invalid input length
|
|
245
|
+
with pytest.raises(ValueError, match="must be a list of length"):
|
|
246
|
+
state_multi.set_conditions(temperatures=[300.0])
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def test_set_get_user_defined_rate_parameters():
|
|
250
|
+
"""Test setting and getting user-defined rate parameters."""
|
|
251
|
+
# Use the test mechanism which includes a user-defined reaction
|
|
252
|
+
mech = create_test_mechanism()
|
|
253
|
+
solver = get_test_solver(mech)
|
|
254
|
+
|
|
255
|
+
# Test single grid cell
|
|
256
|
+
state = solver.create_state(number_of_grid_cells=1)
|
|
257
|
+
params = {"EMIS.my emission": 1.0}
|
|
258
|
+
state.set_user_defined_rate_parameters(params)
|
|
259
|
+
result = state.get_user_defined_rate_parameters()
|
|
260
|
+
assert result["EMIS.my emission"][0] == 1.0
|
|
261
|
+
|
|
262
|
+
# Test multiple grid cells
|
|
263
|
+
state_multi = solver.create_state(number_of_grid_cells=2)
|
|
264
|
+
params_multi = {"PHOTO.photo B": [1.0, 2.0]}
|
|
265
|
+
state_multi.set_user_defined_rate_parameters(params_multi)
|
|
266
|
+
result_multi = state_multi.get_user_defined_rate_parameters()
|
|
267
|
+
assert result_multi["PHOTO.photo B"] == [1.0, 2.0]
|
|
268
|
+
|
|
269
|
+
# Test invalid parameter
|
|
270
|
+
with pytest.raises(ValueError, match="User-defined rate parameter invalid_param not found"):
|
|
271
|
+
state.set_user_defined_rate_parameters({"invalid_param": 1.0})
|
|
272
|
+
|
|
273
|
+
solver = get_test_solver(mech)
|
|
274
|
+
|
|
275
|
+
state = solver.create_state(number_of_grid_cells=1)
|
|
276
|
+
|
|
277
|
+
# Test species ordering
|
|
278
|
+
species_ordering = state.get_species_ordering()
|
|
279
|
+
assert isinstance(species_ordering, dict)
|
|
280
|
+
assert len(species_ordering) == 3 # A, B, C (M is third-body and not included)
|
|
281
|
+
|
|
282
|
+
# Dictionary style access
|
|
283
|
+
assert species_ordering["A"] >= 0
|
|
284
|
+
assert species_ordering["B"] >= 0
|
|
285
|
+
assert species_ordering["C"] >= 0
|
|
286
|
+
|
|
287
|
+
# Using get() method with default value
|
|
288
|
+
assert species_ordering.get("A", -1) >= 0 # returns value if key exists
|
|
289
|
+
assert species_ordering.get("Z", -1) == -1 # returns -1 since Z doesn't exist
|
|
290
|
+
|
|
291
|
+
# Test key membership
|
|
292
|
+
assert "A" in species_ordering
|
|
293
|
+
assert "B" in species_ordering
|
|
294
|
+
assert "C" in species_ordering
|
|
295
|
+
assert "M" not in species_ordering # third-body not included
|
|
296
|
+
|
|
297
|
+
# Test parameter ordering
|
|
298
|
+
param_ordering = state.get_user_defined_rate_parameters_ordering()
|
|
299
|
+
assert isinstance(param_ordering, dict)
|
|
300
|
+
assert len(param_ordering) == 6
|
|
301
|
+
|
|
302
|
+
# Convert dict keys to list using list() function
|
|
303
|
+
param_names = list(param_ordering.keys())
|
|
304
|
+
assert len(param_names) == 6
|
|
305
|
+
assert isinstance(param_names[0], str)
|
|
306
|
+
|
|
307
|
+
# Alternative way using list comprehension
|
|
308
|
+
param_names_alt = [key for key in param_ordering]
|
|
309
|
+
assert param_names_alt == param_names
|
|
310
|
+
|
|
311
|
+
# Sort the keys if needed - useful for consistent ordering in tests
|
|
312
|
+
sorted_param_names = sorted(param_ordering.keys())
|
|
313
|
+
assert len(sorted_param_names) == 6
|
|
314
|
+
assert all(isinstance(name, str) for name in sorted_param_names)
|
|
315
|
+
|
|
316
|
+
# Verify all expected keys are present
|
|
317
|
+
expected_params = [
|
|
318
|
+
"PHOTO.photo B",
|
|
319
|
+
"EMIS.my emission",
|
|
320
|
+
"LOSS.my first order loss",
|
|
321
|
+
"SURF.my surface.effective radius [m]",
|
|
322
|
+
"SURF.my surface.particle number concentration [# m-3]",
|
|
323
|
+
"USER.my user defined"
|
|
324
|
+
]
|
|
325
|
+
assert sorted(expected_params) == sorted(param_names)
|
|
@@ -5,32 +5,17 @@ set -x
|
|
|
5
5
|
target_arch="$(uname -m)"
|
|
6
6
|
echo "Detected target_arch: $target_arch"
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
# x86_64 and aarch64 use manylinux_2_28 (AlmaLinux 8) with dnf
|
|
10
|
-
# i686 uses manylinux2014 (CentOS 7) with yum
|
|
11
|
-
if [ "$target_arch" = "i686" ]; then
|
|
12
|
-
PKG_MGR="yum"
|
|
13
|
-
|
|
14
|
-
# CentOS 7 is EOL, so we need to use vault.centos.org for i686 builds
|
|
15
|
-
# Replace the repo files to point to vault.centos.org
|
|
16
|
-
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*.repo
|
|
17
|
-
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*.repo
|
|
18
|
-
else
|
|
19
|
-
PKG_MGR="dnf"
|
|
20
|
-
fi
|
|
21
|
-
|
|
22
|
-
echo "Using package manager: $PKG_MGR"
|
|
23
|
-
|
|
24
|
-
$PKG_MGR -y update
|
|
8
|
+
dnf -y update
|
|
25
9
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
10
|
+
# For 64 bit systems can enable our fortran components, but we require netcdf
|
|
11
|
+
if [[ "$target_arch" == "x86_64" || "$target_arch" == "aarch64" ]]; then
|
|
12
|
+
dnf install -y epel-release
|
|
13
|
+
dnf install -y netcdf-devel netcdf-fortran-devel
|
|
30
14
|
fi
|
|
31
15
|
|
|
32
|
-
|
|
16
|
+
dnf install -y tree wget zip lapack-devel
|
|
33
17
|
|
|
18
|
+
# 64 bit intel and amd systems support building cuda
|
|
34
19
|
if [ "$target_arch" = "x86_64" ]; then
|
|
35
20
|
# Install CUDA 12.8 for x86_64 on AlmaLinux 8 (manylinux_2_28) - supports GCC 14
|
|
36
21
|
dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel8/x86_64/cuda-rhel8.repo
|
|
@@ -44,7 +29,4 @@ if [ "$target_arch" = "x86_64" ]; then
|
|
|
44
29
|
# Verify CUDA installation
|
|
45
30
|
echo "=== CUDA Installation Verification ==="
|
|
46
31
|
/usr/local/cuda/bin/nvcc --version
|
|
47
|
-
|
|
48
|
-
# list the installed CUDA packages
|
|
49
|
-
# tree -L 4 /usr/local/cuda
|
|
50
32
|
fi
|
musica/types.py
CHANGED
|
@@ -165,30 +165,31 @@ class State():
|
|
|
165
165
|
k += 1
|
|
166
166
|
|
|
167
167
|
def set_conditions(self,
|
|
168
|
-
temperatures: Union[Union[float, int], List[Union[float, int]]],
|
|
169
|
-
pressures: Union[Union[float, int], List[Union[float, int]]],
|
|
168
|
+
temperatures: Optional[Union[Union[float, int], List[Union[float, int]]]] = None,
|
|
169
|
+
pressures: Optional[Union[Union[float, int], List[Union[float, int]]]] = None,
|
|
170
170
|
air_densities: Optional[Union[Union[float, int], List[Union[float, int]]]] = None):
|
|
171
171
|
"""
|
|
172
172
|
Set the conditions for the state. The individual conditions can be a single value
|
|
173
173
|
when solving for a single grid cell, or a list of values when solving for multiple grid cells.
|
|
174
174
|
If air density is not provided, it will be calculated from the Ideal Gas Law using the provided
|
|
175
|
-
temperature and pressure.
|
|
175
|
+
temperature and pressure. If temperature or pressure are not provided, their values will remain
|
|
176
|
+
unchanged.
|
|
176
177
|
|
|
177
178
|
Parameters
|
|
178
179
|
----------
|
|
179
|
-
temperatures : Union[float, List[float]]
|
|
180
|
+
temperatures : Optional[Union[float, List[float]]]
|
|
180
181
|
Temperature in Kelvin.
|
|
181
|
-
pressures : Union[float, List[float]]
|
|
182
|
+
pressures : Optional[Union[float, List[float]]]
|
|
182
183
|
Pressure in Pascals.
|
|
183
184
|
air_densities : Optional[Union[float, List[float]]]
|
|
184
185
|
Air density in mol m-3. If not provided, it will be calculated from the Ideal Gas Law.
|
|
185
186
|
"""
|
|
186
|
-
if isinstance(temperatures, float) or isinstance(temperatures, int):
|
|
187
|
+
if temperatures is not None and (isinstance(temperatures, float) or isinstance(temperatures, int)):
|
|
187
188
|
if self.__number_of_grid_cells > 1:
|
|
188
189
|
raise ValueError(
|
|
189
190
|
f"temperatures must be a list of length {self.__number_of_grid_cells}.")
|
|
190
191
|
temperatures = [temperatures]
|
|
191
|
-
if isinstance(pressures, float) or isinstance(pressures, int):
|
|
192
|
+
if pressures is not None and (isinstance(pressures, float) or isinstance(pressures, int)):
|
|
192
193
|
if self.__number_of_grid_cells > 1:
|
|
193
194
|
raise ValueError(
|
|
194
195
|
f"pressures must be a list of length {self.__number_of_grid_cells}.")
|
|
@@ -198,10 +199,10 @@ class State():
|
|
|
198
199
|
raise ValueError(
|
|
199
200
|
f"air_densities must be a list of length {self.__number_of_grid_cells}.")
|
|
200
201
|
air_densities = [air_densities]
|
|
201
|
-
if len(temperatures) != self.__number_of_grid_cells:
|
|
202
|
+
if temperatures is not None and len(temperatures) != self.__number_of_grid_cells:
|
|
202
203
|
raise ValueError(
|
|
203
204
|
f"temperatures must be a list of length {self.__number_of_grid_cells}.")
|
|
204
|
-
if len(pressures) != self.__number_of_grid_cells:
|
|
205
|
+
if pressures is not None and len(pressures) != self.__number_of_grid_cells:
|
|
205
206
|
raise ValueError(
|
|
206
207
|
f"pressures must be a list of length {self.__number_of_grid_cells}.")
|
|
207
208
|
if air_densities is not None and len(air_densities) != self.__number_of_grid_cells:
|
|
@@ -210,10 +211,10 @@ class State():
|
|
|
210
211
|
k = 0
|
|
211
212
|
for state in self.__states:
|
|
212
213
|
for condition in state.conditions:
|
|
213
|
-
condition.temperature = temperatures[k]
|
|
214
|
-
condition.pressure = pressures[k]
|
|
215
|
-
condition.air_density = air_densities[k] if air_densities is not None else
|
|
216
|
-
GAS_CONSTANT *
|
|
214
|
+
condition.temperature = temperatures[k] if temperatures is not None else condition.temperature
|
|
215
|
+
condition.pressure = pressures[k] if pressures is not None else condition.pressure
|
|
216
|
+
condition.air_density = air_densities[k] if air_densities is not None else condition.pressure / (
|
|
217
|
+
GAS_CONSTANT * condition.temperature)
|
|
217
218
|
k += 1
|
|
218
219
|
|
|
219
220
|
def get_concentrations(self) -> Dict[str, List[float]]:
|
|
@@ -334,11 +335,13 @@ class MICM():
|
|
|
334
335
|
Mechanism object which specifies the chemical mechanism to use. If provided, this will be used
|
|
335
336
|
to create the solver.
|
|
336
337
|
solver_type : SolverType, optional
|
|
337
|
-
Type of solver to use. If not provided, the default solver type will be used.
|
|
338
|
+
Type of solver to use. If not provided, the default Rosenbrock (with standard-ordered matrices) solver type will be used.
|
|
338
339
|
ignore_non_gas_phases : bool, optional
|
|
339
340
|
If True, non-gas phases will be ignored when configuring micm with the mechanism. This is only needed
|
|
340
341
|
until micm properly supports non-gas phases. This option is only supported when passing in a mechanism.
|
|
341
342
|
"""
|
|
343
|
+
if solver_type is None:
|
|
344
|
+
solver_type = SolverType.rosenbrock_standard_order
|
|
342
345
|
self.__solver_type = solver_type
|
|
343
346
|
self.__vector_size = _vector_size(solver_type)
|
|
344
347
|
if config_path is None and mechanism is None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: musica
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.2
|
|
4
4
|
Summary: MUSICA is a Python library for performing computational simulations in atmospheric chemistry.
|
|
5
5
|
Author-Email: Matthew Dawsom <mattdawson@ucar.edu>, Jiwon Gim <jiwongim@ucar.edu>, David Fillmore <fillmore@ucar.edu>, Kyle Shores <kshores@ucar.edu>, Montek Thind <mthind@ucar.edu>
|
|
6
6
|
Maintainer-Email: ACOM MUSICA Developers <musica-support@ucar.edu>
|
|
@@ -207,6 +207,7 @@ License: Apache License
|
|
|
207
207
|
limitations under the License.
|
|
208
208
|
|
|
209
209
|
Project-URL: homepage, https://wiki.ucar.edu/display/MUSICA/MUSICA+Home
|
|
210
|
+
Requires-Python: >=3.9
|
|
210
211
|
Requires-Dist: pyyaml>=6.0.2
|
|
211
212
|
Requires-Dist: xarray>=2022.3.0
|
|
212
213
|
Requires-Dist: ussa1976>=v0.3.4
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
musica/__init__.py,sha256=pSZ-H2IJ4EEYIbQDygjGwjhGySXdeifB1DzQBMJzz2g,403
|
|
2
|
-
musica/_musica.cp39-win32.pyd,sha256=
|
|
3
|
-
musica/_version.py,sha256=
|
|
2
|
+
musica/_musica.cp39-win32.pyd,sha256=AJPc20jqwp6lXjlvcSp5gLDHg7_1ruFciSbhU1Q54Mk,1418240
|
|
3
|
+
musica/_version.py,sha256=4bzF9LMIExRVigCODQ4A-chBc4NdBm0Fk_FjBxMRo9Q,20
|
|
4
4
|
musica/backend.py,sha256=Fw3-HECqsifQmvRonDTGeEZqS-KXYD09BCwBue_HwfM,1081
|
|
5
5
|
musica/binding_common.cpp,sha256=qrJCfdePt-ZoIgCTrPJqSUF1Ie8Mq7b7S2_pEdpi4CE,1013
|
|
6
6
|
musica/binding_common.hpp,sha256=YAcb9WnfXL7Ps-rR-iMBSwUgBQZfZZdCQQod5CTMEZA,108
|
|
@@ -11,12 +11,12 @@ musica/constants.py,sha256=sQqh1UVu2HRvl25qWPW0ACT8NrHe_r4Ugy-v_BiTGG4,126
|
|
|
11
11
|
musica/cpu_binding.cpp,sha256=Cy06zLErMV0g7Ol9Fg-q2cpG-g5fb8hcBl-M-ihHLyk,236
|
|
12
12
|
musica/cuda.cpp,sha256=oTG2ZnL-SiW2kx9eL4XJOQGJeIiGuy8tJ5BEoLRWL4M,358
|
|
13
13
|
musica/cuda.py,sha256=ClHKnSNiU8SX0BANh5KybismYHH6mFUyC-3r8S9qARo,271
|
|
14
|
-
musica/examples/__init__.py,sha256=
|
|
15
|
-
musica/examples/carma_aluminum.py,sha256=
|
|
16
|
-
musica/examples/carma_sulfate.py,sha256=
|
|
14
|
+
musica/examples/__init__.py,sha256=hR0kZhoHfL9dcup7gg64HDJyIyAQqHAsip8LpuRNnI8,32
|
|
15
|
+
musica/examples/carma_aluminum.py,sha256=Q2IRvU9jxuKAUZvhQkTawVfZV0UADiMvXP-R6uzjemo,3808
|
|
16
|
+
musica/examples/carma_sulfate.py,sha256=MbV1oBrB6rc7yWMxbnYVr_SHlTMqd6uV21kwVhlUymY,8365
|
|
17
17
|
musica/examples/examples.py,sha256=xWnFSNMYPpUhz04YtSSNsr6DoxmQoOdUtTT9GSUm3ps,5901
|
|
18
|
-
musica/examples/sulfate_box_model.py,sha256=
|
|
19
|
-
musica/examples/ts1_latin_hypercube.py,sha256=
|
|
18
|
+
musica/examples/sulfate_box_model.py,sha256=LU1kJYtCZNV_4Mi8kJl2V7YQwQuP1dv8Ba4-2vhPFbE,17110
|
|
19
|
+
musica/examples/ts1_latin_hypercube.py,sha256=tLH9swPT4pvDnd7a86-xnt8PqXl4Y7bAXowsA0J7PV8,9868
|
|
20
20
|
musica/gpu_binding.cpp,sha256=X0qISrKYz7Ldjn5UnqNw8oLzOY4VgyF3fUUszm-QSJI,240
|
|
21
21
|
musica/main.py,sha256=gVCfeh44VL4EH7eFRR2wU_I_kANB94furojDi-0LhoE,2797
|
|
22
22
|
musica/mechanism_configuration/__init__.py,sha256=odlwrCvBBnqUBi951RysExLDYqK_AfqP4nRY90MQpcc,40
|
|
@@ -47,23 +47,24 @@ musica/test/examples/v1/full_configuration/full_configuration.json,sha256=zBC3EV
|
|
|
47
47
|
musica/test/examples/v1/full_configuration/full_configuration.yaml,sha256=XY6TW78rus0DyrI70NR3yvTeUIPff8_I9ErOXy2m3KE,5911
|
|
48
48
|
musica/test/integration/test_analytical.py,sha256=eOPb3DtjQEodTZCpjelw1LQZM_VyhFi2TOlx1bmEtkk,14129
|
|
49
49
|
musica/test/integration/test_carma.py,sha256=itPJNxSRp7FHJokYSicZFgqzBBrZ9dr1TDxawDPT9BM,7092
|
|
50
|
-
musica/test/integration/test_carma_aluminum.py,sha256=
|
|
51
|
-
musica/test/integration/test_carma_sulfate.py,sha256
|
|
50
|
+
musica/test/integration/test_carma_aluminum.py,sha256=F7_8xwZnKjSxgnZKdZR1tDwzwfVUiD7ZT1b_9cseE3M,368
|
|
51
|
+
musica/test/integration/test_carma_sulfate.py,sha256=OWQDLQNao5vU2FAMpWDVqs8xrFhpxvRfhx8HrP6GTCs,759
|
|
52
52
|
musica/test/integration/test_chapman.py,sha256=t6p0CadUy-B4OP7A-EZ9Wz52diuYs5yc9LKiFUS9T6A,3651
|
|
53
|
-
musica/test/integration/test_sulfate_box_model.py,sha256=
|
|
53
|
+
musica/test/integration/test_sulfate_box_model.py,sha256=umqG0PAaCu27J3s5W_cnWJt9T_9EFox9z_JMHKNz5GI,1638
|
|
54
54
|
musica/test/integration/test_tuvx.py,sha256=6MU5RrbNpX_I5VHTDUTreCGdL9c9y3voy68QurVazNI,1980
|
|
55
55
|
musica/test/unit/test_parser.py,sha256=PF7GPddM4-Mbz0qjzqRvl_YSISj-VQR49MGXLfe8dDg,2667
|
|
56
56
|
musica/test/unit/test_serializer.py,sha256=y6u_e2uJm9TGpn7B3x8_LobVGxIFyuKzF-WrIfP1Ewo,2527
|
|
57
|
+
musica/test/unit/test_state.py,sha256=he0cEVOS7fnWRP7cOzift5abSAwEWUC-eQ6V5deTgdM,10694
|
|
57
58
|
musica/test/unit/test_util_full_mechanism.py,sha256=O7nJjpIt1k-pxUNj4zBiLdSXruyhj8qfbp8Me75kPJg,25915
|
|
58
|
-
musica/tools/prepare_build_environment_linux.sh,sha256=
|
|
59
|
+
musica/tools/prepare_build_environment_linux.sh,sha256=i69LuyY25KE-jFIFNuYC4_33_DGTngentBvt2Tbed9g,1017
|
|
59
60
|
musica/tools/prepare_build_environment_macos.sh,sha256=Yhhd-8W6YvR79NabEqixexU6BsClNf7DH_EYYlsmeMo,41
|
|
60
61
|
musica/tools/repair_wheel_gpu.sh,sha256=nQueyGNC2qWcBAicjVdAfB6JH4m_51dFOG83vVxke54,1525
|
|
61
62
|
musica/tuvx.cpp,sha256=vvRi7T8TLZ-U8H7R-jrWIEmHBexXlms-0abhPGibnC8,3108
|
|
62
63
|
musica/tuvx.py,sha256=6EDOULrBc2cojLgK-lNKH68YVHQyOFpBC-jkGYuaraY,6587
|
|
63
|
-
musica/types.py,sha256=
|
|
64
|
-
musica-0.12.
|
|
65
|
-
musica-0.12.
|
|
66
|
-
musica-0.12.
|
|
67
|
-
musica-0.12.
|
|
68
|
-
musica-0.12.
|
|
69
|
-
musica-0.12.
|
|
64
|
+
musica/types.py,sha256=zTqzaflhrwQqVMtwN_5eNxkvMis_QWAo3XwcNSpWEqs,17544
|
|
65
|
+
musica-0.12.2.dist-info/METADATA,sha256=FlXiev8ZTGt1gS9XbB3IKm4X5_jaDHB8dmMnUD29alg,26345
|
|
66
|
+
musica-0.12.2.dist-info/WHEEL,sha256=-lU5UGmG1GnVwKRtK0kgAhlzoAPNkoTPfc0g2GDJrhY,100
|
|
67
|
+
musica-0.12.2.dist-info/entry_points.txt,sha256=t9qRU9Ya63_yYMKJkTiVS5kCaW6dDDr0wuQ26lgXTH8,49
|
|
68
|
+
musica-0.12.2.dist-info/licenses/AUTHORS.md,sha256=1ssAXR4WOMdfl5Or1raPu_2nxHbkwCpxfwJwzpF_cJM,2691
|
|
69
|
+
musica-0.12.2.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
70
|
+
musica-0.12.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|