Skip to content

Commit fa32e7c

Browse files
authored
Merge pull request #257 from NCAR/main
v2.5.2
2 parents 14cf834 + 64cf4af commit fa32e7c

File tree

20 files changed

+591
-120
lines changed

20 files changed

+591
-120
lines changed

src/acom_music_box/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
This package contains modules for handling various aspects of a music box,
55
including species, products, reactants, reactions, and more.
66
"""
7-
__version__ = "2.5.1"
7+
__version__ = "2.5.2"
88

99
from .utils import convert_time, convert_pressure, convert_temperature, convert_concentration
1010
from .species import Species

src/acom_music_box/conditions.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .utils import convert_time, convert_pressure, convert_temperature, convert_concentration
1+
from .utils import convert_pressure, convert_temperature, convert_concentration
22
from .species_concentration import SpeciesConcentration
33
from .species import Species
44
from .reaction_rate import ReactionRate
@@ -9,7 +9,6 @@
99
from .reaction_rate import ReactionRate
1010
from .species import Species
1111
from .species_concentration import SpeciesConcentration
12-
from .utils import convert_time, convert_pressure, convert_temperature, convert_concentration
1312

1413
import logging
1514
logger = logging.getLogger(__name__)
@@ -54,7 +53,7 @@ def __str__(self):
5453
return f"Pressure: {self.pressure}, Temperature: {self.temperature}, Species Concentrations: {self.species_concentrations}, Reaction Rates: {self.reaction_rates}"
5554

5655
@classmethod
57-
def from_UI_JSON(cls, UI_JSON, species_list, reaction_list):
56+
def from_UI_JSON(self, UI_JSON, species_list, reaction_list):
5857
"""
5958
Creates an instance of the class from a UI JSON object.
6059
@@ -108,15 +107,15 @@ def from_UI_JSON(cls, UI_JSON, species_list, reaction_list):
108107

109108
reaction_rates.append(ReactionRate(reaction_from_list, rate))
110109

