module Drasil.PDController.ODEs where

import Language.Drasil.Code (odeInfo, odeOptions, quantvar, ODEInfo,
    ODEMethod(RK45), ODEOptions)
import Language.Drasil.CodeExpr

import Data.Drasil.Quantities.Physics (time)
import Drasil.PDController.Unitals (qdSetPointTD, qdPropGain, qdDerivGain,
    qdSimTime, ipSetPt, ipDerivGain, ipPropGain, opProcessVariable,
    qdStepTime, odeRelTolConst, odeAbsTolConst)


pidODEOptions :: ODEOptions
pidODEOptions :: ODEOptions
pidODEOptions
  = ODEMethod
-> CodeExpr -> CodeExpr -> CodeExpr -> CodeExpr -> ODEOptions
odeOptions ODEMethod
RK45 (ConstQDef -> CodeExpr
forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy ConstQDef
odeAbsTolConst) (ConstQDef -> CodeExpr
forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy ConstQDef
odeRelTolConst) (QuantityDict -> CodeExpr
forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy QuantityDict
qdStepTime) (Integer -> CodeExpr
forall r. LiteralC r => Integer -> r
exactDbl 0)

-- This is a second order ODE. The equation should be in the form of
-- variable substitution, i.e. u = y'. However here the the equation
-- can be defined in terms of the dependent variable itself because of the 
-- way scipy expects the function in python. 
pidODEInfo :: ODEInfo
pidODEInfo :: ODEInfo
pidODEInfo
  = CodeVarChunk
-> CodeVarChunk
-> [CodeVarChunk]
-> CodeExpr
-> CodeExpr
-> CodeExpr
-> [CodeExpr]
-> ODEOptions
-> ODEInfo
odeInfo (UnitalChunk -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar UnitalChunk
time) (ConstrConcept -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar ConstrConcept
opProcessVariable)
      [ConstrConcept -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar ConstrConcept
ipPropGain, ConstrConcept -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar ConstrConcept
ipDerivGain, ConstrConcept -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar ConstrConcept
ipSetPt]
      (Integer -> CodeExpr
forall r. LiteralC r => Integer -> r
exactDbl 0)
      (QuantityDict -> CodeExpr
forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy QuantityDict
qdSimTime)
      (Integer -> CodeExpr
forall r. LiteralC r => Integer -> r
exactDbl 0)
      [CodeExpr -> CodeExpr -> CodeExpr
forall r. ExprC r => r -> r -> r
idx (ConstrConcept -> CodeExpr
forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy ConstrConcept
opProcessVariable) (Integer -> CodeExpr
forall r. LiteralC r => Integer -> r
int 1),
      CodeExpr -> CodeExpr
forall r. ExprC r => r -> r
neg ((Integer -> CodeExpr
forall r. LiteralC r => Integer -> r
exactDbl 1 CodeExpr -> CodeExpr -> CodeExpr
forall r. ExprC r => r -> r -> r
`addRe` QuantityDict -> CodeExpr
forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy QuantityDict
qdDerivGain) CodeExpr -> CodeExpr -> CodeExpr
forall r. ExprC r => r -> r -> r
`mulRe` CodeExpr -> CodeExpr -> CodeExpr
forall r. ExprC r => r -> r -> r
idx (ConstrConcept -> CodeExpr
forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy ConstrConcept
opProcessVariable) (Integer -> CodeExpr
forall r. LiteralC r => Integer -> r
int 1))   -- ? CHECK: Seems like `neg` does not generate generate sufficient parentheses?
      CodeExpr -> CodeExpr -> CodeExpr
forall r. ExprC r => r -> r -> r
$- ((Integer -> CodeExpr
forall r. LiteralC r => Integer -> r
exactDbl 20 CodeExpr -> CodeExpr -> CodeExpr
forall r. ExprC r => r -> r -> r
`addRe` QuantityDict -> CodeExpr
forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy QuantityDict
qdPropGain) CodeExpr -> CodeExpr -> CodeExpr
forall r. ExprC r => r -> r -> r
`mulRe` CodeExpr -> CodeExpr -> CodeExpr
forall r. ExprC r => r -> r -> r
idx (ConstrConcept -> CodeExpr
forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy ConstrConcept
opProcessVariable) (Integer -> CodeExpr
forall r. LiteralC r => Integer -> r
int 0))
      CodeExpr -> CodeExpr -> CodeExpr
forall r. ExprC r => r -> r -> r
`addRe` (QuantityDict -> CodeExpr
forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy QuantityDict
qdSetPointTD CodeExpr -> CodeExpr -> CodeExpr
forall r. ExprC r => r -> r -> r
`mulRe` QuantityDict -> CodeExpr
forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy QuantityDict
qdPropGain)]
      ODEOptions
pidODEOptions