class AlgebraicBlock(ModelElementBlock): __var = VariableNames() def __init__(self, *args, **kwargs): super().__init__(class_name='model_algebraic') @property def fixed(self): fix_from_traj = [] for alg in self.algebraics.values(): if alg.data is not None: fix_from_traj.append( [self.__var.algebraic, alg.name, alg.data]) return fix_from_traj @property def steps(self): steps = {} for alg in self.algebraics.values(): if alg.step is not None: steps[alg.name] = alg return steps
def __init__(self, reaction_models): #super(MultipleExperimentsEstimator, self).__init__() self.reaction_models = reaction_models self.experiments = list(self.reaction_models.keys()) self._idx_to_variable = dict() self.variances = { name: model.variances for name, model in self.reaction_models.items() } self.make_sublist() self._n_meas_times = 0 self._n_meas_lambdas = 0 self._n_actual = 0 self._n_params = 0 self._spectra_given = True self._concentration_given = False self.global_params = None self.parameter_means = False self.__var = VariableNames()
def __init__(self, model): """It takes in a standard Kipet/Pyomo model, rewrites it and calls fe_factory. More information on fe_factory is included in that class description. Args: model (ConcreteModel): Pyomo model passed from KIPET """ super(FESimulator, self).__init__(model) # KIPET variables self.__var = VariableNames() self.p_sim = PyomoSimulator(model) self.model = self.p_sim.model self.param_dict = {} self.param_name = self.__var.model_parameter # setattr(self.model, 'test_var', Var(self.model.alltime, # [0], # initialize=1.0)) # print(self.model.test_var.display()) self.c_sim = self.model.clone() # Check all parameters are fixed before simulating for param_obj in getattr(self.model, self.__var.model_parameter).values(): if not param_obj.fixed: param_obj.fixed = True # Build the parameter dictionary in the format that fe_factory uses model_var = self.__var.model_parameter for k, v in getattr(self.model, model_var).items(): self.param_dict[model_var, k] = v.value #Build the initial condition dictionary in the format that fe_factory uses vars_to_init = [ self.__var.concentration_model, self.__var.state_model, ] self.ics_ = {} for var in vars_to_init: self._var_init(var)
def __init__(self, model): """Simulator constructor. Note: Makes a shallow copy to the model. Changes applied to the model within the simulator are applied to the original model passed to the simulator Args: model (Pyomo model) """ self.__var = VariableNames() super(PyomoSimulator, self).__init__(model) self._alltimes = sorted( self.model.alltime) #added for special structure CS #self._times = sorted(self.model.time) self._n_alltimes = len(self._alltimes) #added for special structure CS #self._n_times = len(self._times) self._meas_times = sorted(self.model.meas_times) self._allmeas_times = sorted(self.model.allmeas_times) self._ipopt_scaled = False self._spectra_given = hasattr(self.model, self.__var.spectra_data) self._concentration_given = hasattr( self.model, self.__var.concentration_measured) or hasattr( self.model, self.__var.user_defined) or hasattr( self.model, self.__var.state) self._conplementary_states_given = hasattr(self.model, self.__var.state) self._absorption_given = hasattr( self.model, self.__var.spectra_species ) # added for special case of absorption data available but not concentration data CS self._huplc_given = hasattr(self.model, 'Chat') self._smoothparam_given = hasattr(self.model, self.__var.smooth_parameter) # creates scaling factor suffix if not hasattr(self.model, 'scaling_factor'): self.model.scaling_factor = Suffix(direction=Suffix.EXPORT)
""" Helper functions for making KIPET models """ from kipet.top_level.variable_names import VariableNames __var = VariableNames() def step_fun(model, time_var, num='0', coeff=1, time=1e-3, fixed=True, switch=False, M=1, eta=1e-2, constant=0.5): """This formulates the step functions for KIPET using a sigmoidal function Args: model: The ConcreteModel using the step function time_var (float): Time point for step num (str): The name of the step function coeff (float): Coefficient for the step size time (float): The time for the step change (init if not fixed)
def __init__(self, model_orig, src_mod, init_con=None, param_name=None, param_values=None, inputs=None, inputs_sub=None, jump_times=None, jump_states=None): """ The `the paran name` might be a list of strings or a single string corresponding to the parameters of the model. The `param_values` dictionary needs to be declared with the following syntax: `param_dict["P", "k0"] = 49.7796` Where the first key corresponds to one of the parameter names, and the second to the corresponding index (if any). A similar structure is expected for the initial conditions and inputs. The `inputs` and `input_sub` parameters are in place depending of whether there is a single index input or a multiple index input. Note that if the user does not provide correct information to fe_factory; an exception will be thrown because of the n_var and m_eqn check for simulation. Once the constructor is called, one can initialize the model with the following sintax: `self.load_initial_conditions(init_cond=ics_dict)` Finally, to run the initialization and automatic data patching to tgt model use: `self.run()` If a given finite element problem fails, we do will try once again with relaxed options. It is recommended to go back and check the model for better understanding of the issue. Finally, an explicit function of time on the right hand side is prohibited. Please put this information into an input (fixed variable) instead. Args: tgt_mod (ConcreteModel): The originall fully discretized model that we want to patch the information to. src_mod (ConcreteModel): The undiscretized reference model. init_con (str): The initial constraint name (corresponds to a Constraint object). param_name (list): The param name list. (Each element must correspond to a pyomo Var) param_values (dict): The corresponding values: `param_dict["param_name", "param_index"] = 49.7796` inputs (dict): The input dictionary. Use this dictonary for single index (time) inputs inputs_sub (dict): The multi-index dictionary. Use this dictionary for multi-index inputs. """ # This is a huge __init__ ==> offload to methods self.__var = VariableNames() self.ip = SolverFactory('ipopt') self.ip.options['halt_on_ampl_error'] = 'yes' self.ip.options['print_user_options'] = 'yes' self.model_orig = model_orig self.model_ref = src_mod.clone() time_index = None for i in self.model_ref.component_objects(ContinuousSet): time_index = i break if time_index is None: raise Exception('no continuous_set') self.time_set = time_index.name model_original_time_set = getattr(self.model_orig, self.time_set) self.ncp = model_original_time_set.get_discretization_info()['ncp'] fe_l = model_original_time_set.get_finite_elements() self.fe_list = [fe_l[i + 1] - fe_l[i] for i in range(0, len(fe_l) - 1)] self.nfe = len(self.fe_list) #: Re-construct the model with [0,1] time domain times = getattr(self.model_ref, self.time_set) change_continuous_set(times, [0, 1]) for var in self.model_ref.component_objects(Var): var.clear() var.reconstruct() for con in self.model_ref.component_objects(Constraint): con.clear() con.construct() # self.model_ref.display(filename="selfmoddisc0.txt") #: Discretize d = TransformationFactory('dae.collocation') d.apply_to(self.model_ref, nfe=1, ncp=self.ncp, scheme='LAGRANGE-RADAU') #: Find out the differential variables self.dvs_names = [] self.dvar_names = [] for con in self.model_ref.component_objects(Constraint): name = con.name namel = name.split('_', 1) if len(namel) > 1: if namel[1] == "disc_eq": realname = getattr(self.model_ref, namel[0]) self.dvar_names.append(namel[0]) self.dvs_names.append(realname.get_state_var().name) self.model_ref.h_i = Param(times, mutable=True, default=1.0) #: Length of finite element #: Modify the collocation equations to introduce h_i (the length of finite element) for i in self.dvar_names: con = getattr(self.model_ref, i + '_disc_eq') dv = getattr(self.model_ref, i) e_dict = {} fun_tup = True for k in con.keys(): if isinstance(k, tuple): pass else: k = (k, ) fun_tup = False e = con[k].expr.args[0] e_dict[k] = e * self.model_ref.h_i[k[0]] + dv[k] * ( 1 - self.model_ref.h_i[k[0]] ) == 0.0 #: As long as you don't clone if fun_tup: self.model_ref.add_component( i + "_deq_aug", Constraint(con.index_set(), rule=lambda m, *j: e_dict[j] if j[0] > 0.0 else Constraint.Skip)) else: self.model_ref.add_component( i + "_deq_aug", Constraint(con.index_set(), rule=lambda m, j: e_dict[j] if j > 0.0 else Constraint.Skip)) self.model_ref.del_component(con) #: Sets for iteration #: Differential variables self.remaining_set = {} for i in self.dvs_names: dv = getattr(self.model_ref, i) if dv.index_set().name == times.name: #: Just time set #print(i, 'here') self.remaining_set[i] = None continue #set_i = dv._implicit_subsets #: More than just time set #set_i = dv._index._implicit_subsets #Update for pyomo 5.6.8 KH.L set_i = identify_member_sets(dv) # set_i = identify_member_sets(dv.index_set()) #print(f'set_i = {set_i}') remaining_set = set_i[1] for s in set_i[2:]: remaining_set *= s if isinstance(remaining_set, list): self.remaining_set[i] = remaining_set else: self.remaining_set[i] = [] self.remaining_set[i].append(remaining_set) #: Algebraic variables self.weird_vars = [] #:Not indexed by time self.remaining_set_alg = {} # with open('model_check.txt', 'w') as f5: # self.model_ref.pprint(ostream = f5) for av in self.model_ref.component_objects(Var): # print(av.name) if av.name in self.dvs_names: continue if av.index_set().name == times.name: #: Just time set self.remaining_set_alg[av.name] = None continue #set_i = av._implicit_subsets #set_i = av._index._implicit_subsets #Update for pyomo 5.6.8 KH.L set_i = identify_member_sets(av) if set_i is None or not times in set_i: self.weird_vars.append(av.name) #: Not indexed by time! continue #: if this happens we might be in trouble remaining_set = set_i[1] #: Index by time and others for s in set_i[2:]: if s.name == times.name: self.remaining_set_alg[av.name] = None continue else: remaining_set *= s if isinstance(remaining_set, list): self.remaining_set_alg[av.name] = remaining_set else: self.remaining_set_alg[av.name] = [] self.remaining_set_alg[av.name].append(remaining_set) if init_con is not None: #: Delete the initial conditions (we use .fix() instead) ic = getattr(self.model_ref, init_con) self.model_ref.del_component(ic) if isinstance(param_name, list): #: Time independent parameters if param_values: if isinstance(param_values, dict): for pname in param_name: p = getattr(self.model_ref, pname) for key in p.keys(): try: val = param_values[pname, key] p[key].set_value(val) except KeyError: raise Exception( "Missing a key of the param_values\n" "Please provide all the required keys.\n" "missing: {}".format(key)) p[key].fix() else: Exception( "Arg param_values should be provided in a dictionary") else: Exception( "Arg param_values should be provided in a dictionary") elif isinstance(param_name, str): if param_values: if isinstance(param_values, dict): p = getattr(self.model_ref, param_name) for key in p.keys(): try: val = param_values[param_name, key] p[key].set_value(val) except KeyError: raise Exception( "Missing a key of the param_values\n" "Please provide all the required keys.\n" "missing: {}".format(key)) p[key].fix() elif not param_name: pass else: raise Exception("wrong type for param_name") #: Fix initial conditions for i in self.dvs_names: dv = getattr(self.model_ref, i) if self.remaining_set[i] is None: dv[0].fix() for rs in self.remaining_set[i]: for k in rs: k = k if isinstance(k, tuple) else (k, ) dv[(0, ) + k].fix() self.inputs = None self.input_remaining_set = {} #: Check if inputs are declared # if self.inputs is not None: # if not isinstance(inputs, dict) or isinstance(inputs, str): # raise Exception("Must be a dict or str") # if isinstance(inputs, str): # self.inputs = [self.inputs] # for i in self.inputs: # p = getattr(self.model_ref, i) # p.fix() # if p.index_set().name == times.name: #: Only time-set # self.input_remaining_set[i] = None # continue # #set_i = p._implicit_subsets # #set_i = p._index._implicit_subsets #Update for pyomo 5.6.8 KH.L # set_i = identify_member_sets(p) # if not times in set_i: # raise RuntimeError("{} is not by index by time, this can't be an input".format(i)) # remaining_set = set_i[1] # for s in set_i[2:]: # if s.name == times.name: #: would this ever happen? # continue # else: # remaining_set *= s # if isinstance(remaining_set, list): # self.input_remaining_set[i] = remaining_set # else: # self.input_remaining_set[i] = [] # self.input_remaining_set[i].append(remaining_set) #self.inputs_sub = None # inputs_sub['some_var'] = ['index0', 'index1', ('index2a', 'index2b')] self.inputs_sub = inputs_sub #print(times.name) #print([i.name for i in get_index_sets(getattr(self.model_ref, 'Dose'))]) #print(times.display()) if self.inputs_sub is not None: for key in self.inputs_sub.keys(): model_var_obj = getattr(self.model_ref, key) # This finds the index of the set # if identify_member_sets(model_var_obj) is None: # raise RuntimeError("This variable is does not have multiple indices" # "Pass {} as part of the inputs keyarg instead.".format(key)) # elif model_var_obj.index_set().name == times.name: # raise RuntimeError("This variable is indexed over time" # "Pass {} as part of the inputs keyarg instead.".format(key)) # else: # if times not in identify_member_sets(model_var_obj): # raise RuntimeError("{} is not indexed over time; it can not be an input".format(key)) for k in self.inputs_sub[key]: if isinstance(k, str) or isinstance(k, int) or isinstance( k, tuple): k = (k, ) if not isinstance(k, tuple) else k else: raise RuntimeError("{} is not a valid index".format(k)) for t in times: model_var_obj[(t, ) + k].fix() if hasattr(self.model_ref, self.__var.time_step_change): for time_step in getattr(self.model_ref, self.__var.time_step_change): getattr(self.model_ref, self.__var.time_step_change)[time_step].fix() if hasattr(self.model_ref, self.__var.model_constant): for param, obj in getattr(self.model_ref, self.__var.model_constant).items(): obj.fix() # : Check n vars and m equations (n, m) = reconcile_nvars_mequations(self.model_ref) if n != m: raise Exception("Inconsistent problem; n={}, m={}".format(n, m)) self.jump = False
class Comp(): var = VariableNames() def __init__(self, model, constant_info=None): self._model = model self._model_vars = self.var.model_vars self._rate_vars = self.var.rate_vars self.constant_info = constant_info self.var_dict = {} self.var_unit_dict = {} self.assign_vars() self.assign_rate_vars() def assign_vars(self): """Digs through and assigns the variables as top-level attributes """ list_of_vars = self._model_vars for mv in list_of_vars: if hasattr(self._model, mv): mv_obj = getattr(self._model, mv) index_sets = get_index_sets(mv_obj) dim = len(index_sets) if dim > 1: indx = 1 else: indx = 0 comp_set = list(index_sets[indx].keys()) for comp in comp_set: comp = str(comp) if isinstance(comp, str): if isinstance(comp[0], int): comp.insert(0, 'y') comp_name = comp for k, v in string_replace_dict.items(): comp_name.replace(k, v) self.var_dict[comp_name] = ModalVar( comp_name, comp_name, mv, self._model) if dim > 1: setattr(self, comp_name, mv_obj[0, comp]) else: setattr(self, comp_name, mv_obj[comp]) def assign_rate_vars(self): for mv in self._rate_vars: if hasattr(self._model, mv): mv_obj = getattr(self._model, mv) index_sets = get_index_sets(mv_obj) comp_set = list(index_sets[-1].keys()) dim = len(index_sets) for comp in comp_set: if isinstance(comp, str): comp_name = comp comp_name.replace(' ', '_') elif isinstance(comp, int): comp_name = f'y{comp}' comp_name = f'd{comp_name}dt' self.var_dict[comp_name] = ModalVar( comp_name, str(comp), mv, self._model) if dim > 1: setattr(self, comp_name, mv_obj[0, comp]) else: setattr(self, comp_name, mv_obj[comp]) def _id(self, comp): id_ = id(getattr(self, comp)) print(id_) return id_ @property def get_var_list(self): return list(self.var_dict.keys()) # class Comp_Check(): # var = VariableNames() # def __init__(self, model, param_list): # self._model = model # self._param_list = param_list # self.var_dict = {} # self.assign_params_for_units_check() # def assign_params_for_units_check(self): # """Digs through and assigns the variables as top-level attributes # """ # m = self._model # for var in self._param_list: # if hasattr(m, var): # var_obj = getattr(m, var) # self.var_dict[var] = var_obj # setattr(self, var, var_obj) # def get_unit_model(element_dict, set_up_model): # """Takes a ReactionModel instance and returns a Comp_Check object # representing the model's varialbes with units # """ # unit_model = ConcreteModel() # new_params = set() # for elem, comp_block in element_dict.items(): # if len(comp_block) > 0: # for comp in comp_block: # new_params.add(comp.name) # m_units = comp.units # if m_units is None: # m_units = str(1) # else: # m_units = getattr(u, str(m_units)) # print(m_units) # print(type(m_units)) # setattr(unit_model, comp.name, Var(initialize=1, units=m_units)) # c_units = Comp_Check(unit_model, list(new_params)) # return c_units