Skip to content

Commit

Permalink
Merge pull request #257 from NCAR/main
Browse files Browse the repository at this point in the history
v2.5.2
  • Loading branch information
K20shores authored Oct 9, 2024
2 parents ea86445 + 3238d4c commit 9127f34
Show file tree
Hide file tree
Showing 20 changed files with 591 additions and 120 deletions.
2 changes: 1 addition & 1 deletion src/acom_music_box/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
This package contains modules for handling various aspects of a music box,
including species, products, reactants, reactions, and more.
"""
__version__ = "2.5.1"
__version__ = "2.5.2"

from .utils import convert_time, convert_pressure, convert_temperature, convert_concentration
from .species import Species
Expand Down
15 changes: 7 additions & 8 deletions src/acom_music_box/conditions.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .utils import convert_time, convert_pressure, convert_temperature, convert_concentration
from .utils import convert_pressure, convert_temperature, convert_concentration
from .species_concentration import SpeciesConcentration
from .species import Species
from .reaction_rate import ReactionRate
Expand All @@ -9,7 +9,6 @@
from .reaction_rate import ReactionRate
from .species import Species
from .species_concentration import SpeciesConcentration
from .utils import convert_time, convert_pressure, convert_temperature, convert_concentration

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

@classmethod
def from_UI_JSON(cls, UI_JSON, species_list, reaction_list):
def from_UI_JSON(self, UI_JSON, species_list, reaction_list):
"""
Creates an instance of the class from a UI JSON object.
Expand Down Expand Up @@ -108,15 +107,15 @@ def from_UI_JSON(cls, UI_JSON, species_list, reaction_list):

reaction_rates.append(ReactionRate(reaction_from_list, rate))

return cls(
return self(
pressure,
temperature,
species_concentrations,
reaction_rates)

@classmethod
def from_config_JSON(
cls,
self,
path_to_json,
config_JSON,
species_list,
Expand Down Expand Up @@ -164,7 +163,7 @@ def from_config_JSON(
for chem_spec in config_JSON['chemical species']:
species = Species(name=chem_spec)
concentration = convert_concentration(
config_JSON['chemical species'][chem_spec], 'initial value')
config_JSON['chemical species'][chem_spec], 'initial value', temperature, pressure)

species_concentrations.append(
SpeciesConcentration(
Expand All @@ -190,14 +189,14 @@ def from_config_JSON(
if not reaction_exists:
reaction_rates.append(ReactionRate(reaction, 0))

return cls(
return self(
pressure,
temperature,
species_concentrations,
reaction_rates)

@classmethod
def read_initial_rates_from_file(cls, file_path, reaction_list):
def read_initial_rates_from_file(self, file_path, reaction_list):
"""
Reads initial reaction rates from a file.
Expand Down
6 changes: 3 additions & 3 deletions src/acom_music_box/constants.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
BOLTZMANN_CONSTANT = 1.380649e-23
AVOGADRO_CONSTANT = 6.02214076e23
GAS_CONSTANT = BOLTZMANN_CONSTANT * AVOGADRO_CONSTANT
BOLTZMANN_CONSTANT = 1.380649e-23 # joules / Kelvin
AVOGADRO_CONSTANT = 6.02214076e23 # / mole
GAS_CONSTANT = BOLTZMANN_CONSTANT * AVOGADRO_CONSTANT # joules / Kelvin-mole

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
}
},
"evolving conditions": {
"evolving_conditions.csv": {}
},
"initial conditions": {},
"model components": [
Expand Down
35 changes: 12 additions & 23 deletions src/acom_music_box/music_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import pandas as pd

from tqdm import tqdm
from tqdm.contrib.logging import logging_redirect_tqdm

import logging
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -55,7 +54,6 @@ def __init__(
self.evolving_conditions = evolving_conditions if evolving_conditions is not None else EvolvingConditions([
], [])
self.config_file = config_file if config_file is not None else "camp_data/config.json"

self.solver = None

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

def create_solver(
self,
path_to_config,
solver_type=musica.micmsolver.rosenbrock,
number_of_grid_cells=1):
"""
Creates a micm solver object using the CAMP configuration files.
Args:
path_to_config (str): The path to CAMP configuration directory.
Returns:
None
"""
# Create a solver object using the configuration file
self.solver = musica.create_solver(
path_to_config,
solver_type,
number_of_grid_cells)

def check_config(self, boxConfigPath):
"""
Verifies correct configuration of the MusicBox object.
Expand All @@ -106,7 +84,17 @@ def check_config(self, boxConfigPath):
Throws error for the first check failed.
"""

# look for duplicate reaction names
# Check for duplicate reactions in the reaction list
if self.reaction_list:
reaction_names = [reaction.name for reaction in self.reaction_list.reactions]
reaction_names = [name for name in reaction_names if name is not None]
dup_names = [name for name in reaction_names if reaction_names.count(name) > 1]

if dup_names:
raise Exception(f"Error: Duplicate reaction names specified within {boxConfigPath}: {dup_names}. "
"Please remove or rename the duplicates.")

# look for duplicate reaction names in the initial conditions
if (self.initial_conditions):
if (self.initial_conditions.reaction_rates):
reactionNames = []
Expand Down Expand Up @@ -301,6 +289,7 @@ def loadJson(self, path_to_json):

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

Expand Down
3 changes: 1 addition & 2 deletions src/acom_music_box/reaction_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ def from_config_JSON(cls, path_to_json, config_JSON, species_list):

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

Expand Down
3 changes: 1 addition & 2 deletions src/acom_music_box/species_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ def from_config_JSON(cls, path_to_json, config_JSON):

# assumes species file is first in the list
if (len(config['camp-files']) > 0):
species_file_path = os.path.dirname(
config_file_path) + "/" + config['camp-files'][0]
species_file_path = os.path.join(os.path.dirname(config_file_path), config['camp-files'][0])
with open(species_file_path, 'r') as species_file:
species_data = json.load(species_file)
# loads species by names from camp files
Expand Down
16 changes: 2 additions & 14 deletions src/acom_music_box/tools/waccmToMusicBox.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import tempfile
import zipfile
from acom_music_box import Examples
from acom_music_box.utils import calculate_air_density

import logging
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -219,19 +220,6 @@ def readWACCM(waccmMusicaDict, latitude, longitude,
return (musicaDict)


# Calculate air density from the ideal gas law.
# tempK = temperature in degrees Kelvin
# pressPa = pressure in Pascals
# return density of air in moles / cubic meter
def calcAirDensity(tempK, pressPa):
BOLTZMANN_CONSTANT = 1.380649e-23 # joules / Kelvin
AVOGADRO_CONSTANT = 6.02214076e23 # / mole
GAS_CONSTANT = BOLTZMANN_CONSTANT * AVOGADRO_CONSTANT # joules / Kelvin-mole
airDensity = pressPa / (GAS_CONSTANT * tempK) # moles / m3

return airDensity


# set up indexes for the tuple
musicaIndex = 0
valueIndex = 1
Expand All @@ -252,7 +240,7 @@ def convertWaccm(varDict):
temperature = varDict["temperature"][valueIndex]
pressure = varDict["pressure"][valueIndex]
logger.info(f"temperature = {temperature} K pressure = {pressure} Pa")
air_density = calcAirDensity(temperature, pressure)
air_density = calculate_air_density(temperature, pressure)
logger.info(f"air density = {air_density} mol m-3")

for key, vTuple in varDict.items():
Expand Down
Loading

0 comments on commit 9127f34

Please sign in to comment.