111-
return cls(
110+
return self(
112111
pressure,
113112
temperature,
114113
species_concentrations,
115114
reaction_rates)
116115

117116
@classmethod
118117
def from_config_JSON(
119-
cls,
118+
self,
120119
path_to_json,
121120
config_JSON,
122121
species_list,
@@ -164,7 +163,7 @@ def from_config_JSON(
164163
for chem_spec in config_JSON['chemical species']:
165164
species = Species(name=chem_spec)
166165
concentration = convert_concentration(
167-
config_JSON['chemical species'][chem_spec], 'initial value')
166+
config_JSON['chemical species'][chem_spec], 'initial value', temperature, pressure)
168167

169168
species_concentrations.append(
170169
SpeciesConcentration(
@@ -190,14 +189,14 @@ def from_config_JSON(
190189
if not reaction_exists:
191190
reaction_rates.append(ReactionRate(reaction, 0))
192191

193-
return cls(
192+
return self(
194193
pressure,
195194
temperature,
196195
species_concentrations,
197196
reaction_rates)
198197

199198
@classmethod
200-
def read_initial_rates_from_file(cls, file_path, reaction_list):
199+
def read_initial_rates_from_file(self, file_path, reaction_list):
201200
"""
202201
Reads initial reaction rates from a file.
203202

src/acom_music_box/constants.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
BOLTZMANN_CONSTANT = 1.380649e-23
2-
AVOGADRO_CONSTANT = 6.02214076e23
3-
GAS_CONSTANT = BOLTZMANN_CONSTANT * AVOGADRO_CONSTANT
1+
BOLTZMANN_CONSTANT = 1.380649e-23 # joules / Kelvin
2+
AVOGADRO_CONSTANT = 6.02214076e23 # / mole
3+
GAS_CONSTANT = BOLTZMANN_CONSTANT * AVOGADRO_CONSTANT # joules / Kelvin-mole

src/acom_music_box/examples/configs/analytical/evolving_conditions.csv

Lines changed: 0 additions & 2 deletions
This file was deleted.

src/acom_music_box/examples/configs/analytical/my_config.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
}
2727
},
2828
"evolving conditions": {
29-
"evolving_conditions.csv": {}
3029
},
3130
"initial conditions": {},
3231
"model components": [

src/acom_music_box/music_box.py

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import pandas as pd
1111

1212
from tqdm import tqdm
13-
from tqdm.contrib.logging import logging_redirect_tqdm
1413

1514
import logging
1615
logger = logging.getLogger(__name__)
@@ -55,7 +54,6 @@ def __init__(
5554
self.evolving_conditions = evolving_conditions if evolving_conditions is not None else EvolvingConditions([
5655
], [])
5756
self.config_file = config_file if config_file is not None else "camp_data/config.json"
58-
5957
self.solver = None
6058

6159
def add_evolving_condition(self, time_point, conditions):
@@ -70,26 +68,6 @@ def add_evolving_condition(self, time_point, conditions):
7068
time=[time_point], conditions=[conditions])
7169
self.evolvingConditions.append(evolving_condition)
7270

73-
def create_solver(
74-
self,
75-
path_to_config,
76-
solver_type=musica.micmsolver.rosenbrock,
77-
number_of_grid_cells=1):
78-
"""
79-
Creates a micm solver object using the CAMP configuration files.
80-
81-
Args:
82-
path_to_config (str): The path to CAMP configuration directory.
83-
84-
Returns:
85-
None
86-
"""
87-
# Create a solver object using the configuration file
88-
self.solver = musica.create_solver(
89-
path_to_config,
90-
solver_type,
91-
number_of_grid_cells)
92-
9371
def check_config(self, boxConfigPath):
9472
"""
9573
Verifies correct configuration of the MusicBox object.
@@ -106,7 +84,17 @@ def check_config(self, boxConfigPath):
10684
Throws error for the first check failed.
10785
"""
10886

109-
# look for duplicate reaction names
87+
# Check for duplicate reactions in the reaction list
88+
if self.reaction_list:
89+
reaction_names = [reaction.name for reaction in self.reaction_list.reactions]
90+
reaction_names = [name for name in reaction_names if name is not None]
91+
dup_names = [name for name in reaction_names if reaction_names.count(name) > 1]
92+
93+
if dup_names:
94+
raise Exception(f"Error: Duplicate reaction names specified within {boxConfigPath}: {dup_names}. "
95+
"Please remove or rename the duplicates.")
96+
97+
# look for duplicate reaction names in the initial conditions
11098
if (self.initial_conditions):
11199
if (self.initial_conditions.reaction_rates):
112100
reactionNames = []
@@ -301,6 +289,7 @@ def loadJson(self, path_to_json):
301289

302290
with open(path_to_json, 'r') as json_file:
303291
data = json.load(json_file)
292+
self.config_file = data['model components'][0]['configuration file']
304293
# Set box model options
305294
self.box_model_options = BoxModelOptions.from_config_JSON(data)
306295

src/acom_music_box/reaction_list.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,7 @@ def from_config_JSON(cls, path_to_json, config_JSON, species_list):
8181

8282
# assumes reactions file is second in the list
8383
if (len(config['camp-files']) > 1):
84-
reaction_file_path = os.path.dirname(
85-
config_file_path) + "/" + config['camp-files'][1]
84+
reaction_file_path = os.path.join(os.path.dirname(config_file_path), config['camp-files'][1])
8685
with open(reaction_file_path, 'r') as reaction_file:
8786
reaction_data = json.load(reaction_file)
8887

src/acom_music_box/species_list.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ def from_config_JSON(cls, path_to_json, config_JSON):
8080

8181
# assumes species file is first in the list
8282
if (len(config['camp-files']) > 0):
83-
species_file_path = os.path.dirname(
84-
config_file_path) + "/" + config['camp-files'][0]
83+
species_file_path = os.path.join(os.path.dirname(config_file_path), config['camp-files'][0])
8584
with open(species_file_path, 'r') as species_file:
8685
species_data = json.load(species_file)
8786
# loads species by names from camp files

src/acom_music_box/tools/waccmToMusicBox.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import tempfile
1818
import zipfile
1919
from acom_music_box import Examples
20+
from acom_music_box.utils import calculate_air_density
2021

2122
import logging
2223
logger = logging.getLogger(__name__)
@@ -219,19 +220,6 @@ def readWACCM(waccmMusicaDict, latitude, longitude,
219220
return (musicaDict)
220221

221222

222-
# Calculate air density from the ideal gas law.
223-
# tempK = temperature in degrees Kelvin
224-
# pressPa = pressure in Pascals
225-
# return density of air in moles / cubic meter
226-
def calcAirDensity(tempK, pressPa):
227-
BOLTZMANN_CONSTANT = 1.380649e-23 # joules / Kelvin
228-
AVOGADRO_CONSTANT = 6.02214076e23 # / mole
229-
GAS_CONSTANT = BOLTZMANN_CONSTANT * AVOGADRO_CONSTANT # joules / Kelvin-mole
230-
airDensity = pressPa / (GAS_CONSTANT * tempK) # moles / m3
231-
232-
return airDensity
233-
234-
235223
# set up indexes for the tuple
236224
musicaIndex = 0
237225
valueIndex = 1
@@ -252,7 +240,7 @@ def convertWaccm(varDict):
252240
temperature = varDict["temperature"][valueIndex]
253241
pressure = varDict["pressure"][valueIndex]
254242
logger.info(f"temperature = {temperature} K pressure = {pressure} Pa")
255-
air_density = calcAirDensity(temperature, pressure)
243+
air_density = calculate_air_density(temperature, pressure)
256244
logger.info(f"air density = {air_density} mol m-3")
257245

258246
for key, vTuple in varDict.items():

0 commit comments

Comments
 (0)