Source code for despasito.parameter_fitting.interface

""" Interface needed to create further objects to represent experimental data.
"""

# All folders in this directory refer back to this interface
import numpy as np
import logging
from abc import ABC, abstractmethod

logger = logging.getLogger(__name__)


[docs] class ExpDataTemplate(ABC): r""" Interface needed to create further objects to represent experimental data. Parameters ---------- data_dict : dict Dictionary of exp data * calculation_type (str) - Optional, default=*to be set* * MultiprocessingObject (obj) - Optional, Initiated :class:`~despasito.utils.parallelization.MultiprocessingJob` * eos_obj (obj) - Equation of state object * weights (dict) - A dictionary where each key is the header used in the exp. data file. The value associated with a header can be a list as long as the number of data points to multiply by the objective value associated with each point, or a float to multiply the objective value of this data set. * density_opts (dict) - Optional, default={}, Dictionary of options used in calculating pressure vs. mole fraction curves. * Allowed property keys and associated values * kwargs for :func:`~despasito.parameter_fitting.fit_functions.obj_function_form` Attributes ---------- name : str Data type, name of module, "To be set" Eos : obj Equation of state object weights : dict, Optional, default: {"some_property": 1.0 ...} Dictionary corresponding to thermo_dict, with weighting factor or vector for each system property used in fitting obj_opts : dict Keywords to compute the objective function with :func:`~despasito.parameter_fitting.fit_functions.obj_function_form`. npoints : int Number of sets of system conditions this object computes thermodict : dict Dictionary of inputs needed for thermodynamic calculations - calculation_type (str) default=*to be set* - density_opts (dict) default={} """ def __init__(self, data_dict): # Self interaction parameters self.name = "To be set" if "eos_obj" in data_dict: self.Eos = data_dict["eos_obj"] del data_dict["eos_obj"] else: raise ValueError("An Eos object should have been included") if "weights" in data_dict: self.weights = data_dict["weights"] del data_dict["weights"] else: self.weights = {} self.obj_opts = {} if "objective_method" in data_dict: self.obj_opts["method"] = data_dict["objective_method"] del data_dict["objective_method"] fitting_opts = ["nan_number", "nan_ratio"] for key in fitting_opts: if key in data_dict: self.obj_opts[key] = data_dict[key] del data_dict[key] logger.info("Objective function options: {}".format(self.obj_opts)) self.npoints = np.nan # Add to thermo_dict self.thermodict = {"calculation_type": None} thermo_dict_keys = ["MultiprocessingObject", "density_opts", "calculation_type"] for key in thermo_dict_keys: if key in data_dict: self.thermodict[key] = data_dict[key] del data_dict[key]
[docs] def update_parameters(self, fit_bead, param_names, param_values): r""" Update a single parameter value during parameter fitting process. To refresh those parameters that are dependent on to bead_library or cross_library, use method "parameter refresh". Parameters ---------- fit_bead : str Name of bead being fit param_names : list Parameters to be fit. See EOS documentation for supported parameter names. Cross interaction parameter names should be composed of parameter name and the other bead type, separated by an underscore (e.g. epsilon_CO2). param_values : list Value of parameter """ for i, param in enumerate(param_names): bead_names = [fit_bead] fit_parameter_names_list = param.split("_") param = fit_parameter_names_list[0] if len(fit_parameter_names_list) > 1: bead_names.append(fit_parameter_names_list[1]) if len(fit_parameter_names_list) == 1: self.Eos.update_parameter(fit_parameter_names_list[0], [fit_bead], param_values[i]) elif len(fit_parameter_names_list) == 2: self.Eos.update_parameter( fit_parameter_names_list[0], [fit_bead, fit_parameter_names_list[1]], param_values[i], ) else: raise ValueError( "Parameters for only one bead are allowed to be fit. Multiple " "underscores in a parameter name suggest more than one bead type " "in your fit parameter name, {}".format(param) ) if hasattr(self.Eos, "parameter_refresh"): self.Eos.parameter_refresh()
[docs] @abstractmethod def objective(self): """Float representing objective function of from comparing predictions to experimental data.""" pass
def __str__(self): string = "Data Set Object\nName: {}\nCalculation_type: {}\nNumber of " "Points: {}".format( self.name, self.thermodict["calculation_type"], self.npoints ) return string