I'm trying to solve a coupled non-linear system of 4 PDEs, here's the code:
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
from odeintw import odeintw
# constants
global rH, L, q, p, Q, mu
rH = 1.0 ; L = 1.0 ; p = 2.0 ; q = 1.0 ; Q = 1.71 ; mu = Q*rH/L**2
def dfunc(G, kx, ky, w, r):
try:
z = 1.0/(rH - r)
except ZeroDivisionError:
print "Trying to divide zero"
phi = mu*( 1.0 - rH/r)
fr = 1.0 - (rH/r)**3
scale = L**2 * np.sqrt(fr) / r**2 + 0j
vp = (w + q*phi)/(np.sqrt(fr)) + p*mu*rH/r + 0j
vn = (w + q*phi)/(np.sqrt(fr)) - p*mu*rH/r + 0j
# G11 -> G1, G12 -> G2, G21 -> G3, G22 -> G4
G1, G2, G3, G4 = G
G11 = (vp - kx + (vn + kx)*G1**2 - ky*G1*G2 - ky*G1*G3
+ (vp-kx)*G2*G3 )
G12 = (ky + (vn + kx)*G1*G2 - ky*G2**2 - ky*G1*G4
+ (vp-kx)*G2*G4 )
G21 = (ky + (vn + kx)*G1*G3 - ky*G1*G4 - ky*G3**2
+ (vp-kx)*G3*G4 )
G22 = (vn + kx + (vn + kx)*G2*G3 - ky*G2*G4 - ky*G2*G3
+ (vp-kx)*G4**2 )
return np.multiply(scale, np.array([ G11, G12, G21, G22 ]))
# jaccobian
def jac(G, kx, ky, w, r):
G1, G2, G3, G4 = G
jac = np.array([
[2(vn+kx)*G1 - ky*(G2+G3), -ky*G1 + (vp-kx)*G3, -ky*G1+(vp-kx)*G2, 0 ],
[(vn+kx)*G2-ky*G4, (vn+kx)*G1-2*ky*G2+(vp-kx)*G4, 0, -ky*G1+(vp-kx)*G2 ],
[(vn+kx)*G3-ky*G4, 0, (vn+kx)*G1-2*ky*G3+(vp-kx)*G4, -ky*G1+(vp-kx)*G3 ],
[0, (vn+kx)*G3-ky*(G4+G3), (vn+kx)*G2-ky*G2, -ky*G2+2*(vp-kx)*G4 ]
])
return np.multiply(scale, jac)
# Initial value
Gir = np.array([ 1.0j, 0, 0, 1.0j ])
r = np.arange(rH + 0.1, 1000*rH, 1)
kx = 0
ky = 0
w = 0.0001 + 0.0000001j
G, infodict = odeintw(dfunc, Gir, r, args=(kx,ky,w), Dfun=jac, full_output=True )
print 'final', np.size(G), G
However it gives the following error and does not really move from the initial point:
lsoda-- warning..internal t (=r1) and h (=r2) are
such that in the machine, t + h = t on the next step
(h = step size). solver will continue anyway
In above, R1 = .1100000000000E+01 R2 = .3569471009368E-22
And the final solution G is an array of 3996 size, please help me understand this. Thanks!
In the functions dfunc and jac, the second argument must be the independent variable. In your case, the independent variable is r, so the definitions should begin
def dfunc(G, r, kx, ky, w):
and
def jac(G, r, kx, ky, w):
Related
I get this error The number of derivatives returned by func() (1) must equal the length of the initial conditions vector (3)
Can some kindly suggest how resolve ?
Thanks
# Define the ODE system
diffeq <- function(t, y, params) {
with(as.list(c(y, params)), {
dCc <- -k12 * c_central + k21 * c_peripheral - k10 * c_central
dCp <- k12 * c_central - k21 * c_peripheral
dy <- -alpha * exp(-beta * y) * y + (c_central - gamma) * (c_central - gamma)
dw <- g * (t - delay) - kw * w
dg <- ks * kw * w0 * (w/W0)^(-param) * exp(-u * y) - (ks + v * y) * g
return(list(dCc, dCp,dy, dw, dg))
})
}
# Set the initial conditions and parameter values
y0 <- 0
g0 <- 0
w0 <- 100
c_central0 <- 500/5
c_peripheral0 <- 0
params <- c(alpha = 1, beta = 2, gamma = 3, kw = 0.1, k12 = 1.2,
k21 = 1.5, k10 = 0.04,ks = 0.01, delay = 0.5,
W0 = 100, param = 2, u = 1, v = 2,c_central = c_central0, c_peripheral = c_peripheral0)
# Solve the differential equations using an ODE solver
result <- ode(y = c(y = y0, w = w0, g = g0), times = seq(0, 40, by = 0.1), func = diffeq, parms = params)
# Plot the solution
plot(result[, "time"], result[, "y"], type = "l", xlab = "Time (t)", ylab = "y(t)")
lines(result[, "time"], result[, "w"], col = "red")
lines(result[, "time"], result[, "g"], col = "blue")```
I'm trying to solve a differential equation that has the form Y'(t)=A(t)*Y(t), where Y and Y' is a column with 4 elements, A is a 4x4 matrix. In the A(t) matrix I'm using the functions m(t) and f(t) to compute each value of the matrix. However, when I put a simple value to m(t) and f(t) (ex: a constant value or a t^2...) the function solvedPmWithTime returns a 4x1 matrix, which is what I expect, but when I use the m(t) and /or function f(t) that I want, which is computed by the compute_m_and_f function, it returns a 1x1 matrix. I can't find my error. If someone could help it would be very much appreciated :). Here are the codes of the functions and the code of the live script that I use to compute the differential equation:
function [m,f] = compute_m_and_f()
syms m(t) f(t)
Bm =600000;
sigmam =2.5;
tm =6;
tf =6;
sigmaf = 2;
Bf = 600000;
eqnM = diff(m,t) == Bm / sqrt(2*pi*sigmam^2)*exp(-((t-tm)^2)/(2*sigmam^2));
condM = m(0)==0;
eqnF = diff(f,t) == Bf / sqrt(2*pi*sigmaf^2)*exp(-((t-tf)^2)/(2*sigmaf^2));
condF = f(0)==0;
M(t) = dsolve(eqnM, condM);
F(t) = dsolve(eqnF, condF);
taum = 4;
tauf = 5;
m(t) = piecewise(t>taum, M(t)-M(t-taum),M(t));
f(t) = piecewise(t>tauf, F(t)-F(t-taum),F(t));
end
function solvedPmWithTime= solvedPmWithTime(~, y)
[m, f] = compute_m_and_f;
alpha = 480;
beta = 0.0011;
sigma = 0.0634;
epsilon = 0.0725;
a = (alpha * (f + m)) / (1 + alpha * beta * (f + m));
b11 =- (1 - (m / (f + m)) ^ sigma);
b12 = (1 - (f / (f + m)) ^ epsilon);
b13 = (1 - (f / (f + m)) ^ epsilon);
b14 = (1 - (f / (f + m)) ^ epsilon);
b21 = (1 - (m / (f + m)) ^ sigma);
b22 = -1;
b23 = 0;
b24 = 0;
b31 = 0;
b32 = (f / (f + m)) ^ epsilon;
b33 = -1;
b34 = 0;
b41 = 0;
b42 = 0;
b43 = (f / (f + m)) ^ epsilon;
b44 =- (1 - (f / (f + m)) ^ epsilon);
b = [b11, b12, b13, b14; b21, b22, b23, b24; b31, b32, b33, b34; b41, b42, b43, b44];
A = a * b;
solvedPmWithTime = A * y;
end
clear all
rho = 6;
Bf = 600000;
Pm1_0 = 0;
Pm2_0 = 0;
Pm3_0 = 0;
Pf_0 = 3600;
[t, Pm] = ode45(#solvedPmWithTime, [0, 100], [Pm1_0; Pm2_0; Pm3_0; Pf_0]); %this returns an error because the size of the matrix is not 4x1
Pm1 = Pm(:, 1);
Pm2 = Pm(:, 2);
Pm3 = Pm(:, 3);
Pf = Pm(:, 4);
hold off
plot(t, Pm1, t, Pm2, t, Pm3, t, Pf)
legend('Pm1', 'Pm2', 'Pm3', 'Pf')
n = solvedPmWithTime([0, 100], [Pm1_0; Pm2_0; Pm3_0; Pf_0]);
size(n)
I want to get extract intermediate parameter values from below ODE function. Can someone figure out how to extract those values from the ode solver.
I want to get values of "a, b,s,& w" apart from the main outputs of the ode solver. I tried to modify return option in the function, but that doesn't work.
Be kind to explain by providing sample codes as I am bit new to python.
from scipy.integrate import odeint
import numpy as np
import matplotlib.pyplot as plt
# parameters
S = 0.0001
M = 30.03
K = 113.6561
Vr = 58
R = 8.3145
T = 298.15
Q = 0.000133
Vp = 0.000022
Mr = 36
Pvap = 1400
wf = 0.001
tr = 1200
mass = 40000
# define t
time = 14400
t = np.arange(0, time + 1, 1)
# define initial state
Cv0 = (mass / Vp) * wf # Cv(0)
Cr0 = (mass / Vp) * (1 - wf)
Cair0 = 0 # Cair(0)
# define function and solve ode
def model(x, t):
C = x[0] # C is Cair(t)
c = x[1] # c is Cv(t)
a = Q + (K * S / Vr)
b = (K * S * M) / (Vr * R * T)
s = (K * S * M) / (Vp * R * T)
w = (1 - wf) * 1000
Peq = (c * Pvap) / (c + w * c * M / Mr)
Pair = (C * R * T) / M
dcdt = -s * (Peq - Pair)
if t <= tr:
dCdt = -a * C + b * Peq
else:
dCdt = -a * C
return [dCdt, dcdt]
x = odeint(model, [Cair0, Cv0], t)
C = x[:, 0]
c = x[:, 1]
I have a system of two equations and I need Matlab to solve for a certain variable. The problem is the variable I need is inside an expression, and trig functions. I wrote the following code:
function [ V1, V2 ] = find_voltages( w1, l1, d, w2, G1, G2, m, v, e, h, a, x)
k1 = sqrt((2*V1*e)/(G1^2*m*v^2));
k2 = sqrt((2*V2*e)/(G2^2*m*v^2));
A = h + l1*a;
b = -A*k1*sin(k1*w1) + a*cos(k1*w1);
B = A*cos(k1*w1) + (a/k1)*sin(k1*w1);
C = B + a*b;
c = C*k2*sinh(k2*w2) + b*cosh(k2*w2);
D = C*cosh(k2*w2) + (b/k2)*sinh(k2*w2);
bd = A*k1*sinh(k1*w1) + a*cosh(k1*w1);
Bd = A*cosh(k1*w1) + (a/k1)*sinh(k1*w1);
Cd = Bd + a*bd;
cd = -Cd*k2*sin(k2*w2) + bd*cos(k2*w2);
Dd = Cd*cos(k2*w2) + (bd/k2)*sin(k2*w2);
fsolve([c*(x-(l1+w1+d+w2)) + D == 0, cd*(x-(l1+w1+d+w2)) + Dd == 0], [V1,V2])
end
and got an error because V1 and V2 are not defined. They are part of an expression, and need to be solved for. Is there a way to do this? Also, is it a problem that the functions I put as arguments to solve are conglomerates of the smaller equations above them?
Valid values:
Drift space 1 (l1): 0.11
Quad 1 length (w1): 0.11
Quad 2 length (w2): 0.048
Separation (d): 0.014
Radius of Separation 1 (G1): 0.016
Radius of Separation 2 (G2): 0.01
Voltage 1 (V1): -588.5
Voltage 2 (V2): 418
Kinetic Energy in eV: 15000
Mass (m) 9.109E-31
Kinetic Energy in Joules (K): 2.4E-15
Velocity (v): 72591415.94
Charge on an Electron (e): 1.602E-19
k1^2=(2*V1*e)/(G1^2*m*v^2): 153.4467773
k2^2=(2*V2*e)/(G2^2*m*v^2): 279.015
First start by re-writing your function as an expression which returns the extent to which your function(s) fail to hold for some valid guess for [V1,V2]. E.g.,
function gap = voltage_eqn(V, w1, l1, d, w2, G1, G2, m, v, e, h, a, x)
V1 = V(1) ;
V2 = V(2) ;
k1 = sqrt((2*V1*e)/(G1^2*m*v^2));
k2 = sqrt((2*V2*e)/(G2^2*m*v^2));
A = h + l1*a;
b = -A*k1*sin(k1*w1) + a*cos(k1*w1);
B = A*cos(k1*w1) + (a/k1)*sin(k1*w1);
C = B + a*b;
c = C*k2*sinh(k2*w2) + b*cosh(k2*w2);
D = C*cosh(k2*w2) + (b/k2)*sinh(k2*w2);
bd = A*k1*sinh(k1*w1) + a*cosh(k1*w1);
Bd = A*cosh(k1*w1) + (a/k1)*sinh(k1*w1);
Cd = Bd + a*bd;
cd = -Cd*k2*sin(k2*w2) + bd*cos(k2*w2);
Dd = Cd*cos(k2*w2) + (bd/k2)*sin(k2*w2);
gap(2) = c*(x-(l1+w1+d+w2)) + D ;
gap(1) = cd*(x-(l1+w1+d+w2)) + Dd ;
end
Then call fsolve from some initial V0:
Vf = fsolve(#(V) voltage_eqn(V, w1, l1, d, w2, G1, G2, q, m, v, e, h, a, x), V0) ;
I have a function f which I am trying to take the symbolic limit of. So I start with the standard
R1 = 18;
h1 = 6.48528;
R2 = 1.8;
h2 = 0.060045431;
f1 = R1^2 / (4 * h1);
R3 = 1;
syms x
f1 =#(r) (h2/R2^2) * r.^2 + f1;
f2 =#(r) (h2/R2^2) * r.^2 + f1;
f1p = matlabFunction(diff(f1(x)));
f2p = matlabFunction(diff(f2(x)));
f =#(r1, t1, r2, t2) ...
-((r1.*r2.*(-f1(r1) + f2(r2) + (r1 - r2.*cos(t1 - t2)).*f1p(r1)).* ...
sqrt(((1 + abs(f1p(r1)).^2).*(1 + f1p(r1).^2))./(1 + abs(cos(t2).* ...
f2p(r2)).^2 + abs(sin(t2).*f2p(r2)).^2)).*(-f1(r1) + f2(r2) + ...
(-r2 + r1.*cos(t1 - t2)).*f2p(r2)).*sqrt(1 + f2p(r2).^2))./ ...
(pi.*(1 + abs(cos(t1).*f1p(r1)).^2 + abs(sin(t1).*f1p(r1)).^2).* ...
(r1.^2 + r2.^2 + abs(f1(r1) - f2(r2)).^2 - 2.*r1.*r2.*cos(t1 - t2)).^2))
then I try to take the limit of f
syms r1 r2 t1 t2
limit(f(r1, t1, r2, t2), r2, r1)
And I get piecewise([r1 == 0, 0], [r1 ~= 0, (limit( huge function of r1, r2, t1, t2 )])
So why does Matlab not want to do the limit and is it valid to just convert to a string remove the limit and replace r2 with r1 the return to a function handle? Is there a better way to do this?
And I want to do this so I can then convert the entire mess back into an anonymous function (using matlabFunction).