B u `g@sjddlZddlmZddlmZddlmZmZddlm Z ddl m Z m Z ddl mZmZmZmZddlmZmZmZdd lmZdd lmZdd lmZdd lmZdd lmZddlmZddlmZddlmZddlm Z ddl!m"Z"m#Z#m$Z$m%Z%e&dZ'ddZ(ddZ)ddZ*ddZ+ddZ,ddZ-d*d!d"Z.d#d$Z/e j0d%d&d'Gd(d)d)e Z1dS)+N)xrange)next)numpynumpy_available) ComponentSet)TransformationTransformationFactory)VarConstraintList Expression Objective) ContinuousSet DerivativeVarIntegral)generate_finite_elements)generate_colloc_points)expand_components)create_partial_expression)add_discretization_equations)add_continuity_equations)block_fully_discretized)get_index_information) DAE_Error) ConfigBlock ConfigValue PositiveIntInz pyomo.daecs.ddfdd}|S)Nncpadotcsft|ddkr&td|}|dtfddtdDS)Nrzlist index out of rangec3sF|]>}||dVqdS)g?N).0j)ridxlowidxrtmpvr 5sz:_lagrange_radau_transform.._fun..)listord IndexErrorget_lower_element_boundarysumrange)ilow)rrsr&)r#r$r%r'_fun.s z'_lagrange_radau_transform.._fun)get_discretization_info)r&r1r2r )rrr1r&r'_lagrange_radau_transform*s   r4cs.ddfdd}|S)Nradotdotcsft|ddkr&td|}|dtfddtdDS)Nrrzlist index out of rangec3sJ|]B}||ddVqdS)g?Nr )r!r")r5r#r$rr%r&r r'r(FszA_lagrange_radau_transform_order2.._fun..)r)r*r+r,r-r.)r/r0)r5rr1r&)r#r$r%r'r2?s z._lagrange_radau_transform_order2.._fun)r3)r&r1r2r )r5rr1r&r' _lagrange_radau_transform_order2;s   r7cs.ddfdd}|S)Nrrcs|t|ddkr(tdn|kr._fun..)r)r*r+get_finite_elementsr,r-r.)r/r0)rrr1r&)r#r$r%r'r2Ps   z*_lagrange_legendre_transform.._fun)r3)r&r1r2r )rrr1r&r'_lagrange_legendre_transformLs  r9cs.ddfdd}|S)Nrr5cs|t|ddkr(tdn|kr._fun..)r)r*r+r8r,r-r.)r/r0)r5rr1r&)r#r$r%r'r2es   z1_lagrange_legendre_transform_order2.._fun)r3)r&r1r2r )r5rr1r&r'#_lagrange_legendre_transform_order2as  r:c Cst|dkst|dkr tdg}t|}t|}xt||dD]n}d}td||}t||}x@||kr||kr|||kr||||||7}|d7}qhW|||qFW|S)NrzCannot convolve an empty listr)len ValueErrorr.maxmininsert) abZansmnkvalr"stopr r r'convvs   rGc s,gtjj}xdt|dD]T|||||||}|||||}||qWg}xt|dD]dkr|qdg}d}x"|krt|ddg}|d7}qWx t|t|kr|ddqWfdd|D}ddt||D}qWt|} | S)Nrrcsg|]}|qSr r )r!t)gammar/r r' szcalc_cp..cSsg|] }t|qSr )r-)r!pairr r r'rKs) rmath factorialr.r?rGr;ziproots) alphabetarDrNnumZdenomZpolyprodr"cpr )rJr/r'calc_cps*     rVrc Csg}xtt|D]}g}d}xrtt|D]b}||kr.g}|dd|||||d|| ||||||||d7}q.Wdg}x&tt|dD]}t|||}qWt||} g} x.tt|D]}| tt| ||qW|| qW|S)Nrr) r.r;r?rGrZpolyderappendfloatpolyval) rUorderr@r/ptmpr%r"rowpZpderZarowr r r' calc_adots("   r^c Csg}xtt|D]}g}d}xrtt|D]b}||kr,g}|dd|||||d|| ||||||||d7}q,Wdg}x&tt|dD]}t|||}qW|t|dqW|S)Nrrg?)r.r;r?rGrWrrY)rUafinalr/r[r%r"r\r]r r r' calc_afinals "  r`zdae.collocationzmDiscretizes a DAE model using orthogonal collocation over finite elements transforming the model into an NLP.)docc seZdZedZedededdedededded ed d d d edededdgdddfddZ ddZ ddZ ddZ ddZ d"ddZd d!ZZS)#)Collocation_Discretization_Transformationzdae.collocationnfe zPThe desired number of finite element points to be included in the discretization)defaultdomain descriptionrzAThe desired number of collocation points over each finite elementwrtNz#The ContinuousSet to be discretizedzIndicates which ContinuousSet the transformation should be applied to. If this keyword argument is not specified then the same scheme will be applied to all ContinuousSets.)rergraschemezLAGRANGE-RADAUzLAGRANGE-LEGENDREz+Indicates which collocation scheme to applyzqOptions are 'LAGRANGE-RADAU' and 'LAGRANGE-LEGENDRE'. The default scheme is Lagrange polynomials with Radau roots)rerfrgracsPtt|i|_i|_i|_i|_i|_i|_i|_ t t ft t fd|_dS)N)zLAGRANGE-RADAUzLAGRANGE-LEGENDRE)superrb__init___ncp_nfe_adot_adotdot_afinal_tau _reduced_cpr4r7r9r: all_schemes)self) __class__r r'rlsz2Collocation_Discretization_Transformation.__init__c Cstsv|j|dkrtdddlm}m}m}||j||j|<||j||j|<||j||j |<d|j |<n|d}d}|j|d}t t t |||}|dd|dt|d} t|d } ||j|<| |j|<| |j |<d|j |<dS) z This function sets the radau collocation points and a values depending on how many collocation points have been specified and whether or not the user has numpy rdzENumpy was not found so the maximum number of collocation points is 10r)radau_tau_dictradau_adot_dictradau_adotdot_dictNrgg?r6)rrmr<pyomo.dae.utilitiesrwrxryrrrorprqsortedr)rVr?rWr^) ru currentdsrwrxryrQrRrDrUrr5r r r'_get_radau_constantss(        z>Collocation_Discretization_Transformation._get_radau_constantsc Csts|j|dkrtdddlm}m}m}m}||j||j|<||j||j |<||j||j |<||j||j |<nvd}d}|j|}t t t|||} | ddt| d} t| d} t| } | |j|<| |j |<| |j |<| |j |<dS) z This function sets the legendre collocation points and a values depending on how many collocation points have been specified and whether or not the user has numpy rdzENumpy was not found so the maximum number of collocation points is 10r)legendre_tau_dictlegendre_adot_dictlegendre_adotdot_dictlegendre_afinal_dictgrr6N)rrmr<rzr~rrrrrrorprqr{r)rVr?r^r`) rur|r~rrrrQrRrDrUrr5r_r r r'_get_legendre_constants=s(       zACollocation_Discretization_Transformation._get_legendre_constantscKs||}|j}|j}|j}|dk r^|jtk r8tdn&d|kr^td|d|j fd|j krptdt |j dkr|dkr||j d<||j d<d}n||j |j <||j |j <|j }|j |_|j|jd|_|jdkr||n|jdkr||||||S) a\ Applies specified collocation transformation to a modeling instance Keyword Arguments: nfe The desired number of finite element points to be included in the discretization. ncp The desired number of collocation points over each finite element. wrt Indicates which ContinuousSet the transformation should be applied to. If this keyword argument is not specified then the same scheme will be applied to all ContinuousSets. scheme Indicates which collocation scheme to apply. Options are 'LAGRANGE-RADAU' and 'LAGRANGE-LEGENDRE'. The default scheme is Lagrange polynomials with Radau roots. NzHThe component specified using the 'wrt' keyword must be a continuous setrjzQThe discretization scheme '%s' has already been applied to the ContinuousSet '%s'zA general discretization scheme has already been applied to to every ContinuousSet in the model. If you would like to specify a specific discretization scheme for one of the ContinuousSets you must discretize each ContinuousSet separately.rzLAGRANGE-RADAUzLAGRANGE-LEGENDRE)CONFIGrcrrictyper TypeErrorr3r<namernr;rmrj _scheme_namertget_schemer}r_transformBlock)ruinstancekwdsconfigZtmpnfeZtmpncpZtmpdsr|r r r' _apply_to`s:                z3Collocation_Discretization_Transformation._apply_tocCsi|_x|jtddD] }|dks0||jkrd|krJtd|jt||j||st |d|j|krt d|jt |d|j|j<t ||j|j<t ||j||}|j|j|d<|j||d<|j||d <|j||d <|j||d <|j||d <|j|d<qWt|x$|jtddD]}|}xt|D]}|dkst|j|krZ|}|j|} ||} | d krtd|j|jf|j| d} t| ||| } || |jdkrZt| ||| qZW|!rBt"| || #|t$t%|dd} | dkrHt |_&|j&} | '|qBWt(|r|)t*rx0|jt*ddD]}|+| #|t,q~Wx |jt-ddD]}|+qWdS)NT)Z descend_intorjzSAttempting to discretize ContinuousSet '%s' after it has already been discretized. rzMore finite elements were found in ContinuousSet '%s' than the number of finite elements specified in apply. The larger number of finite elements will be used.rcrZ tau_pointsrr5r_rhzError discretizing '%s' with respect to '%s'. Current implementation only allows for taking the first or second derivative with respect to a particular ContinuousSetzLAGRANGE-LEGENDRE&_pyomo_dae_reclassified_derivativevars)._feZcomponent_objectsr rr3rrrnZ get_changedr;loggerwarnr)rrrrmrorprqrrrZget_continuousset_listrZget_derivative_expressionZ get_state_varZ_contsetcountrrZset_derivative_expressionrZ parent_blockZis_fully_discretizedrZreclassify_component_typer getattrrrWrZcontains_componentrZ reconstructr r )rublockr|dsZ disc_infodZdsetsr/ZoldexprlocrrjZnewexprZreclassified_listrDr r r'rsr            z9Collocation_Discretization_Transformation._transformBlockc s |dkrtd|jtk r"td|}t|jdkr>tdn>d|jkrT|jd}n(|j|jkrn|j|j}ntd|jdkrtdjtk rtd|dkrtd |dkrtd ||krtd ||kr|S dkrt d |jjf }t |d s.||k rNt d |jjfn ||j krNt d |jjfj|jkr|jj}|j|kr~tdn |||j<n|j|i|jj<jd} || t|| } t|} |j} t|} | d}| dx|D]x tdt| dD]xtd||dD]}|dkrX| ||kn|| d}|| dd}| ||}| ||d|d}|||| |tfddt||d|dDkq"Wq WqW|S)aY This method will add additional constraints to a model to reduce the number of free collocation points (degrees of freedom) for a particular variable. Parameters ---------- instance : Pyomo model The discretized Pyomo model to add constraints to var : ``pyomo.environ.Var`` The Pyomo variable for which the degrees of freedom will be reduced ncp : int The new number of free collocation points for `var`. Must be less that the number of collocation points used in discretizing the model. contset : ``pyomo.dae.ContinuousSet`` The :py:class:`ContinuousSet` that was discretized and for which the `var` will have a reduced number of degrees of freedom Nz>A continuous set must be specified using the keyword 'contset'zKThe component specified using the 'contset' keyword must be a ContinuousSetrzXThis method should only be called after using the apply() method to discretize the modelzContinuousSet '%s' has not been discretized, please call the apply_to() method with this ContinuousSet to discretize it before calling this methodzA variable must be specifiedzBThe component specified using the 'var' keyword must be a variablez2The number of collocation points must be specifiedz3The number of collocation points must be at least 1zThe number of collocation points used to interpolate an individual variable must be less than the number used to discretize the original modelz>ContinuousSet '%s' is not an indexing set of the variable '%s' set_tuplezmVariable '%s' has already been constrained to a reduced number of collocation points over ContinuousSet '%s'.Z_interpolation_constraintsZnon_dszindex functionrc3s&|]}|tVqdS)N)r)r!r")coeffr/r#rCvarr r'r(zszVCollocation_Discretization_Transformation.reduce_collocation_points..)rrr r;rm RuntimeErrorrr<r Zdimr+Z index_sethasattrrrsZ local_nameZ add_componentr Zfind_componentr)rrraddr*_interpolation_coeffsr-)rurrrZcontsetrZtot_ncpZvaridxtempZ list_nameZconlistrIZfeinfoZtmpidxrDr%Ztmp2titfitr )rr/r#rCrr'reduce_collocation_pointss                      &zCCollocation_Discretization_Transformation.reduce_collocation_pointsccsFx@|D]8}d}x(|D] }||kr|||||}qW|VqWdS)Nrr )rurrr/lr"r r r'rs   z?Collocation_Discretization_Transformation._interpolation_coeffs)NNN)__name__ __module__ __qualname__rrZdeclarerrrrlr}rrrrr __classcell__r r )rvr'rbs4      #A` ~rb)r)2loggingZ six.movesrsixrZpyomo.common.dependenciesrrZpyomo.common.collectionsrZpyomo.core.baserrZ pyomo.corer r r r Z pyomo.daer rrZpyomo.dae.miscrrrrrrrrZpyomo.dae.diffvarrZpyomo.common.configrrrr getLoggerrr4r7r9r:rGrVr^r`registerrbr r r r' s:             9