2

I would like to solve the following DGL system numerically in python:

enter image description here

The procedure should be the same as always. I have 2 coupled differential equations of the 2nd order and I use the substitution g' = v and f' = u to create four coupled differential equations of the 1st order.

enter image description here

Here ist my code:

from scipy.integrate import solve_ivp
import numpy as np
import matplotlib.pyplot as plt

# Constants
e = 1
mu = 1
lambd = 1

# Initial second-order system

# g'' + 2/r g'-2/r^2 g - 3/r eg^2- e^2 g^3 - e/(2r) f^2 - e^2/4 f^2g = 0
# f'' + 2/r f' - 2/r^2 f - 2e/r fg - e^2/2 fg^2 + mu^2 f - lambda f^3 = 0

# Substitution
# g' = v
# v' = g''
# f' = u
# u' = f''

# Equivalent set of first-order systems
def dSdr(r, S):
    g, v, f, u = S
    dgdr = v
    dvdr = -2 / r * v + 2 / r ** 2 * g + 3 / r * e * g ** 2 + \
        e ** 2 * g ** 3 + e / (2 * r) * f**2 + e**2 / 4 * f ** 2 * g
    dfdr = u
    dudr = -2 / r * u + 2 / r ** 2 * f + 2 * e / r * f * g + e ** 2 / 2 * f * g**2 - mu ** 2 * f + lambd * f ** 3

    return [dgdr, dvdr, dfdr, dudr]

# Initial conditions
g0 = 0.0001
v0 = 0.0001
f0 = 1
u0 = 0.0001
S0 = [g0, v0, f0, u0]

r_start = 0.1
r_end = 100
r = np.linspace(r_start, r_end, 1000)

# Solve the differential equations

sol = solve_ivp(dSdr, t_span=(min(r), max(r)), y0=S0, t_eval=r, method='RK45')




# Check if integration was successful
if sol.success:
    print("Integration successful")
else:
    print("Integration failed:", sol.message)

# Debugging information
print("Number of function evaluations:", sol.nfev)
print("Number of accepted steps:", sol.t_events)
print("Number of steps that led to errors:", sol.t)

# Plot results
plt.figure(figsize=(10, 6))
plt.plot(sol.t, sol.y[0], label='g(r)')
plt.plot(sol.t, sol.y[2], label='f(r)')
plt.xlabel('r')
plt.ylabel('Function values')
plt.legend()
plt.title('Solutions of the differential equations')
plt.show()

My boundary con. should be f(0) = g(0) = 0 and f(infinity) = mu/sqrt(lambd) g(infinity) = 0 so that the system makes physical sense. But how can I incorporate this condition or how do I know the initial conditions for v,u? The system should look like this (From the original paper):

enter image description here

but it doesn't. Does anyone know what to do?

enter image description here

Source:

enter link description here

2
  • 2
    @Hendriksdf5, your equations as you have written them are entirely consistent with the trivial solution f=g=0 everywhere. So, they are probably wrong. Your stated boundary conditions also disagree with the picture you have posted. Please post a link to the original equations, not your rendition of them. Wherever you took that picture from would be a start. You can solve these type of equations by finite-volume methods, but we need to see the correct equations first. Commented May 24, 2024 at 21:13
  • I have attached the source as well as a snippet of the paper where you can see what system they are trying to solve. They scale the system by a factor before solving it but that shouldn't matter should it? Commented May 24, 2024 at 22:21

1 Answer 1

7

Although you could try a "shooting" method using initial-value solvers, I find it best to go for a boundary-value problem directly. I do so by a method akin to the finite-volume method in computational fluid mechanics (CFD).

Division by r creates singularities, so start by multiplying your equations by r2. Collecting the derivative terms you will then get equations which look like spherically-symmetric diffusion equations:

enter image description here

