GARCH(1,1) MLE by Pyomo - python

import pyomo.environ as pyo
import numpy as np
def get_model_garch11mle(vec_retn: np.array) -> pyo.ConcreteModel:
mdl = pyo.ConcreteModel(name='GARCH11')
mdl.alpha_0 = pyo.Var(bounds=(1e-6,1), initialize=.4)
mdl.alpha_1 = pyo.Var(bounds=(1e-6,1), initialize=.4)
mdl.beta_1 = pyo.Var(bounds=(1e-6,1), initialize=.4)
mdl.T = range(len(vec_retn))
mdl.h_t = pyo.Expression(mdl.T)
for i in mdl.T:
if i == 0:
mdl.h_t[i] = pyo.Expression(expr=mdl.alpha_0 / (1 - mdl.alpha_1 - mdl.beta_1))
else:
mdl.h_t[i] = pyo.Expression(expr=mdl.alpha_0 + mdl.alpha_1 * (vec_retn[i - 1]**2) + mdl.beta_1 * mdl.h_t[i - 1])
mdl.obj = pyo.Objective(expr=sum([pyo.log(mdl.h_t[i]) + vec_retn[i]**2/mdl.h_t[i] for i in mdl.T]))
return mdl
vec_retn = np.random.randn(100)**2 /3 + np.random.randn(100)**3 /6
temp_mdl = get_model_garch11mle(vec_retn)
opt = pyo.SolverFactory('gurobi')
temp_res = opt.solve(temp_mdl)
In this snippet I need to update a seq of h[t] using variables (a0, a1, b1) and h[t-1]. Curious what's the proper way to write the problem for Pyomo?
Currently, I got:
ValueError: Accessing the expression of expression 'ScalarExpression'
before the Expression has been constructed (there is currently no value to return).
When removed redundant 'Expression()' as:
import pyomo.environ as pyo
import numpy as np
def get_model_garch11mle(vec_retn: np.array) -> pyo.ConcreteModel:
mdl = pyo.ConcreteModel(name='GARCH11')
mdl.alpha_0 = pyo.Var(bounds=(1e-6, 1), initialize=.4)
mdl.alpha_1 = pyo.Var(bounds=(1e-6, 1), initialize=.4)
mdl.beta_1 = pyo.Var(bounds=(1e-6, 1), initialize=.4)
mdl.T = range(len(vec_retn))
mdl.h_t = pyo.Expression(mdl.T)
for i in mdl.T:
if i == 0:
mdl.h_t[i] = mdl.alpha_0 / (1 - mdl.alpha_1 - mdl.beta_1)
else:
mdl.h_t[i] = mdl.alpha_0 + mdl.alpha_1 * vec_retn[
i - 1]**2 + mdl.beta_1 * mdl.h_t[i - 1]
mdl.obj = pyo.Objective(expr=sum(
pyo.log(mdl.h_t[i]) + vec_retn[i]**2 / mdl.h_t[i] for i in mdl.T))
return mdl
vec_retn = np.random.randn(100)**2 / 3 + np.random.randn(100)**3 / 6
temp_mdl = get_model_garch11mle(vec_retn)
opt = pyo.SolverFactory('mosek')
temp_res = opt.solve(temp_mdl)
when using 'mosek':
DegreeError: MOSEK does not support expressions of degree None.
when using 'gurobi':
RuntimeError: Cannot write legal LP file. Objective 'obj' has nonlinear terms that are not quadratic.

The problem is in your for-loop, you don't need to declare new Expression components just assign the expression to the appropriate index:
for i in mdl.T:
if i == 0:
mdl.h_t[i] = mdl.alpha_0 / (1 - mdl.alpha_1 - mdl.beta_1)
else:
mdl.h_t[i] = mdl.alpha_0 + mdl.alpha_1 * (vec_retn[i - 1]**2) + mdl.beta_1 * mdl.h_t[i - 1]

Related

How to add latent heat term in FiPy?

