B @`@sXddlmZmZmZmZmZddlmZmZddl m Z ddl m Z ddlmZddlmZmZddlmZddlZd Zed Zdd lmZmZmZddlZed kZ ed dgd\Z!Z"iZ#ddZ$ede$d\Z%Z&ddZ'ddZ(ddZ)ddZ*Gddde j+Z,ddZ-Gd d!d!e j+Z.Gd"d#d#e j/Z0d$d%Z1d&d'Z2Gd(d)d)Z3dS)*) ConstraintParamvalueSuffixBlock) ContinuousSet DerivativeVar) DAE_Error)current)native_numeric_types) IndexTemplate_GetItemIndexer)iterkeysN) Simulatorz pyomo.core)numpynumpy_availableattempt_importPyPyzscipy.integratescipy)Z alt_namescCs\|rXt|j|j|j|j|j|j|j|j |j |j |j |j |j|j|j|j|j|jddS)N)loglog10sincostancoshsinhtanhasinacosatanexpsqrtasinhacoshatanhceilfloor)casadi_intrinsicupdaterrrrrrrrrrrr r!r"r#r$r%r&)casadi availabler+7/tmp/pip-unpacked-wheel-bi3529v6/pyomo/dae/simulator.py_finalize_casadi-s(r-r))callbackcCs8t||dtkr0|||d|gSdSdS)a5 Accepts an equality expression and an index value. Checks the GetItemExpression at expr.arg(i) to see if it is a :py:class:`DerivativeVar`. If so, return the GetItemExpression for the :py:class:`DerivativeVar` and the RHS. If not, return None. rN)typeargr)exprir+r+r,_check_getitemexpressionFsr4c Cs||}|dfg}g}d}x|r|\}}|jtjkrd||d|f||d|fq|jtjkr||d|f||d| fq|jtjkr||d| fqt|tj krt|dt kr||f}q|||fqW|dkr dSd}d} x.|D]&\} }|dkr4| | 9} n|| 9}qW|\}}|dkrn||d||| gS|| |d||gSdS)aI Accepts an equality expression and an index value. Checks the ProductExpression at expr.arg(i) to see if it contains a :py:class:`DerivativeVar`. If so, return the GetItemExpression for the :py:class:`DerivativeVar` and the RHS. If not, return None. r/Nr) r1pop __class__EXPRProductExpressionappendDivisionExpressionReciprocalExpressionr0GetItemExpressionr) r2r3Zexpr_stackZptermsdvcurrZe_ZnumerZdenomZtermr+r+r,_check_productexpressionTs<           r@cCs||d}t|tjkrDt|dtkrD||d| gSt|tjkr|d}|d}t|tks~|r~dSt|tjkrt|dtksdS||d| |gSdS)aJ Accepts an equality expression and an index value. Checks the NegationExpression at expr.arg(i) to see if it contains a :py:class:`DerivativeVar`. If so, return the GetItemExpression for the :py:class:`DerivativeVar` and the RHS. If not, return None. rr/N)r1r0r7r<rr8r is_potentially_variable)r2r3r1lhsrhsr+r+r,_check_negationexpressions    rDc Cs||}g}d}d}xt|jD]\}}|dk r>||q"t|tjkrdt|dtkrd|}q"t|tjkr|d}|d} t|t ks| st| tjkrt| dtkr| }|}q"||q"W|dk r|d|} x|D] }| |8} qW| |} || gSdS)aF Accepts an equality expression and an index value. Checks the Sum expression at expr.arg(i) to see if it contains a :py:class:`DerivativeVar`. If so, return the GetItemExpression for the :py:class:`DerivativeVar` and the RHS. If not, return None. Nr/r) r1 enumerateargsr9r0r7r<rr8r rA) r2r3Zsumexpitemsr>ZdvcoefidxitemrBrCRHSr+r+r,_check_viewsumexpressions6        rKcs,eZdZdZfddZfddZZS)Pyomo2Scipy_Visitorzc Expression walker that replaces _GetItemExpression instances with mutable parameters. cstt|||_dS)N)superrL__init__ templatemap)selfrO)r6r+r,rNszPyomo2Scipy_Visitor.__init__cst|tkrd|fSt|tjkrt|}||jkr|tdd|j|<|j|d|jj d dd|j Df|j|_ d|j|fSt t||S)NT)Zmutablez%s[%s],css|]}t|VqdS)N)str).0xr+r+r, sz>Pyomo2Scipy_Visitor.visiting_potential_leaf..)r0r r7r<r rOrZ constructbasenamejoinrF_namerMrLvisiting_potential_leaf)rPnode_id)r6r+r,rZs  (z+Pyomo2Scipy_Visitor.visiting_potential_leaf)__name__ __module__ __qualname____doc__rNrZ __classcell__r+r+)r6r,rLs rLcCsts tdt|}||S)aESubstitute _GetItem nodes in an expression tree. This substition function is used to replace Pyomo _GetItem nodes with mutable Params. Args: templatemap: dictionary mapping _GetItemIndexer objects to mutable params Returns: a new expression tree with all substitutions done zDSciPy is not installed. Cannot substitute SciPy intrinsic functions.)scipy_availabler rLdfs_postorder_stack)r2rOvisitorr+r+r,convert_pyomo2scipys recs0eZdZdZfddZddZddZZS)Substitute_Pyomo2Casadi_Visitora Expression walker that replaces * _UnaryFunctionExpression instances with unary functions that point to casadi intrinsic functions. * _GetItemExpressions with _GetItemIndexer objects that references CasADi variables. cstt|||_dS)N)rMrfrNrO)rPrO)r6r+r,rN sz(Substitute_Pyomo2Casadi_Visitor.__init__cCs,t|tjkr(t|d|jt|jS|S)z(Replace a node if it's a unary function.r)r0r7ZUnaryFunctionExpressionrYr')rPr[valuesr+r+r,visits  z%Substitute_Pyomo2Casadi_Visitor.visitcCst|tjkrbt|}||jkrTd|jjddd|jDf}t j ||j|<d|j|fSt|t ks| rt|tkrd|fSdS)z,Replace a node if it's a _GetItemExpression.z%s[%s]rQcss|]}t|VqdS)N)rR)rSrTr+r+r,rUszJSubstitute_Pyomo2Casadi_Visitor.visiting_potential_leaf..T)FN)r0r7r<r rOrVrWrXrFr)SXsymr is_expression_typer )rPr[r\rWr+r+r,rZs    z7Substitute_Pyomo2Casadi_Visitor.visiting_potential_leaf)r]r^r_r`rNrhrZrar+r+)r6r,rfs   rfc@s eZdZdZddZddZdS)Convert_Pyomo2Casadi_Visitora Expression walker that evaluates an expression generated by the Substitute_Pyomo2Casadi_Visitor walker. In Coopr3 this walker was not necessary because the expression could be simply evaluated. But in Pyomo5, the evaluation logic was changed to be non-recursive, which involves checks on the types of leaves in the expression tree. Hence, the evaluation logic fails if leaves in the tree are not standard Pyomo5 variable types. cCs ||S)z% Visit nodes that have been expanded )Z_apply_operation)rPr[rgr+r+r,rh5sz"Convert_Pyomo2Casadi_Visitor.visitcCsR|jtkrd|fS|jtjkr&d|fS|r:dt|fS|sNdt|fSdS)z^ Visiting a potential leaf. Return True if the node is not expanded. T)FN)r6r r)riZis_variable_typerrk)rPr[r+r+r,rZ9s    z4Convert_Pyomo2Casadi_Visitor.visiting_potential_leafN)r]r^r_r`rhrZr+r+r+r,rl)s rlcCsts tdt|}||S)amSubstitute IndexTemplates in an expression tree. This substition function is used to replace Pyomo intrinsic functions with CasADi functions. Args: expr: a Pyomo expression templatemap: dictionary mapping _GetItemIndexer objects to mutable params Returns: a new expression tree with all substitutions done zUCASADI is not installed. Cannot substitute CasADi variables and intrinsic functions.)casadi_availabler rfrc)r2rOrdr+r+r,substitute_pyomo2casadiNsrncCsts tdt}||S)aConvert a Pyomo expression tree to Casadi. This function replaces a Pyomo expression with a CasADi expression. This assumes that the `substitute_pyomo2casadi` function has been called, so the Pyomo expression contains CasADi variables and intrinsic functions. The resulting expression can be used with the CasADi integrator. Args: expr: a Pyomo expression with CasADi variables and intrinsic functions Returns: a CasADi expression tree. zSCASADI is not installed. Cannot convert a Pyomo expression to a Casadi expression.)rmr rlrc)r2rdr+r+r,convert_pyomo2casadicsroc@sNeZdZdZdddZdddZddd Zd d Zd d ZddZ ddZ dS)rar Simulator objects allow a user to simulate a dynamic model formulated using pyomo.dae. Parameters ---------- m : Pyomo Model The Pyomo model to be simulated should be passed as the first argument package : `string` The Python simulator package to use. Currently 'scipy' and 'casadi' are the only supported packages rcs||_|jdkr&td|jddgf|jdkrPts@tdq\tr\tdn ts\tdtt |j t dd d r|td | t }t|d krtd t |d}t|| t}t |}t|drx|jD]}||jqWt|dkrtdiigg}x|jtddD]}d|jkr<q&|dkrNq&|} d} d} d} x^| D]R} | |kr| dkrtd|j| } n| dkr| } n | | } | | j7} qlW| dkrАq&| dkrd} |j}x| D]}|dkr||}n:t|ts|f}|d| f|| d}|||}t |t!j"k rVqd}t |#dt!j$krzt%|d}|dkrt |#d t!j$krt%|d }|dkrt |#dt!j&kst |#dt!j'kst |#dt!j(krt)|d}|dkrPt |#d t!j&ksFt |#d t!j'ksFt |#d t!j(krPt)|d }|dkrzt |#dt!j*krzt+|d}|dkrt |#d t!j*krt+|d }|dkrt |#dt!j,krt-|d}|dkrt |#d t!j,krt-|d }|dkrL|jdkr tdt.|j|#d|#d }t/|}||q|d}|d }t0|}|krtdt.|||jdkrt/||<nt1||<qWq&Wgx,D]$}|j23}t0||j4qWg}x|_?|_@|_A||_B||_C||_Dd|_Ed|_Fd|_Gd|_HdS)N)rr)z8Unrecognized simulator package %s. Please select from %srr)zuThe scipy module is not available. You may build the Simulator object but you will not be able to run the simulation.zThe scipy ODE integrators do not work in pypy. You may build the Simulator object but you will not be able to run the simulation.z:The casadi module is not available. Cannot simulate model.TF)activeZ descend_intoz>The Simulator cannot handle hierarchical models at the moment.r/zWCurrently the simulator may only be applied to Pyomo models with a single ContinuousSetr&_pyomo_dae_reclassified_derivativevarsz+Cannot simulate a model with no derivatives)rpZ_disc_eqzSCannot simulate the constraint %s because it is indexed by duplicate ContinuousSets)NzModel contains an algebraic equation or unrecognized differential equation. Constraint '%s' cannot be simulated using Scipy. If you are trying to simulate a DAE model you must use CasADi as the integration package.z7Found multiple RHS expressions for the DerivativeVar %szDCannot simulate a differential equation with multiple DerivativeVarscs`g}|x.tD]"\}}|kr|||qWxD]}||qDW|S)N) set_valuerEr9)trTZresidualrHvd) cstemplate derivlistdiffvarsrhsdictrOr+r,_rhsfun~s  z#Simulator.__init__.._rhsfunz%s[%s]rQcss|]}t|VqdS)N)rR)rSrTr+r+r,rUsz%Simulator.__init__..)I _intpackager rbloggerwarningis_pypyrm ValueErrorlenlistZcomponent_data_objectsrZ component_maprrgr rkeyshasattrrqr9rWZcomponent_objectsrZdimZ index_setZsubsetsZcrossZdimenZrule isinstancetupler0r7ZEqualityExpressionr1r<r4r8r;r:r@Z SumExpressionrKZNegationExpressionrDrRrnr rerVZ get_state_var_argsrr{rXrFr)rirj_contsetZ _cstemplate _diffvars _derivlist _templatemap_rhsdict_alglist_algvars_model_tsim _simsolution _simalgvars _siminputvars)rPmpackagetempZcontsetZderivsrvZalglistconZconindexZdimsumZcsidxZnoncsidxsZconruler3ZtempexpZtempidxrFZalgexpr>rJZdvkeyZderivsvZalgvarsrIr{r\rWr+)rwrxryrzrOr,rNs*                                                       zSimulator.__init__NcCs4|dkr|jS|dkr|jS|dkr*|jS|jSdS)au This function returns the ordered list of differential variable names. The order corresponds to the order being sent to the integrator function. Knowing the order allows users to provide initial conditions for the differential equations using a list or map the profiles returned by the simulate function to the Pyomo variables. Parameters ---------- vartype : `string` or None Optional argument for specifying the type of variables to return the order for. The default behavior is to return the order of the differential variables. 'time-varying' will return the order of all the time-dependent algebraic variables identified in the model. 'algebraic' will return the order of algebraic variables used in the most recent call to the simulate function. 'input' will return the order of the time-dependent algebraic variables that were treated as inputs in the most recent call to the simulate function. Returns ------- `list` z time-varyingZ algebraicinputN)rrrr)rPvartyper+r+r,get_variable_orderszSimulator.get_variable_ordercCsts td|dkri}|jdkrLdddddg}|dkr>d}qd|d krdd}nd d d d g}|dkrdd }||krtd|j||f|dk r||j|jkrtd||jf|dk r|dk rtd|dkr|dkrd}|dkr tj |j|j|d}nt |j|j|}g} i|_ g|_ |dk rt |tk rTtdxH|jD]>} | j|kr| || j7} | |j | j<n |j | q\W|jdkrt|j dkrtdtt| } | | d|jks| d|jkrtdt|| }n|j|_ |dk rtt|t|jkrLtdt|jt|t|jkrtdt|jng}x|jD]|} x(t| jD]\} } t | tkrPqW|j}t| jd| |ft| j| dd}|t| j|qW|jdkrBtstdt r(td|!||| |||\}}n:t| dkrh|"|||||\}}n|#||||\}}||_$||_%||gS)a= Simulate the model. Integrator-specific options may be specified as keyword arguments and will be passed on to the integrator. Parameters ---------- numpoints : int The number of points for the profiles returned by the simulator. Default is 100 tstep : int or float The time step to use in the profiles returned by the simulator. This is not the time step used internally by the integrators. This is an optional parameter that may be specified in place of 'numpoints'. integrator : string The string name of the integrator to use for simulation. The default is 'lsoda' when using Scipy and 'idas' when using CasADi varying_inputs : ``pyomo.environ.Suffix`` A :py:class:`Suffix` object containing the piecewise constant profiles to be used for certain time-varying algebraic variables. initcon : list of floats The initial conditions for the the differential variables. This is an optional argument. If not specified then the simulator will use the current value of the differential variables at the lower bound of the ContinuousSet for the initial condition. integrator_options : dict Dictionary containing options that should be passed to the integrator. See the documentation for a specific integrator for a list of valid options. Returns ------- numpy array, numpy array The first return value is a 1D array of time points corresponding to the second return value which is a 2D array of the profiles for the simulated differential and algebraic variables. z=The numpy module is not available. Cannot simulate the model.NrZvodeZzvodeZlsodaZdopri5Zdop853ZodeintZcvodesZidasZ collocationZrkzDUnrecognized %s integrator '%s'. Please select an integrator from %szCThe step size %6.2f is larger than the span of the ContinuousSet %szLCannot specify both the step size and the number of points for the simulatord)numzcVarying input values must be specified using a Suffix. Please refer to the simulator documentation.rzWhen simulating with Scipy you must provide values for all parameters and algebraic variables that are indexed by the ContinuoutSet using the 'varying_inputs' keyword argument. Please refer to the simulator documentation for more information.rrzvFound a switching point for one or more of the time-varying inputs that is not within the bounds of the ContinuousSet.z^Too many initial conditions were specified. The simulator was expecting a list with %i values.z]Too few initial conditions were specified. The simulator was expecting a list with %i values.r/z=The scipy module is not available. Cannot simulate the model.zLThe scipy ODE integrators do not work under pypy. Cannot simulate the model.)&rrr|r rlastfirstrWnpZlinspaceZarangerrr0r TypeErrorr_baserr9rrsetsortZunion1drrErr rrrbr_simulate_with_scipy!_simulate_with_casadi_with_inputs_simulate_with_casadi_no_inputsrr)rPZ numpointsZtstep integratorvarying_inputsinitconintegrator_optionsZvalid_integratorstsim switchptsalgrurHr3Z initpointvidxprofiler+r+r,simulates.                 zSimulator.simulatec Cst|jj|f|}|||dt|}d} x|r|j|dkr|| d|krxP|j D]B} || d|| krh|j |j | } | || || dqhW| || } t|| g}| d7} q6W|std|||gS)Nrr/rrz7The Scipy integrator %s did not terminate successfully.)roder{Zset_integratorZset_initial_valuerarrayZ successfulrtrrrrsZ integrateZvstackr ) rPrrrrrrZscipyintrr3rupZ profilestepr+r+r,rs$  zSimulator._simulate_with_scipycs fddjD}tj|}fddjD}tj|}||d} tjdkrfddjD} tj| } ddjD} tj| } | | d<| | d <||d <d |d <td || |}||d}|d j }tjdkr|d j }t j ||fdd}||gS)Ncsg|]}j|qSr+)r)rSr3)rPr+r, sz=Simulator._simulate_with_casadi_no_inputs..csg|]}tj|qSr+)ror)rSr3)rPr+r,rs)rTrrcsg|]}j|qSr+)r)rSr3)rPr+r,rscSsg|] }t|qSr+)ro)rSr3r+r+r,rszrZgridTZ output_t0F)x0xfzfr/)axis) rr)vertcatrrrrrrfullTr concatenate)rPrrrrxalltempxall odealltempodealldaezalltempzall algalltempalgallrsolr algprofiler+)rPr,rs,        z)Simulator._simulate_with_casadi_no_inputscs"fddjD}tj|}tjdfddjD}tj|} fddjD} tjf| } || | d} tj dkrԇfddj D} tj| }d dj D}tj|}|| d <|| d <d |d <t d|| |}t}t dddddg}dt|f|_t|g}xjD]~}||tfddDtdgdgfddttD} tj| }||q.timecsg|]}tj|qSr+)ror)rSr3)rPrr+r,rscsg|]}j|qSr+)r)rSr3)rPr+r,rs)rTrrrcsg|]}j|qSr+)r)rSr3)rPr+r,rscSsg|] }t|qSr+)ro)rSr3r+r+r,rsrrg?tfrr/rrcsg|]}|qSr+)Z searchsorted)rSr3)rr+r,rsc s2g|]*}t|d|d|qS)r/)r)Zrepmat)rSr3)rtidxtswitchr+r,rsZ simulator)rrrr)r)rr)rrirjrrrgrrrrrrZhstackshapeZDMrrrrangeZhorzcatr9Zmapaccumrrr)rPrrrrrrrrrZptempZpallrrrrrrNZtsimtempZpalltemprrIrrr+)rrPrrrrr,rsR         "    z+Simulator._simulate_with_casadi_with_inputsc Cs|jdkrtdt|j}|j|j}xt|D]\}}x$t|jD]\}}t|t krFPqFWt ||j|j dd|f}xPt|D]D\}}t |jd||ft |j|dd} |||j| <qWq2WdS)z This function will initialize the model using the profile obtained from simulating the dynamic model. Nz9Tried to initialize the model without simulating it firstrr/)rr rrrrrErr0r rZinterprrr) rPZtvalsZinitvarsrHruZidx2r3Zvalinitrtrr+r+r,initialize_models     zSimulator.initialize_model)r)N)NNNNNN) r]r^r_r`rNrrrrrrr+r+r+r,rzs   $ M!@r)4Zpyomo.core.baserrrrrZ pyomo.daerrZpyomo.dae.diffvarr Zpyomo.core.exprr r7Zpyomo.core.expr.numvaluer Zpyomo.core.expr.template_exprr r sixrlogging__all__ getLoggerr}Zpyomo.common.dependenciesrrrrplatformpython_implementationrrrbr'r-r)rmr4r@rDrKZExpressionReplacementVisitorrLrerfZExpressionValueVisitorrlrnrorr+r+r+r, s6      /.*%