Source code for opencmp.config_functions.base_config_functions

########################################################################################################################
# Copyright 2021 the authors (see AUTHORS file for full list).                                                         #
#                                                                                                                      #
# This file is part of OpenCMP.                                                                                        #
#                                                                                                                      #
# OpenCMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public  #
# License as published by the Free Software Foundation, either version 2.1 of the License, or (at your option) any     #
# later version.                                                                                                       #
#                                                                                                                      #
# OpenCMP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied        #
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more  #
# details.                                                                                                             #
#                                                                                                                      #
# You should have received a copy of the GNU Lesser General Public License along with OpenCMP. If not, see             #
# <https://www.gnu.org/licenses/>.                                                                                     #
########################################################################################################################

from .expanded_config_parser import ConfigParser
from ngsolve import CoefficientFunction, GridFunction, Mesh, Parameter
from os import path
from typing import Dict, Union, Optional, List
from .load_config import parse_str


[docs]class ConfigFunctions: """ Class to hold any functions from the config files. """ def __init__(self, config_rel_path: str, import_dir: str, mesh: Mesh, t_param: List[Parameter], new_variables: List[Dict[str, Union[float, CoefficientFunction, GridFunction]]] = [{}]) -> None: """ Initializer Args: config_rel_path: The filename, and relative path, for the config file for this controller. import_dir: The path to the main run directory containing the file from which to import any Python functions. t_param: List of parameters representing the current time and previous time steps. new_variables: List of dictionaries containing any new model variables and their values at each time step used in the time discretization scheme. """ # Set the run directory for the config functions. # Files could get accessed at run_dir + '/' + <path>. Make sure that if the config file is in the current # directory run_dir is specified such that this will still work. if '/' in config_rel_path: idx = config_rel_path[::-1].index('/') self.run_dir = config_rel_path[:len(config_rel_path) - idx - 1] else: self.run_dir = '.' # Load the config file. self.config = ConfigParser(config_rel_path) # Check if the config parser is empty. If it is that might be because the file doesn't exist, in which case # raise an error. Alternatively it might just mean that the file is empty because it doesn't need to be used. if self.config == []: if not path.exists(config_rel_path): raise FileNotFoundError('File {} does not exist.'.format(config_rel_path)) # Set the time parameter. self.t_param = t_param # Set the import file path. self.import_dir = import_dir
[docs] def _find_rel_path_for_file(self, file_name: str) -> str: """ Function to check if a file exists, returning a relative path to it. Args: file_name: The name of the file. Returns: The path to the file, relative to the run directory. """ # Check current working directory. if not path.isfile(file_name): # Check the specific run directory. if not path.isfile(self.run_dir + '/' + file_name): # Check the main run directory. if not path.isfile(self.run_dir + '/../' + file_name): raise FileNotFoundError('The given file does not exist.') else: rel_file_path = self.run_dir + '/../' + file_name else: rel_file_path = self.run_dir + '/' + file_name else: rel_file_path = file_name return rel_file_path
[docs] def re_parse(self, param_dict: Dict[str, Union[str, float, CoefficientFunction, GridFunction, list]], re_parse_dict: Dict[str, str], t_param: Optional[List[Parameter]], updated_variables: List[Dict[str, Union[int, str, float, CoefficientFunction, GridFunction]]], mesh: Mesh) -> Dict: """ Iterates through a parameter dictionary and re-parses any expressions containing model variables to use the updated values of those variables. Args: param_dict: The parameter dictionary to update. re_parse_dict: Dictionary containing only the parameters that need to be re-parsed and their string expressions. t_param: List of parameters representing the current time and previous time steps. If None, the re-parsed values have no possible time dependence and one single value is returned instead of a list of values corresponding to the re-parsed value at each time step. mesh: Mesh used by the model updated_variables: List of dictionaries containing any new model variables and their values at each time step used in the time discretization scheme. Returns: The updated parameter dictionary. """ for key, val in re_parse_dict.items(): if callable(val): # Need t_param to actually be a list of time parameters to be able to call an imported Python function. assert t_param is not None # The expression is an imported Python function, so just re-evaluate it with the new time and model # variable values. param_dict[key] = [val(t_param, updated_variables, mesh, i) for i in range(len(t_param))] else: # Re-parse the string expression and use to replace the parameter value in dict. re_parse_val, variable_eval = parse_str(val, self.import_dir, t_param, updated_variables, mesh=mesh) param_dict[key] = re_parse_val return param_dict