I have been trying to simulate Two Temperature Model using fipy
the math of the model:
C_e(∂T_e)/∂t=∇[k_e∇T_e ]-G(T_e-T_ph )+ A(r,t)
C_ph(∂T_ph)/∂t=∇[k_ph∇T_ph] + G(T_e-T_ph)
the source supposed to heat the electrons T_e, then the heat transferred to phonons T_ph through G, when T_ph reach melting point for example 2700 K, some of heat (360000 J) goes as latent heat before melting.
here is my code:
from fipy.tools import numerix
import scipy
import fipy
import numpy as np
from fipy import CylindricalGrid1D
from fipy import Variable, CellVariable, TransientTerm, DiffusionTerm, Viewer, LinearLUSolver, LinearPCGSolver, \
LinearGMRESSolver, ImplicitDiffusionTerm, Grid1D, ImplicitSourceTerm
## Mesh
nr = 50
dr = 1e-7
# r = nr * dr
mesh = CylindricalGrid1D(nr=nr, dr=dr, origin=0)
x = mesh.cellCenters[0]
# Variables
T_e = CellVariable(name="electronTemp", mesh=mesh,hasOld=True)
T_e.setValue(300)
T_ph = CellVariable(name="phononTemp", mesh=mesh, hasOld=True)
T_ph.setValue(300)
G = CellVariable(name="EPC", mesh=mesh)
t = Variable()
# Material parameters
C_e = CellVariable(name="C_e", mesh=mesh)
k_e = CellVariable(name="k_e", mesh=mesh)
C_ph = CellVariable(name="C_ph", mesh=mesh)
k_ph = CellVariable(name="k_ph", mesh=mesh)
C_e = 4.15303 - (4.06897 * numerix.exp(T_e / -85120.8644))
C_ph = 4.10446 - 3.886 * numerix.exp(-T_ph / 373.8)
k_e = 0.1549 * T_e**-0.052
k_ph =1.24 + 16.29 * numerix.exp(-T_ph / 151.57)
G = numerix.exp(21.87 + 10.062 * numerix.log(numerix.log(T_e )- 5.4))
# Boundary conditions
T_e.constrain(300, where=mesh.facesRight)
T_ph.constrain(300, where=mesh.facesRight)
# Source 𝐴(𝑟,𝑡) = 𝑎𝐷(𝑟)𝜏−1 𝑒−𝑡/𝜏 , 𝐷(𝑟) = 𝑆𝑒 exp (−𝑟2/𝜎2)/√2𝜋𝜎2
sig = 1.0e-6
tau = 1e-15
S_e = 35
d_r = (S_e * 1.6e-9 * numerix.exp(-x**2 /sig**2)) / (numerix.sqrt(2. * 3.14 * sig**2))
A_t = numerix.exp(-t/tau)
a = (numerix.sqrt(2. * 3.14)) / (3.14 * sig)
A_r = a * d_r * tau**-1 * A_t
eq0 = (
TransientTerm(var=T_e, coeff=C_e) == \
DiffusionTerm(var=T_e, coeff=k_e) - \
ImplicitSourceTerm(coeff=G, var=T_e) + \
ImplicitSourceTerm(var=T_ph, coeff=G) + \
A_r)
eq1 = (TransientTerm(var=T_ph, coeff=C_ph) == DiffusionTerm(var=T_ph, coeff=k_ph) + ImplicitSourceTerm(var=T_e, coeff=G) - ImplicitSourceTerm(coeff=G, var=T_ph))
eq = eq0 & eq1
dt = 1e-18
steps = 7000
elapsed = 0.
vi = Viewer((T_e, T_ph), datamin=0., datamax=2e4)
for step in range(steps):
T_e.updateOld()
T_ph.updateOld()
vi.plot()
res = 1e100
dt *= 1.01
count = 0
while res > 1:
res = eq.sweep(dt=dt, underRelaxation=0.5)
print(t, res)
t.setValue(t + dt)
As I understood I can include the latent heat as source term as sink in eq1, or add a gaussian peak to C_ph and the peak center should be around melting point.
I have no idea which one is better and more stable, I have no idea how to implement any one of them .
please help me with that
Based on the comments (please edit that into the question), change eq1 to
eq1 = (TransientTerm(var=T_ph, coeff=C_ph)
== DiffusionTerm(var=T_ph, coeff=k_ph)
+ ImplicitSourceTerm(var=T_e, coeff=G)
- ImplicitSourceTerm(coeff=G, var=T_ph)
+ (1/numerix.sqrt(2*numerix.pi * sig2)) * numerix.exp(-(T_ph - 1850)**2 / 2 * sig2)))
It will be evaluated explicitly, but it will update whenever T_ph updates.

Turning my Euler function in to a higher order Runge–Kutta (RK4) that runs with an O(h^4) algorithm?

