musica 0.11.1.1__cp312-cp312-win_amd64.whl → 0.14.2__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.
- musica/__init__.py +23 -3
- musica/_musica.cp312-win_amd64.pyd +0 -0
- musica/_version.py +1 -1
- musica/backend.py +58 -0
- musica/carma/__init__.py +20 -0
- musica/carma/carma.py +1727 -0
- musica/constants.py +3 -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/main.py +128 -0
- musica/mechanism_configuration/__init__.py +18 -0
- musica/mechanism_configuration/ancillary.py +6 -0
- musica/mechanism_configuration/arrhenius.py +149 -0
- musica/mechanism_configuration/branched.py +140 -0
- musica/mechanism_configuration/emission.py +82 -0
- musica/mechanism_configuration/first_order_loss.py +90 -0
- musica/mechanism_configuration/mechanism.py +93 -0
- musica/mechanism_configuration/phase.py +58 -0
- musica/mechanism_configuration/phase_species.py +58 -0
- musica/mechanism_configuration/photolysis.py +98 -0
- musica/mechanism_configuration/reaction_component.py +54 -0
- musica/mechanism_configuration/reactions.py +32 -0
- musica/mechanism_configuration/species.py +65 -0
- musica/mechanism_configuration/surface.py +98 -0
- musica/mechanism_configuration/taylor_series.py +136 -0
- musica/mechanism_configuration/ternary_chemical_activation.py +160 -0
- musica/mechanism_configuration/troe.py +160 -0
- musica/mechanism_configuration/tunneling.py +126 -0
- musica/mechanism_configuration/user_defined.py +99 -0
- musica/mechanism_configuration/utils.py +10 -0
- musica/micm/__init__.py +10 -0
- musica/micm/conditions.py +49 -0
- musica/micm/micm.py +135 -0
- musica/micm/solver.py +8 -0
- musica/micm/solver_result.py +24 -0
- musica/micm/state.py +220 -0
- musica/micm/utils.py +18 -0
- musica/tuvx/__init__.py +11 -0
- musica/tuvx/grid.py +98 -0
- musica/tuvx/grid_map.py +167 -0
- musica/tuvx/profile.py +130 -0
- musica/tuvx/profile_map.py +167 -0
- musica/tuvx/radiator.py +95 -0
- musica/tuvx/radiator_map.py +173 -0
- musica/tuvx/tuvx.py +283 -0
- musica-0.14.2.dist-info/DELVEWHEEL +2 -0
- {musica-0.11.1.1.dist-info → musica-0.14.2.dist-info}/METADATA +146 -63
- musica-0.14.2.dist-info/RECORD +104 -0
- {musica-0.11.1.1.dist-info → musica-0.14.2.dist-info}/WHEEL +1 -1
- musica-0.14.2.dist-info/entry_points.txt +3 -0
- musica-0.14.2.dist-info/licenses/AUTHORS.md +59 -0
- musica.libs/libaws-c-auth-0a61a643442f1c0912920b37d9fb0be5.dll +0 -0
- musica.libs/libaws-c-cal-eaafa5905de6c9ba274eb8737e6087dd.dll +0 -0
- musica.libs/libaws-c-common-b4aa4468297ae8e1664f9380a5510317.dll +0 -0
- musica.libs/libaws-c-compression-9f997952aeae03067122ca493c9081b5.dll +0 -0
- musica.libs/libaws-c-event-stream-fe9cc8e1692f60c2b5694a8959dbd7c3.dll +0 -0
- musica.libs/libaws-c-http-4a9d50ba6ad8882f5267ef89e5e4103a.dll +0 -0
- musica.libs/libaws-c-io-e454f1c7a44e77f8c957a016888754be.dll +0 -0
- musica.libs/libaws-c-mqtt-67c5fc291740f5cbc5e53fb767e93226.dll +0 -0
- musica.libs/libaws-c-s3-206db4af6e1a95637b1921ea596603b9.dll +0 -0
- musica.libs/libaws-c-sdkutils-5c9c62dafb8b774cd4a3386f95ef428d.dll +0 -0
- musica.libs/libaws-checksums-7e50fe01b862214958f4d2ab4215fde5.dll +0 -0
- musica.libs/libaws-cpp-sdk-core-7a9ba9c045ee16f5262e955d96865718.dll +0 -0
- musica.libs/libaws-cpp-sdk-s3-4eebff3923c6d250fb508da3c990e0ae.dll +0 -0
- musica.libs/libaws-crt-cpp-3173f1e6f504a96d88e8dbf9e04b3b14.dll +0 -0
- musica.libs/libbrotlicommon-c62c08223e450dfc2fff33c752cc2285.dll +0 -0
- musica.libs/libbrotlidec-ccde7c3978eb1d2e052b193f2968d30a.dll +0 -0
- musica.libs/libbz2-1-669a4bf9266d5f020e843aa5fd75b93c.dll +0 -0
- musica.libs/libcrypto-3-x64-237eeb55505d067eab5e0b886e519387.dll +0 -0
- musica.libs/libcurl-4-bdf865458887dc1235b192ec83729214.dll +0 -0
- musica.libs/libgcc_s_seh-1-5a3153f12338f79fbbb7bf095fc5cef1.dll +0 -0
- musica.libs/libgfortran-5-90848e0eacdecce3a9005faf5aaec7e7.dll +0 -0
- musica.libs/libgomp-1-b8afcf09fecd2f6f01e454c9a5f2c690.dll +0 -0
- musica.libs/libhdf5-320-eec6c8ba2fdde30d365786ffbff40989.dll +0 -0
- musica.libs/libhdf5_hl-320-7e26e1caaad6be4082d728cf08ab2de4.dll +0 -0
- musica.libs/libiconv-2-b37d1b4acab5310c4e4f6e2a961d1464.dll +0 -0
- musica.libs/libidn2-0-d17600177f3b4cd2521d595b3472d240.dll +0 -0
- musica.libs/libintl-8-e4d4ca6b37338fbb0a8c1246afa7258f.dll +0 -0
- musica.libs/liblzma-5-bd95aa0fda6e7c8e41b3843d6fc2942c.dll +0 -0
- musica.libs/libnetcdf-0623e518145bddd30cc615b6d7f2f9c1.dll +0 -0
- musica.libs/libnetcdff-7-982cb7ee026b78f05a79d00e735f91d1.dll +0 -0
- musica.libs/libnghttp2-14-6d49ed806389b4892bcf29c6ed6e3984.dll +0 -0
- musica.libs/libnghttp3-9-d3c9b57d760f6dae7d6a067a68126b84.dll +0 -0
- musica.libs/libngtcp2-16-a43356e6376d41ce4238e2c55581636a.dll +0 -0
- musica.libs/libngtcp2_crypto_ossl-0-b37121badf25a552e5654f27bf6ff093.dll +0 -0
- musica.libs/libopenblas-a16595c3cae114c5c7304aa8bb3c1272.dll +0 -0
- musica.libs/libpsl-5-4368d4c2412410a4a14f3e7f3227e295.dll +0 -0
- musica.libs/libquadmath-0-4edeffe0a60c96360445d33a1876dbda.dll +0 -0
- musica.libs/libssh2-1-f407a2b50419bd904c7eb2c101ae81ea.dll +0 -0
- musica.libs/libssl-3-x64-d2e43d36e6f87f6f1645717cd0871f86.dll +0 -0
- musica.libs/libstdc++-6-83061aaccaf8df77a3b584efef12bc7c.dll +0 -0
- musica.libs/libsz-2-d12f3d26417507ec8dea9964f9fe36a1.dll +0 -0
- musica.libs/libunistring-5-0473d7a71d94f08292beed694c34f7d1.dll +0 -0
- musica.libs/libwinpthread-1-9157bac12a85fb717fa3d2bf6712631a.dll +0 -0
- musica.libs/libxml2-16-7fe545d280fdef922282226eef91571f.dll +0 -0
- musica.libs/libzip-62d3c877b7842bc509fc000316a4731b.dll +0 -0
- musica.libs/libzstd-a25427164f8775046eb8ce488d7d0884.dll +0 -0
- musica.libs/zlib1-1dc85208162ee57fe97e892bb5160fe9.dll +0 -0
- _musica.cp312-win_amd64.pyd +0 -0
- lib/musica.lib +0 -0
- lib/yaml-cpp.lib +0 -0
- musica/CMakeLists.txt +0 -47
- musica/binding.cpp +0 -19
- musica/mechanism_configuration.cpp +0 -519
- musica/mechanism_configuration.py +0 -1291
- musica/musica.cpp +0 -214
- 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/examples/v1/full_configuration.json +0 -434
- musica/test/examples/v1/full_configuration.yaml +0 -271
- musica/test/test_analytical.py +0 -323
- musica/test/test_chapman.py +0 -123
- musica/test/test_parser.py +0 -693
- musica/test/tuvx.py +0 -10
- musica/tools/prepare_build_environment_linux.sh +0 -41
- musica/tools/prepare_build_environment_windows.sh +0 -22
- musica/tools/repair_wheel_gpu.sh +0 -25
- musica/types.py +0 -362
- musica-0.11.1.1.dist-info/RECORD +0 -30
- {musica-0.11.1.1.dist-info → musica-0.14.2.dist-info}/licenses/LICENSE +0 -0
musica/constants.py
ADDED
musica/cuda.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .examples import Examples
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python example for CARMA aluminum aerosols.
|
|
3
|
+
|
|
4
|
+
This script creates one grid box with an initial concentration of aluminum particles
|
|
5
|
+
and allows them to coagulate.
|
|
6
|
+
"""
|
|
7
|
+
import xarray as xr
|
|
8
|
+
import numpy as np
|
|
9
|
+
import musica
|
|
10
|
+
import ussa1976
|
|
11
|
+
|
|
12
|
+
available = musica.backend.carma_available()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def run_carma_aluminum_example():
|
|
16
|
+
group = musica.carma.CARMAGroupConfig(
|
|
17
|
+
name="aluminum",
|
|
18
|
+
shortname="PRALUM",
|
|
19
|
+
rmrat=2.0,
|
|
20
|
+
rmin=21.5e-6,
|
|
21
|
+
rmon=21.5e-6,
|
|
22
|
+
ishape=musica.carma.ParticleShape.SPHERE,
|
|
23
|
+
eshape=1.0,
|
|
24
|
+
mie_calculation_algorithm=musica.carma.MieCalculationAlgorithm.TOON_1981,
|
|
25
|
+
is_ice=False,
|
|
26
|
+
is_fractal=True,
|
|
27
|
+
do_wetdep=False,
|
|
28
|
+
do_drydep=True,
|
|
29
|
+
do_vtran=True,
|
|
30
|
+
solfac=0.0,
|
|
31
|
+
scavcoef=0.0,
|
|
32
|
+
df=[1.6] * 5, # 5 bins with fractal dimension 1.6
|
|
33
|
+
falpha=1.0
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Create aluminum element
|
|
37
|
+
element = musica.carma.CARMAElementConfig(
|
|
38
|
+
igroup=1,
|
|
39
|
+
isolute=0,
|
|
40
|
+
name="Aluminum",
|
|
41
|
+
shortname="ALUM",
|
|
42
|
+
itype=musica.carma.ParticleType.INVOLATILE,
|
|
43
|
+
icomposition=musica.carma.ParticleComposition.ALUMINUM,
|
|
44
|
+
rho=0.00395, # kg/m3
|
|
45
|
+
arat=[1.0] * 5, # 5 bins with area ratio 1.0
|
|
46
|
+
kappa=0.0,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Create coagulation
|
|
50
|
+
coagulation = musica.carma.CARMACoagulationConfig(
|
|
51
|
+
igroup1=1,
|
|
52
|
+
igroup2=1,
|
|
53
|
+
igroup3=1,
|
|
54
|
+
algorithm=musica.carma.ParticleCollectionAlgorithm.FUCHS)
|
|
55
|
+
|
|
56
|
+
params = musica.carma.CARMAParameters(
|
|
57
|
+
nbin=5,
|
|
58
|
+
nz=1,
|
|
59
|
+
dtime=1800.0,
|
|
60
|
+
groups=[group],
|
|
61
|
+
elements=[element],
|
|
62
|
+
coagulations=[coagulation]
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
FIVE_DAYS_IN_SECONDS = 432000
|
|
66
|
+
params.nstep = FIVE_DAYS_IN_SECONDS // params.dtime
|
|
67
|
+
params.initialization.do_vtran = False
|
|
68
|
+
|
|
69
|
+
n_levels = params.nz
|
|
70
|
+
deltaz = 1000.0
|
|
71
|
+
zmin = 16500.0
|
|
72
|
+
|
|
73
|
+
vertical_center = zmin + (np.arange(n_levels) + 0.5) * deltaz
|
|
74
|
+
vertical_levels = zmin + np.arange(n_levels + 1) * deltaz
|
|
75
|
+
|
|
76
|
+
centered_variables = ussa1976.compute(z=vertical_center, variables=["t", "p", "rho"])
|
|
77
|
+
edge_variables = ussa1976.compute(z=vertical_levels, variables=["p"])
|
|
78
|
+
|
|
79
|
+
temperature = centered_variables.t.values
|
|
80
|
+
pressure = centered_variables.p.values
|
|
81
|
+
pressure_levels = edge_variables.p.values
|
|
82
|
+
density = centered_variables.rho.values
|
|
83
|
+
|
|
84
|
+
carma = musica.carma.CARMA(params)
|
|
85
|
+
|
|
86
|
+
mmr_initial = 5e9 / (deltaz * 2.57474699e14) / density[0]
|
|
87
|
+
|
|
88
|
+
state = carma.create_state(
|
|
89
|
+
time_step=params.dtime,
|
|
90
|
+
temperature=temperature,
|
|
91
|
+
pressure=pressure,
|
|
92
|
+
pressure_levels=pressure_levels,
|
|
93
|
+
vertical_center=vertical_center,
|
|
94
|
+
vertical_levels=vertical_levels,
|
|
95
|
+
longitude=0.0,
|
|
96
|
+
latitude=-105.0,
|
|
97
|
+
coordinates=musica.carma.CarmaCoordinates.CARTESIAN,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
for i in range(params.nbin):
|
|
101
|
+
for j in range(len(params.elements)):
|
|
102
|
+
state.set_bin(i + 1, j + 1, mmr_initial)
|
|
103
|
+
|
|
104
|
+
bin_data = state.get_bins()
|
|
105
|
+
bin_data = bin_data.expand_dims({"time": [0]})
|
|
106
|
+
env = state.get_environmental_values()
|
|
107
|
+
env = env.expand_dims({"time": [0]})
|
|
108
|
+
|
|
109
|
+
# Run the simulation for the specified number of steps
|
|
110
|
+
for step in range(1, int(params.nstep)):
|
|
111
|
+
state.step()
|
|
112
|
+
bin_data = xr.concat([bin_data, state.get_bins().expand_dims({"time": [step * params.dtime]})], dim="time")
|
|
113
|
+
env = xr.concat([env, state.get_environmental_values().expand_dims(
|
|
114
|
+
{"time": [step * params.dtime]})], dim="time")
|
|
115
|
+
|
|
116
|
+
return xr.merge([bin_data, env])
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
if __name__ == '__main__':
|
|
120
|
+
if not available:
|
|
121
|
+
print("CARMA backend is not available.")
|
|
122
|
+
else:
|
|
123
|
+
state = run_carma_aluminum_example()
|
|
124
|
+
print(state)
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python example for CARMA sulfate that mimics the logic of the CARMA Fortran test.
|
|
3
|
+
|
|
4
|
+
This script creates one grid box with an initial concentration of sulfate particles
|
|
5
|
+
at the smallest size, then allows that to grow using H2SO4 gas. The total mass
|
|
6
|
+
of particles + gas should be conserved.
|
|
7
|
+
|
|
8
|
+
Based on carma_sulfatetest.F90
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import xarray as xr
|
|
12
|
+
import numpy as np
|
|
13
|
+
import musica
|
|
14
|
+
|
|
15
|
+
available = musica.backend.carma_available()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def run_carma_sulfate_example():
|
|
19
|
+
"""Test CARMA sulfate growth from gas condensation in a simple single grid box."""
|
|
20
|
+
|
|
21
|
+
GRAVITY = 9.806 # Acceleration due to gravity in m/s^2
|
|
22
|
+
|
|
23
|
+
# Simplified constants for debugging
|
|
24
|
+
NZ = 1
|
|
25
|
+
NELEM = 1
|
|
26
|
+
NBIN = 38
|
|
27
|
+
|
|
28
|
+
dtime = 1800.0 # Time step in seconds
|
|
29
|
+
deltaz = 10000.0 # Grid box height in meters
|
|
30
|
+
nsteps = int(180000 / dtime)
|
|
31
|
+
|
|
32
|
+
# Sulfate density
|
|
33
|
+
rho_sulfate_kg_m3 = 1923.0 # kg/m³
|
|
34
|
+
|
|
35
|
+
# Grid setup
|
|
36
|
+
latitude = -40.0
|
|
37
|
+
longitude = -105.0
|
|
38
|
+
vertical_center = [17000.0]
|
|
39
|
+
vertical_levels = [vertical_center[0] - deltaz, vertical_center[0] + deltaz]
|
|
40
|
+
|
|
41
|
+
# Standard atmosphere
|
|
42
|
+
pressure_centers = np.array([9000.0])
|
|
43
|
+
temperature_centers = np.array([250.0])
|
|
44
|
+
# this is directly from the original CARMA test, but it seems like there are some unit conversion issues
|
|
45
|
+
air_mass_density_centers = pressure_centers * 10.0 / (8.31430e07 / 28.966 * temperature_centers) * (1.0e-3 * 1.0e6)
|
|
46
|
+
pressure_levels = np.zeros(2)
|
|
47
|
+
pressure_levels[0] = pressure_centers[0] - \
|
|
48
|
+
(vertical_levels[0] - vertical_center[0]) * air_mass_density_centers[0] * GRAVITY
|
|
49
|
+
pressure_levels[1] = pressure_centers[0] - \
|
|
50
|
+
(vertical_levels[1] - vertical_center[0]) * air_mass_density_centers[0] * GRAVITY
|
|
51
|
+
|
|
52
|
+
# Initial mass mixing ratios
|
|
53
|
+
mass_mixing_ratios = {
|
|
54
|
+
"H2O": [1.0e-4],
|
|
55
|
+
"H2SO4": [0.1e-9 * (98.0 / 29.0)],
|
|
56
|
+
"SULFATE": [[0.0 for _ in range(NBIN)]]
|
|
57
|
+
}
|
|
58
|
+
satliq = {
|
|
59
|
+
"H2O": [-1.0],
|
|
60
|
+
"H2SO4": [-1.0]
|
|
61
|
+
}
|
|
62
|
+
satice = {
|
|
63
|
+
"H2O": [-1.0],
|
|
64
|
+
"H2SO4": [-1.0]
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# Set up CARMA parameters
|
|
68
|
+
params = musica.carma.CARMAParameters()
|
|
69
|
+
params.nz = NZ
|
|
70
|
+
params.nbin = NBIN
|
|
71
|
+
|
|
72
|
+
# Create sulfate group - simplified
|
|
73
|
+
sulfate_group = musica.carma.CARMAGroupConfig(
|
|
74
|
+
name="sulfate",
|
|
75
|
+
shortname="SULF",
|
|
76
|
+
rmin=2.e-10, # Minimum radius in m
|
|
77
|
+
rmrat=2.0, # Mass ratio between bins
|
|
78
|
+
swelling_approach={
|
|
79
|
+
"algorithm": musica.carma.ParticleSwellingAlgorithm.WEIGHT_PERCENT_H2SO4,
|
|
80
|
+
"composition": musica.carma.ParticleSwellingComposition.NONE
|
|
81
|
+
},
|
|
82
|
+
do_drydep=True,
|
|
83
|
+
is_sulfate=True
|
|
84
|
+
)
|
|
85
|
+
params.add_group(sulfate_group)
|
|
86
|
+
|
|
87
|
+
# Create sulfate element
|
|
88
|
+
sulfate_element = musica.carma.CARMAElementConfig(
|
|
89
|
+
igroup=1,
|
|
90
|
+
name="Sulfate",
|
|
91
|
+
shortname="SULF",
|
|
92
|
+
rho=rho_sulfate_kg_m3,
|
|
93
|
+
itype=musica.carma.ParticleType.VOLATILE,
|
|
94
|
+
icomposition=musica.carma.ParticleComposition.SULFURIC_ACID
|
|
95
|
+
)
|
|
96
|
+
params.add_element(sulfate_element)
|
|
97
|
+
|
|
98
|
+
# Create gases - simplified to match successful test_carma.py pattern
|
|
99
|
+
water_gas = musica.carma.CARMAGasConfig(
|
|
100
|
+
name="Water Vapor",
|
|
101
|
+
shortname="H2O",
|
|
102
|
+
wtmol=0.018015, # kg/mol
|
|
103
|
+
ivaprtn=musica.carma.VaporizationAlgorithm.H2O_MURPHY_2005,
|
|
104
|
+
icomposition=musica.carma.GasComposition.H2O,
|
|
105
|
+
dgc_threshold=0.1,
|
|
106
|
+
ds_threshold=0.1
|
|
107
|
+
)
|
|
108
|
+
params.add_gas(water_gas)
|
|
109
|
+
|
|
110
|
+
# Create H2SO4 gas
|
|
111
|
+
h2so4_gas = musica.carma.CARMAGasConfig(
|
|
112
|
+
name="Sulfuric Acid",
|
|
113
|
+
shortname="H2SO4",
|
|
114
|
+
wtmol=0.098079, # kg/mol
|
|
115
|
+
ivaprtn=musica.carma.VaporizationAlgorithm.H2SO4_AYERS_1980,
|
|
116
|
+
icomposition=musica.carma.GasComposition.H2SO4,
|
|
117
|
+
dgc_threshold=0.1,
|
|
118
|
+
ds_threshold=0.1
|
|
119
|
+
)
|
|
120
|
+
params.add_gas(h2so4_gas)
|
|
121
|
+
|
|
122
|
+
# Add growth process
|
|
123
|
+
growth = musica.carma.CARMAGrowthConfig(
|
|
124
|
+
ielem=1, # Sulfate element
|
|
125
|
+
igas=2 # H2SO4 gas
|
|
126
|
+
)
|
|
127
|
+
params.add_growth(growth)
|
|
128
|
+
|
|
129
|
+
# Add nucleation process
|
|
130
|
+
nucleation = musica.carma.CARMANucleationConfig(
|
|
131
|
+
ielemfrom=1,
|
|
132
|
+
ielemto=1,
|
|
133
|
+
algorithm=musica.carma.ParticleNucleationAlgorithm.HOMOGENEOUS_NUCLEATION,
|
|
134
|
+
rlh_nuc=0.0,
|
|
135
|
+
igas=2 # H2SO4 gas
|
|
136
|
+
)
|
|
137
|
+
params.add_nucleation(nucleation)
|
|
138
|
+
|
|
139
|
+
# Add coagulation
|
|
140
|
+
coagulation = musica.carma.CARMACoagulationConfig(
|
|
141
|
+
igroup1=1,
|
|
142
|
+
igroup2=1,
|
|
143
|
+
igroup3=1,
|
|
144
|
+
algorithm=musica.carma.ParticleCollectionAlgorithm.FUCHS
|
|
145
|
+
)
|
|
146
|
+
params.add_coagulation(coagulation)
|
|
147
|
+
|
|
148
|
+
# Initialization
|
|
149
|
+
params.initialization.do_substep = True
|
|
150
|
+
params.initialization.do_thermo = True
|
|
151
|
+
params.initialization.maxretries = 16
|
|
152
|
+
params.initialization.maxsubsteps = 32
|
|
153
|
+
params.initialization.dt_threshold = 1.0
|
|
154
|
+
params.initialization.sulfnucl_method = musica.carma.SulfateNucleationMethod.ZHAO_TURCO.value
|
|
155
|
+
|
|
156
|
+
# Create CARMA instance
|
|
157
|
+
carma = musica.carma.CARMA(params)
|
|
158
|
+
|
|
159
|
+
# Output group properties
|
|
160
|
+
group_props, _ = carma.get_group_properties()
|
|
161
|
+
# Print bin radius and bin mass from group_props xarray Dataset
|
|
162
|
+
for i_bin in range(NBIN):
|
|
163
|
+
print(
|
|
164
|
+
f"Bin {i_bin + 1}: bin radius = {group_props.isel(bin=i_bin)['bin_radius']}; bin mass = {group_props.isel(bin=i_bin)['bin_mass']}"
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
bin_state = None
|
|
168
|
+
gas_state = None
|
|
169
|
+
env_state = None
|
|
170
|
+
|
|
171
|
+
for i_step in range(nsteps):
|
|
172
|
+
|
|
173
|
+
# Create state
|
|
174
|
+
state = carma.create_state(
|
|
175
|
+
time_step=dtime,
|
|
176
|
+
temperature=temperature_centers,
|
|
177
|
+
original_temperature=temperature_centers,
|
|
178
|
+
pressure=pressure_centers,
|
|
179
|
+
pressure_levels=pressure_levels,
|
|
180
|
+
vertical_center=vertical_center,
|
|
181
|
+
vertical_levels=vertical_levels,
|
|
182
|
+
longitude=longitude,
|
|
183
|
+
latitude=latitude,
|
|
184
|
+
coordinates=musica.carma.CarmaCoordinates.CARTESIAN,
|
|
185
|
+
specific_humidity=mass_mixing_ratios["H2O"],
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# Initialize particle concentrations to zero
|
|
189
|
+
for ibin in range(1, NBIN + 1):
|
|
190
|
+
for ielem in range(1, NELEM + 1):
|
|
191
|
+
state.set_bin(ibin, ielem, mass_mixing_ratios["SULFATE"][0][ibin - 1])
|
|
192
|
+
|
|
193
|
+
# Set H2O concentration
|
|
194
|
+
state.set_gas(
|
|
195
|
+
gas_index=1,
|
|
196
|
+
value=mass_mixing_ratios["H2O"],
|
|
197
|
+
old_mmr=mass_mixing_ratios["H2O"],
|
|
198
|
+
gas_saturation_wrt_ice=satice["H2O"],
|
|
199
|
+
gas_saturation_wrt_liquid=satliq["H2O"],
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
# Set H2SO4 concentration
|
|
203
|
+
state.set_gas(
|
|
204
|
+
gas_index=2,
|
|
205
|
+
value=[mmr * 1.05 for mmr in mass_mixing_ratios["H2SO4"]],
|
|
206
|
+
old_mmr=mass_mixing_ratios["H2SO4"],
|
|
207
|
+
gas_saturation_wrt_ice=satice["H2SO4"],
|
|
208
|
+
gas_saturation_wrt_liquid=satliq["H2SO4"],
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# Perform model step
|
|
212
|
+
state.step()
|
|
213
|
+
stats = state.get_step_statistics()
|
|
214
|
+
print(f"Step {i_step + 1}/{nsteps}: {stats}")
|
|
215
|
+
|
|
216
|
+
# Get updated state values
|
|
217
|
+
if bin_state is None:
|
|
218
|
+
bin_state = state.get_bins()
|
|
219
|
+
bin_state = bin_state.expand_dims({"time": [i_step * dtime]})
|
|
220
|
+
else:
|
|
221
|
+
bin_state = xr.concat([bin_state, state.get_bins().expand_dims({"time": [i_step * dtime]})], dim="time")
|
|
222
|
+
|
|
223
|
+
if gas_state is None:
|
|
224
|
+
gas_state = state.get_gases()[0]
|
|
225
|
+
gas_state = gas_state.expand_dims({"time": [i_step * dtime]})
|
|
226
|
+
else:
|
|
227
|
+
gas_state = xr.concat([gas_state, state.get_gases()[0].expand_dims({"time": [i_step * dtime]})], dim="time")
|
|
228
|
+
|
|
229
|
+
if env_state is None:
|
|
230
|
+
env_state = state.get_environmental_values()
|
|
231
|
+
env_state = env_state.expand_dims({"time": [i_step * dtime]})
|
|
232
|
+
else:
|
|
233
|
+
env_state = xr.concat([env_state, state.get_environmental_values(
|
|
234
|
+
).expand_dims({"time": [i_step * dtime]})], dim="time")
|
|
235
|
+
|
|
236
|
+
return env_state, gas_state, bin_state
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
if __name__ == '__main__':
|
|
240
|
+
if not available:
|
|
241
|
+
print("CARMA backend is not available.")
|
|
242
|
+
else:
|
|
243
|
+
env_state, gas_state, bin_state = run_carma_sulfate_example()
|
|
244
|
+
print(env_state)
|
|
245
|
+
print(gas_state)
|
|
246
|
+
print(bin_state)
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""MUSICA Examples Module.
|
|
2
|
+
|
|
3
|
+
This module provides a centralized way to access and manage MUSICA examples.
|
|
4
|
+
It defines the Example class for representing individual examples and the
|
|
5
|
+
Examples singleton for accessing all available examples.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
>>> from musica.examples import Examples
|
|
9
|
+
>>> print(Examples.TS1LatinHyperCube)
|
|
10
|
+
>>> for example in Examples:
|
|
11
|
+
... print(example.name)
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Example:
|
|
16
|
+
"""A class representing a MUSICA example.
|
|
17
|
+
|
|
18
|
+
This class encapsulates information about a specific example, including its name,
|
|
19
|
+
short name, description, and file path. It provides methods for string representation
|
|
20
|
+
and class-based construction.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, name, short_name, description, path):
|
|
24
|
+
"""Initialize an Example instance.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
name (str): The display name of the example.
|
|
28
|
+
short_name (str): A short identifier for the example.
|
|
29
|
+
description (str): A detailed description of what the example demonstrates.
|
|
30
|
+
path (str): The file path to the example script.
|
|
31
|
+
"""
|
|
32
|
+
self.name = name
|
|
33
|
+
self.short_name = short_name
|
|
34
|
+
self.description = description
|
|
35
|
+
self.path = path
|
|
36
|
+
|
|
37
|
+
def __str__(self):
|
|
38
|
+
"""Return a string representation of the example.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
str: A formatted string showing the name and description.
|
|
42
|
+
"""
|
|
43
|
+
return f'{self.name}: {self.description}'
|
|
44
|
+
|
|
45
|
+
def __repr__(self):
|
|
46
|
+
"""Return a string representation of the example for debugging.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
str: A formatted string showing the name and description.
|
|
50
|
+
"""
|
|
51
|
+
return f'{self.name}: {self.description}'
|
|
52
|
+
|
|
53
|
+
@classmethod
|
|
54
|
+
def from_config(cls, display_name, path, short_name, description):
|
|
55
|
+
"""Create an Example instance from configuration parameters.
|
|
56
|
+
|
|
57
|
+
This class method provides an alternative constructor that creates an Example
|
|
58
|
+
instance with more explicit parameter naming.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
display_name (str): The display name of the example.
|
|
62
|
+
path (str): The file path to the example script.
|
|
63
|
+
short_name (str): A short identifier for the example.
|
|
64
|
+
description (str): A detailed description of what the example demonstrates.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
Example: A new Example instance with the provided configuration.
|
|
68
|
+
"""
|
|
69
|
+
return cls(name=display_name, short_name=short_name, description=description, path=path)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class _Examples:
|
|
73
|
+
"""A container class for managing MUSICA examples.
|
|
74
|
+
|
|
75
|
+
This class provides a centralized way to access and manage all available MUSICA
|
|
76
|
+
examples. It includes predefined examples and supports iteration, indexing, and
|
|
77
|
+
attribute access patterns.
|
|
78
|
+
"""
|
|
79
|
+
CARMA_Aluminum = Example.from_config(
|
|
80
|
+
display_name='CARMA Aluminum',
|
|
81
|
+
short_name='CARMA_Aluminum',
|
|
82
|
+
path='carma_aluminum.py',
|
|
83
|
+
description='A CARMA example for simulating aluminum aerosol particles.')
|
|
84
|
+
CARMA_Sulfate = Example.from_config(
|
|
85
|
+
display_name='CARMA Sulfate',
|
|
86
|
+
short_name='CARMA_Sulfate',
|
|
87
|
+
path='carma_sulfate.py',
|
|
88
|
+
description='A CARMA example for simulating sulfate aerosol particles.')
|
|
89
|
+
Sulfate_Box_Model = Example.from_config(
|
|
90
|
+
display_name='Sulfate Box Model',
|
|
91
|
+
short_name='Sulfate_Box_Model',
|
|
92
|
+
path='sulfate_box_model.py',
|
|
93
|
+
description='A box model example for simulating sulfate aerosol particles.')
|
|
94
|
+
TS1LatinHyperCube = Example.from_config(
|
|
95
|
+
display_name='TS1 Latin Hypercube',
|
|
96
|
+
short_name='TS1LatinHyperCube',
|
|
97
|
+
path='ts1_latin_hypercube.py',
|
|
98
|
+
description='A Latin hypercube sampling example for the TS1 mechanism. This script shows how to sample an input space and run multiple box models in parallel on a single mechanism.')
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
def get_all(cls):
|
|
102
|
+
"""Get all available examples.
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
list[Example]: A list of all available Example instances.
|
|
106
|
+
"""
|
|
107
|
+
return [cls.CARMA_Aluminum, cls.CARMA_Sulfate, cls.Sulfate_Box_Model, cls.TS1LatinHyperCube]
|
|
108
|
+
|
|
109
|
+
def __iter__(self):
|
|
110
|
+
"""Make the class iterable over examples.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
iterator: An iterator over all available examples.
|
|
114
|
+
"""
|
|
115
|
+
return iter(self.get_all())
|
|
116
|
+
|
|
117
|
+
def __getattr__(self, item):
|
|
118
|
+
"""Handle attribute access for examples.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
item (str): The attribute name to access.
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
Any: The requested attribute value.
|
|
125
|
+
|
|
126
|
+
Raises:
|
|
127
|
+
AttributeError: If the attribute doesn't exist.
|
|
128
|
+
"""
|
|
129
|
+
# Check if the attribute exists in the class definition
|
|
130
|
+
if hasattr(self.__class__, item):
|
|
131
|
+
return getattr(self.__class__, item)
|
|
132
|
+
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{item}'")
|
|
133
|
+
|
|
134
|
+
def __getitem__(self, item):
|
|
135
|
+
"""Support indexing to access examples by position.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
item (int): The index of the example to retrieve.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
Example: The example at the specified index.
|
|
142
|
+
|
|
143
|
+
Raises:
|
|
144
|
+
IndexError: If the index is out of range.
|
|
145
|
+
"""
|
|
146
|
+
return self.get_all()[item]
|
|
147
|
+
|
|
148
|
+
def __repr__(self):
|
|
149
|
+
"""Return a string representation for debugging.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
str: A formatted string showing all available examples.
|
|
153
|
+
"""
|
|
154
|
+
return f'Examples: {self.get_all()}'
|
|
155
|
+
|
|
156
|
+
def __str__(self):
|
|
157
|
+
"""Return a string representation of the examples collection.
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
str: A formatted string showing all available examples.
|
|
161
|
+
"""
|
|
162
|
+
return f'Examples: {self.get_all()}'
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
Examples = _Examples()
|