Figure A.5:

Dimensionless concentration versus dimensionless radial position for different numbers of collocation points.

Figure A.5

Code for Figure A.5

Text of the GNU GPL.

main.py


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# Converted from pelletcolloc.m - pellet collocation profiles vs npts
# [makes] pelletcolloc.dat
import numpy as np
from scipy.optimize import fsolve
from misc import save_ascii, colloc

Phi = 10.0; n = 1
nint = 100
xint = np.linspace(0, 3, nint)

# Polynomial interpolation (Lagrange)
def polinterp(xcol, xint_arr):
    ncol = len(xcol); nint = len(xint_arr)
    W = np.zeros((nint, ncol))
    for i in range(ncol):
        d = 1.0
        for j in range(ncol):
            if j != i:
                d *= (xcol[i] - xcol[j])
        for k in range(nint):
            n_val = 1.0
            for j in range(ncol):
                if j != i:
                    n_val *= (xint_arr[k] - xcol[j])
            W[k, i] = n_val / d
    return W

# Analytical solution
can      = np.where(xint != 0, 3.0/xint * np.sinh(Phi*xint)/np.sinh(3*Phi), 3*Phi/np.sinh(3*Phi))
etaan    = 1.0/Phi * (1.0/np.tanh(3*Phi) - 1.0/(3*Phi))

colvec = [5, 10, 30, 50]
ncol   = len(colvec)
csave  = np.zeros((nint, ncol))
cerr   = np.zeros((nint, ncol))

for i, npts in enumerate(colvec):
    R0, A, B, Q = colloc(npts - 2, 'left', 'right')
    R = R0*3.0; A = A/3.0; B = B/9.0; Q = Q*3.0

    W = polinterp(R, xint)

    def pellet(c):
        res = B @ c + 2.0*(A @ c)/R - 2.0/(n+1)*Phi**2*(c**n)
        res[0]  = A[0, :] @ c
        res[-1] = 1.0 - c[-1]
        return res

    c0 = 0.5*np.linspace(0, 1, npts)
    c  = fsolve(pellet, c0, full_output=False)
    cint = W @ c
    csave[:, i] = cint
    cerr[:, i]  = np.abs(cint - can) / can

table = np.column_stack([xint, csave, cerr])
save_ascii('pelletcolloc.dat', table)