I currently have the below as my Euler function but i would like to try this same function using the Runge-Kutta method as i believe it is more accurate
def Euler(U,V,n,dt):
images = []
for i in range(n):
Uc = U[1:-1, 1:-1]
Vc = V[1:-1, 1:-1]
U[1:-1, 1:-1]=Uc + dt * (Du * laplace(U,hx,ht) + F(Uc,Vc))
V[1:-1, 1:-1]=Vc + dt * (Dv * laplace(V,hx,ht) + G(Uc,Vc))
U=periodic(U)
V=periodic(V)
if i % 500 == 0:
images.append(V)
return images
I have tried to do this below however i can't get this to run at all
def RK4_2_d(U,V,t,c):
for k in range(len(t)-1):
uu=np.zeros((U.shape[0],V.shape[0]))
K1=ht*c*laplace(U[k,:,:],hx,hy);uu[1:-1,1:-1]=K1
K2=ht*c*laplace(U[k,:,:]+uu/2,hx,hy);uu[1:-1,1:-1]=K2
K3=ht*c*laplace([U[k,:,:]+uu/2,hx,hy);uu[1:-1,1:-1]=K3
K4=ht*c*laplace(U[k,:,:]+uu,hx,hy)
K1=ht*c*laplace(V[k,:,:],hx,hy);uu[1:-1,1:-1]=K1
K2=ht*c*laplace(V[k,:,:]+uu/2,hx,hy);uu[1:-1,1:-1]=K2
K3=ht*c*laplace(V[k,:,:]+uu/2,hx,hy);uu[1:-1,1:-1]=K3
K4=ht*c*laplace(V[k,:,:]+uu,hx,hy)
U[1:-1, 1:-1]=Uc + dt * (Du * laplace(U,hx,ht) + F(Uc,Vc))
V[1:-1, 1:-1]=Vc + dt * (Dv * laplace(V,hx,ht) + G(Uc,Vc))
U=periodic(U)
V=periodic(V)
if i % 500 == 0:
images.append(V)
return images
Am i going the right way about this?

Converting the simple IDL argument code to python code

Simply I want to translate the IDL code to python code. This is an easy task for any IDL and Python Expert. But it is not possible for me, if anybody helps me to translate this code then I will thankful to him/her.
RelA = ABS((image1 ) - (image2))
index = where(RelA gt 180.D)
RelA[index] = 360.D- RelA[index]
index = where(RelA le 180.)
RelA[index] = 180.D- RelA[index]
CosRe = cos(RelA * !pi / 180.D)
It's a straightforward conversion to NumPy:
#RelA = ABS((image1 ) - (image2))
RelA = np.abs(image1 - image2)
#index = where(RelA gt 180.D)
index = np.where(RelA > 180.0)
#RelA[index] = 360.D- RelA[index]
RelA[index] = 360.0 - RelA[index]
#index = where(RelA le 180.)
index = np.where(RelA <= 180.0)
#RelA[index] = 180.D- RelA[index]
RelA[index] = 180.0 - RelA[index]
#CosRe = cos(RelA * !pi / 180.D)
CosRe = np.cos(np.radians(RelA))
To translate your second piece of code, just remove the "D" specifiers (Python scalars are automatically higher precision), use "**" instead of "^", and use Numpy's cos function:
D1 = (0.00864 + (0.0000065)) * (0.86D)**(-(3.916 + (0.074 * 0.86)+ (0.05/0.86D)))
D2 = 0.008569 * ((0.8585)**(-4))*(1. + (0.0113 *(0.8585)**(-2)) + (0.00013 * (0.8585D)^(-4)))
D1 = (Pz/Po) * (0.00864 + (0.0000065 * z)) * (0.55)**(-(3.916 + (0.074 * 0.55)+ (0.05/0.55)))
Pr1 = (3./16.*np.pi)* (2/(2+delta))* ((1+delta)+((1+delta)*(np.cos(Agl) * np.cos(Agl))))
Pr2 = (3./16.*np.pi) * (1 + (np.cos(Agl) * np.cos(Agl)))
Pz=image1
Po=image2
Agl=image3
delta=0.0139
D1 = (0.00864D + (0.0000065D )) * (0.86D)^(-(3.916 + (0.074 * 0.86D)+ (0.05/0.86D)))
D2 = 0.008569D * ((0.8585D)^(-4))*(1.D + (0.0113D *(0.8585D)^(-2)) + (0.00013D * (0.8585D)^(-4)))
D1 = (Pz/Po) * (0.00864D + (0.0000065D * z)) * (0.55D)^(-(3.916 + (0.074 * 0.55)+ (0.05/0.55)))
Pr1 = (3.D/16.D*!dPi)* (2/(2+delta))* ((1+delta)+((1+delta)*(cos(Agl) * cos(Agl))))
Pr2 = (3.D/16.D*!Pi) * (1 + (cos(Agl) * cos(Agl)))

Solving differential equations, list index out of range

def rainflow(pr, dt, ci, k, tabo):
phi = tabo/dt
qsim = pd.Series(data=None, index=pr.index)
qsim.iloc[0] = ci
for i in range(1, len(qsim) + 1):
qsim.iloc[i] = k * (pr.iloc[i] - (phi * (qsim.iloc[i-1] / pr.iloc[i-1])))
return qsim.iloc
def irmse(dif, obs):
rmse = np.sqrt(np.mean(dif ** 2) / len(obs))
delta = obs - obs.shift(1)
delta_prom = np.mean(delta)
sigma_obs = (np.sqrt((np.sum((delta - delta_prom) ** 2) / (len(delta)) - 1)))
irmse = rmse / sigma_obs
return irmse
def obj_fun(par, arg):
sim = rainflow(arg[1], arg[2], par[0], par[1])
dif = arg[0] - sim
return irmse(dif, arg[0])
df_data = pd.ExcelFile('Taller_opt.xlsx').parse(sheetname='caudal', index_col='Fecha')
sr_pr_cal = df_data['PT'].iloc[0:int(len(df_data['PT']) * 0.7)]
sr_pr_val = df_data['PT'].iloc[int(len(df_data['PT']) * 0.7):]
sr_qobs_cal = df_data['Qobs'].iloc[0:int(len(df_data['Qobs']) * 0.7)]
sr_qobs_val = df_data['Qobs'].iloc[int(len(df_data['Qobs']) * 0.7):]
dt = 1.
ci = sr_qobs_cal.iloc[0]
met_opt = 'minimize'
par_ini = [0.5, 10]
min_results = so.minimize(fun=obj_fun, x0=par_ini, args=[sr_pr_cal, sr_qobs_cal], method='Nelder-Mead')
I'm trying to optimize my equation but it's give:
File "C:/Users/yeni/PycharmProjects/untitled/new.py", line 23, in obj_fun
sim = rainflow(arg[1], arg[2], par[0], par[1])
IndexError: list index out of range
"IndexError: list index out of range" Why is this happening?
How can ir fix it?

Using scipy.integrate.ode to solve protoplanetary hydrostatic equilibria

I have written code to solve the protoplanetary hydrostatic equilibria equations using first order euler method, and the results are as expected. I now want to rewrite it using fourth order Runge-Kutta solution, which is builtin to scipy.integrate.ode
Expected result, attained by using a custom written euler method:
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import ode
universalGasConstant = 8.31
gravitationalConstant = 6.67 * 10**-11
astronomicalUnit = 1.5 * (10**11)
coreMass = 5.9 * 10**24
sunMass = 2 * (10**30)
coreRadius = 0
coreDensity = 5500.0
semiMajorAxis = 5 * astronomicalUnit
gasMeanMolecularMass = 2.3 * 10**-3
coreRadius = (coreMass / ((4 / 3) * np.pi * coreDensity))**(1 / 3)
print('coreradius is', coreRadius)
hillSphere = (1**-4)*(semiMajorAxis) * (((coreMass) / (3 * sunMass))**(1 / 3))
print('hillsphere is', hillSphere)#THIS IS THE HILLSPHERE
numberOfSlices = 100000000 #NUMBER OF SLICES
deltaRadius = hillSphere / numberOfSlices
print('slice length is', deltaRadius)
#gravitationalForce = ((gravitationalConstant * coreMass) /
#(coreRadius + (deltaRadius)))
sunSurfaceTemperature = 5800
sunRadius = 6.96 * 10**8
equilibriumTemperature = sunSurfaceTemperature * \
(sunRadius / (2 * semiMajorAxis))**(1 / 2)
print('equilibrium temperature at', semiMajorAxis,
'metres is', equilibriumTemperature, 'kelvin')
pressureAtRadius = 0
initialDensity = 10.0 #INITIAL DENSITY
densityAtRadius = 0
muOverRT = gasMeanMolecularMass/(equilibriumTemperature * universalGasConstant)
print('muOverRT is', muOverRT)
totalMass = coreMass
densityAtRadius = initialDensity
def function(y, r):
totalMass = y[0]
distanceFromCOG = y[1]
# the differential equations
dRhodr = -(((gravitationalConstant*totalMass*
densityAtRadius*muOverRT))/(distanceFromCOG**2))
dMdr = 4*np.pi*gravitationalConstant*densityAtRadius
#dPdr = (1/(muOverRT))*dRhodr
return [dRhodr, dMdr]
distanceFromCOG = coreRadius+np.linspace(0,numberOfSlices) #number of points
initialDensity = [0,0]
solution = ode(function,initialDensity,distanceFromCOG).set_integrator('vode', method = 'dopri5')
plt.plot(solution)
solution.set_integrator('dopri5')

Categories

Resources