[docs]defdegrees_of_freedom(point:Union[Point,Node],components:list[str],num_potential_conditions:int):""" Degrees of freedom of point defined by Gibbs phase rule Components + 2 = Phases + DOF 2 is offsetted by the number of potential conditions Parameters ---------- point : Point or Node components : [str] List of components, VA will be ignored num_potential_conditions : number of variable potential conditions Returns ------- int - degrees of freedom, 0 represents an invariant point/node """non_va_comps=len(set(components)-{"VA"})returnnon_va_comps+2-len(point.stable_composition_sets)-(2-num_potential_conditions)
[docs]defis_state_variable(var:v.StateVariable):""" Returns whether var is a state variable or not """returnisinstance(var,(v.IndependentPotential,v.SystemMolesType))
[docs]defupdate_cs_phase_frac(comp_set:CompositionSet,phase_frac:float):""" Wrapper to update the phase fraction of a composition set This just helps with splitting the cs.dof to state variables and constituents when updating Parameters ---------- comp_set : CompositionSet phase_frac : float """num_sv=comp_set.phase_record.num_statevarscomp_set.update(comp_set.dof[num_sv:],phase_frac,comp_set.dof[:num_sv])
[docs]defget_statevars_array(conditions:dict[v.StateVariable,float],state_variables:list[v.StateVariable]=None):""" Creates numpy array of state variables in conditions Parameters ---------- conditions : dict[v.StateVariable, float] Returns ------- numpy array of len(state variables) """# If no state variables is given, then grab them from conditionsifstate_variablesisNone:state_variables=sorted([keyforkeyinconditionsifis_state_variable(key)],key=str)returnnp.asarray([conditions[sv]forsvinstate_variables],dtype=np.float64)
def_sort_axis_by_state_vars(axis_vars:list[v.StateVariable]):""" Sorts list of axis variables by [state variables (N, P, T)] + [non-state variables] Parameters ---------- axis_vars : [v.StateVariable] Returns ------- sorted axis vars : [v.StateVariable] """state_vars=[avforavinaxis_varsifis_state_variable(av)]non_state_vars=[avforavinaxis_varsifnotis_state_variable(av)]returnstate_vars+non_state_varsdef_generate_point_with_fixed_cs(point:Point,cs_to_fix:CompositionSet,cs_to_free:CompositionSet):""" Generates point with two cs, one fixed and one free Parameters ---------- point : Point Point to generate new point from cs_to_fix : CompositionSet cs_to_free : CompositionSet Returns ------- new_point : Point Retains same equilibria as previous point Conditions will be updated with the updated phase fractions of the composition sets """new_point=Point.with_copy(point.global_conditions,point.chemical_potentials,[cs_to_fix],[cs_to_free])new_point._fixed_composition_sets[0].fixed=Trueupdate_cs_phase_frac(new_point._fixed_composition_sets[0],0.0)new_point._free_composition_sets[0].fixed=Falseupdate_cs_phase_frac(new_point._free_composition_sets[0],1.0)forkeyinnew_point.global_conditions:new_point.global_conditions[key]=new_point.get_property(key)returnnew_pointdef_generate_point_with_free_cs(point:Point,bias_towards_free:bool=False):""" Frees all composition sets in point and sets NP to 1/n for all CS If bias_towards_free, then all free cs in point will have a weight of 2 when normalizing phase fractions Parameters ---------- point : Point Point to generate new point from bias_towards_free : bool Whether to bias composition towards free phases of previous point Returns ------- new_point : Point Point will all composition sets free """phase_sum=0forcsinpoint.stable_composition_sets:ifbias_towards_free:phase_sum+=1ifcs.fixedelse2else:phase_sum+=1new_point=Point.with_copy(point.global_conditions,point.chemical_potentials,[],point.stable_composition_sets)forcsinnew_point._free_composition_sets:ifbias_towards_free:new_amt=1ifcs.fixedelse2update_cs_phase_frac(cs,new_amt/phase_sum)else:update_cs_phase_frac(cs,1/phase_sum)cs.fixed=Falseforkeyinnew_point.global_conditions:new_point.global_conditions[key]=new_point.get_property(key)returnnew_point