Here, Sf and Sg are the great long source terms (which you will probably have to check in my code - there's plenty of scope for minor errors). Discretise each (equivalent to integrating over a cell [ri-1/2,ri+1/2] by the finite-volume method). e.g. for f:

enter image description here

This, and the corresponding equation for g can be written in the form

enter image description here

There are small differences at the boundaries and it is the non-zero boundary condition on f that produces a non-trivial solution.

The discretised equations can then be solved iteratively either by the tri-diagonal matrix algorithm (TDMA) or by iterative schemes like Gauss-Seidel or Jacobi. Although experience with CFD suggests that the TDMA would probably be best, for simplicity I’ve opted for a (slightly under-relaxed) Jacobi method here.

Note that, in common with CFD practice, I have, in my edited code, split the source terms as, e.g. sf + spf.f, with spf being negative so that it can be combined with the diagonal coefficient ap on the LHS.

EDIT: code amended so that cell-centre values are 1...N with boundary indices 0 and N+1, source terms split into explicit and implicit parts, code reads more like Python than Fortran!

import numpy as np
import matplotlib.pyplot as plt

N = 100                                # number of cells (1-N); added boundaries 0 and N+1
rmin, rmax = 0.0, 20.0                 # minimum and maximum r (latter an approximation to "infinity"
dr = rmax / N                          # cell width
gL, gR, fL, fR = 0, 0, 0, 1            # boundary conditions

e, nu, lamda = 1, 1, 1

# Cell / node arrangement:
#
#       0                                          N+1
#       |  1     2                        N-1    N  |
#       |-----|-----| .  .  .  .  .   . |-----|-----|
#
r = np.linspace( rmin - 0.5 * dr, rmax + 0.5 * dr, N + 2 )      # cell centres (except for boundaries)
r[0] = rmin;   r[N+1] = rmax                                    # boundary nodes on faces of cells

# Connection coefficients
awL = 2 * rmin ** 2 / dr ** 2
aeR = 2 * rmax ** 2 / dr ** 2
aw = np.zeros( N + 2 )
ae = np.zeros( N + 2 )
for i in range( 1, N + 1 ):
    if i == 1:
        aw[i] = 0
    else:
        aw[i] = ( 0.5 * ( r[i-1] + r[i] ) ) ** 2 / dr ** 2
    if i == N:
        ae[i] = 0
    else:
        ae[i] = ( 0.5 * ( r[i+1] + r[i] ) ) ** 2 / dr ** 2
ap = aw + ae

# Initial values
g = np.zeros( N + 2 )
f = np.zeros( N + 2 )
f = f + 1
g = g + 1

# Boundary conditions
f[0] = fL;   f[N+1] = fR;   g[0] = gL;   g[N+1] = gR


alpha = 0.9                  # Under-relaxation factor
niter = 0
for _ in range( 10000 ):
    niter += 1

    # Source term (e.g., for f this would be decomposed as sf + spf.f, where spf is negative)
    spf = -2  -0.5 * e**2 * r**2 * g**2  - lamda * r**2 * f**2
    sf = -2 * e * r * f * g   +   nu**2 * r**2 * f

    spg = -2  - e**2 * r**2 * g**2  - 0.25 * e**2 * r**2 * f**2
    sg  = -e * r * ( 3 * g**2 + 0.5 * f**2 )

    # Dirichlet boundary conditions applied via source term
    sf[1] += awL * fL;   spf[1] -= awL
    sg[1] += awL * gL;   spg[1] -= awL
    sf[N] += aeR * fR;   spf[N] -= aeR
    sg[N] += aeR * gR;   spg[N] -= aeR

    # Update g and f (under-relaxed Jacobi method)
    ftarget = f.copy()
    gtarget = g.copy()
    for i in range( 2, N ):                                # cells 2 - (N-1)
        ftarget[i] = ( sf[i] + aw[i] * f[i-1] + ae[i] * f[i+1] ) / ( ap[i] - spf[i] )
        gtarget[i] = ( sg[i] + aw[i] * g[i-1] + ae[i] * g[i+1] ) / ( ap[i] - spg[i] )
    i = 1                                                  # leftmost cell
    ftarget[i] = ( sf[i] + ae[i] * f[i+1] ) / ( ap[i] - spf[i] )
    gtarget[i] = ( sg[i] + ae[i] * g[i+1] ) / ( ap[i] - spg[i] )
    i = N                                                  # rightmost cell
    ftarget[i] = ( sf[i] + aw[i] * f[i-1] ) / ( ap[i] - spf[i] )
    gtarget[i] = ( sg[i] + aw[i] * g[i-1] ) / ( ap[i] - spg[i] )

    # Under-relax the update
    f = alpha * ftarget + ( 1 - alpha ) * f
    g = alpha * gtarget + ( 1 - alpha ) * g

    change = ( np.linalg.norm( f - ftarget ) + np.linalg.norm( g - gtarget ) ) / N
    # print( niter, change )
    if change < 1.0e-10: break

print( niter, " iterations " )

plt.plot( r, f, label='f' )
plt.plot( r, g, label='g' )
plt.grid()
plt.legend()
plt.show()

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.