I'm trying to solve a non-linear PDE HJB equation using FiPy, but i have some difficulties translating the PDE into the proper FiPy syntax:
I tried something like :
eqX = TransientTerm() == -DiffusionTerm(coeff=1) + (phi.faceGrad * phi.faceGrad)
and It doesn't work because of the square of the gradient
My equation: (du/dt = - \delta u + ||\grad(u)||^2)
Does FiPy allow to solve this kind of equations? if not is there a package or a way to solve it using finite difference ?
Thank you!
It's possible to recast the final term to be a diffusion term and a source term so that the equation can be rewritten as,
eqn = TransientTerm() = DiffusionTerm(u - 1) - u * u.faceGrad.divergence
That won't give an error, but might not be very stable
Related
I cannot figure out how to solve this separable differential equation using sympy. Help would be greatly appreciated.
y′=(y−4)(y−2),y(0)=5
Here was my attempt, thanks in advance!!!
import sympy as sp
x,y,t = sp.symbols('x,y,t')
y_ = sp.Function('y_')(x)
diff_eq = sp.Eq(sp.Derivative(y_,x), (y-4)*(y-2))
ics = {y_.subs(x,0):5}
sp.dsolve(diff_eq, y_, ics = ics)
the output is y(x) = xy^2 -6xy +8x + 5
The primary error is the introduction of y_. This makes the variable y a constant parameter of the ODE and you get the wrong solution.
If you correct this you get an error of "too many solutions for the integration constant". This is a bug caused by not simplifying the integration constant after it first occurs. So multiplication and addition of constants should just be absorbed, an additive constant in an exponent should become a multiplicative factor for the exponential. As it is, exp(2*C_1)==3 has two solutions if C_1 is considered as an angle (it's a bit of tortured logic from computing roots in the complex plane).
The newer versions can actually solve this fully if you give the third hint in the classification list 'separable', '1st_exact', '1st_rational_riccati', ... that does something different than partial fraction decomposition of the first two
from sympy import *
x = Symbol('x')
y = Function('y')(x)
dsolve(Eq(y.diff(x), (y-2)*(y-4)),y,
ics={y.subs(x,0):5},
hint='1st_rational_riccati')
returning
\displaystyle y{\left(x \right)} = \frac{2 \cdot \left(6 - e^{2 x}\right)}{3 - e^{2 x}}
It's not entirely lasso because I add an extra constraint but I'm not sure how I'm supposed to solve a problem like the following using cvxpy
import cvxpy as cp
import numpy as np
A = np.random.rand(5000,1000)
v0 = np.random.rand(1000,1)
v = cp.Variable(v0.shape)
iota = np.ones(v0.shape)
lam = 1
objective = cp.Minimize( (A#(v-v0)).T#(A#(v-v0)) + lam * cp.abs(v).T # iota )
constraints = [v >= 0]
prob = cp.Problem(objective, constraints)
res = prob.solve()
I tried various versions of this but this is the one that most clearly shows what I'm trying to do. I get the error:
DCPError: Problem does not follow DCP rules. Specifically: The objective is not DCP. Its following subexpressions are not: ....
And then an error I don't undeerstand haha.
CVXPY is a modeling language for convex optimization. Therefore, there is a set of rules your problem must follow to ensure your problem is convex indeed. These are what cvxpy refers to DCP: Disciplined Convex Programming. As the error suggests, your objective is not DCP.
To be more precise, the problem is in the objective (A#(v-v0)).T#(A#(v-v0)): cvxpy don't know it is indeed convex (from program point of view, it's just few multiplications).
To ensure your problem is DCP, it's best to use cvxpy atomic functions.
Essentially you are modeling x^T * x (if x=A#(v-v0)), which is the squares of norm 2 of a vector. cp.norm2 is the way to ensure cvxpy will know the problem is convex.
change the line of the objective function to:
objective = cp.Minimize(cp.norm2(A # (v - v0)) ** 2 + lam * cp.abs(v).T # iota)
and it works.
(Also take a look at cvxpy example of lasso regression)
I am trying to solve the following two differential equation (numerically) in SageMath:
My goal is to obtain the plot of M(r)-r.
I tried the following code:
sage: r = var('r')
sage: M = function('M')(r)
sage: a = function('a')(r)
sage: de1 = (M*a*a*diff(M,r) + (M*M*a+6*a)*diff(a,r) + 1/(r*r) == 0)
sage: de2 = (a*r*diff(M,r) + 7*M*r*diff(a,r) + 2*M*a == 0)
sage: desolve_system([de1,de2], [M,a])
But this is returning an error that says:
"TypeError: ECL says: Error executing code in Maxima: desolve: can't handle this case."
So I am looking for a numerical solution of the differential equations. But since I am new to SageMath, I don't how to proceed. Can someone suggest me how to proceed for obtaining a numerical solution?
EDIT:
The M(r)-r plot corresponding to the above equations is the following:
Following the sage documentation of desolve functions
something like the following should work, if you specify the initial conditions and the integration range. The ODE system is presented as a linear system of equations in the derivatives, so use the matrix functionality of sage to solve this linear system to get the symbolic expressions for the explicit first order system.
A = matrix([[ M*a*a, M*M*a+6*a + 1/(r*r)],
[ a*r, 7*M*r]])
B= matrix([[ 1/(r*r)], [2*M*a]])
f = -A^-1*B
times=srange(ti,tf,dt)
ics=[M0,a0]
sol=desolve_odeint(f,ics,times,dvars = [M,a], ivar = r)
The result is a list of state vectors at the times in times. So with r=times and M=sol[:,0] you should be able to plot M-r against r.
I want to solve the following set of 3 coupled pdes in python using fipy
∇2n − (∇2ψ)n − (∇ψ).∇n = n/10,
∇2p + (∇2ψ)p + (∇ψ).∇p = p/10,
∇2ψ = −(p − n)
The variables are p,n and ψ. As can be seen from the first and second equation, the first term can be set as the diffusion term in the pde solver in fipy. If the other terms of the first and second equation are to be incorporated in the fipy pde solver, I suppose that they should be incorporated in the Implicit Source Term in fipy. But considering the presence of vector identities in these terms, I am facing some difficulty in incorporating these equations in the fipy pde solver. Any help regarding this would be appreciated.
Assuming the instances of 2 that appear in your equations are squaring of the nabla (del) operator, you certainly can write for the first equation:
DiffusionTerm(var=n) - ImplicitSourceTerm(coeff=psi.faceGrad.divergence, var=n) - psi.grad.dot(n.grad) == ImplicitSourceTerm(coeff=1./10, var=n)
however, this is not a very implicit representation.
Better is to apply the chain rule:
$\nabla (n \nabla \psi) \equiv \nabla n \cdot \nabla \psi + n \nabla^2 \psi$
such that
$\nabla^2 n - \nabla(n \nabla psi) == n / 10$
This is then
DiffusionTerm(var=n) - DiffusionTerm(coeff=n, var=psi) == ImplicitSourceTerm(coeff=1./10, var=n)
if you wish to couple your equations, and
DiffusionTerm(var=n) - ConvectionTerm(coeff=psi.faceGrad, var=n) == ImplicitSourceTerm(coeff=1./10, var=n)
if you don't.
I have a system of differential equations like this
dy/dt = f(t,y,y1,y2,....,yn,x),
dy1/dt = f(t,y,y1,y2,..yn,x),
.
.
.
dyn/dt = f(t,y,y1,y2,..yn,x),
x(t) = f(t,y1,y2,...yn,x)
And I have the values y_i(0),x(0)
If I had dx/dt then simply using scipy.integrate IVP I could solve this. I can't calculate the derivative of x(t) it's too complex . Can I simulate this system in python without finding dx/dt ?
No problem, define
def derivatives(t,y):
xt = func_x(t,y);
dy = func_y(t,y,xt)
return dy
where func_y takes scalar (t,xt) and vector (y) arguments and returns a vector of the same size as y. This then works well with solve_ivp.