I tested the code as it is without optimization. I give a report and general recommendations:
Test 1
In[11]:= Equations[tMin, tMax, 200, 20]; // AbsoluteTiming
Out[11]= {7.76804, Null}
Test 2
In[12]:= Equations[tMin, tMax, 200, 200]; // AbsoluteTiming
Out[12]= {86.8025, Null}
Test 3
In[13]:= Equations[tMin, tMax, 2000, 20]; // AbsoluteTiming
Out[13]= {109.039, Null}
Test 4
In[14]:= Equations[tMin, tMax, 2000, 200]; // AbsoluteTiming
Out[14]= {2174.46, Null}
And so it took 36 minutes, 30-50% of the CPU and 12GB of memory (maximum). Most of the time 1 kernel worked. I think that we can reduce the time to 3-5 minutes. Version report:
$Version
Out[]= "12.0.0 for Microsoft Windows (64-bit) (April 6, 2019)"
Let's start the optimization. Here we are dealing with the Riccati matrix equation
$$c'=c.A.c+B1.c+c.B2...(1) $$
where c
is a 2000x200 matrix. Therefore we used Method -> {"EquationSimplification" -> "Residual"
to solve it. Then it takes about 36 min on my ASUS laptop. We can reduce time by simple replacement t->tmax t
. The corresponding code is
PrepareEquations[tMin_, tMax_, NoC_, NoN_] :=
Module[{i,
j,(*C and N species*)\[Alpha]C = 1,(*C monomer*)\[Alpha]N =
1,(*N monomer*)nCmin = 0, nCmax = NoC,(*Number of C atoms*)
nNmin = 0, nNmax = NoN,(*Number of N atoms*)
c0 = 10^-30(*For numerical stability,avoid null value*)},
Print["Function: PrepareEquations"];
Clear[c, a, b, F, Fc, Fn];
Cinit = 0.00439673;(*Initial C concentration*)
Ninit = 0.00761477;(*Initial N concentration*)
k = 1.380649*10^-23;(*Boltzmann constant,unit J/K*)
T = 723;(*Temperature,unit K*)
R[nC_, nN_] := ((3*(nC + nN)*0.0118)/(4 \[Pi]))^(1/3);(*Radius*)
D\[Alpha][i_, j_] := 0;(*Diffusion coefficients*)
D\[Alpha][\[Alpha]C, 0] := 8.0*10^-4;
D\[Alpha][0, \[Alpha]N] := 1.0*10^-4;
k\[Alpha][nC_, nN_, i_, j_] :=
4 \[Pi]*(R[nC, nN] + R[i, j])/0.0118*D\[Alpha][i, j];
(*Calculation of energy*)RsC = 0.02780299;
\[Sigma]C = 4.09324*10^-19;
Fc[nC_] := 4 \[Pi]*(R[nC, 0])^2*\[Sigma]C*(1 - RsC/R[nC, 0]);
\[Sigma]N = 5.54492*10^-20;
RsN = -0.14758424;
Fn[nN_] := 4 \[Pi]*(R[0, nN])^2*\[Sigma]N*(1 - RsN/R[0, nN]);
F[nC_,
nN_] := -k*T*
Log[(nC + nN)!/(nC!*nN!)] + (nC*Fc[nC + nN] +
nN*Fn[nC + nN])/(nC + nN);
b[nC_, nN_, i_, j_] :=
k\[Alpha][nC, nN, i, j]*c[i, j][t];(*Condensation rate*)
a[nC_, nN_, i_, j_] :=
k\[Alpha][nC - i, nN - j, i, j]*
Exp[-((F[nC - i, nN - j] + F[i, j] - F[nC, nN])/(k*
T))];(*Emission rate*)a[i_, j_, i_, j_] := 0;(*Monomer*)
a[0, nN_, 1, j_] := 0;
a[nC_, 0, i_, 1] := 0;
Clear[CL, Eqk, EqD, Eq];
With[{},(*Initial conditions*)CL[nC_, nN_] := c[nC, nN][tMin] == 0;
(*Definition of the equilibrium equations*)
EqD[nC_, nN_] := c[nC, nN]'[t];
Eqk[nC_, nN_] :=
Sum[b[nC - i, nN - (1 - i), i, 1 - i]*
c[nC - i, nN - (1 - i)][
t] - (b[nC, nN, i, 1 - i] + a[nC, nN, i, 1 - i])*
c[nC, nN][t] +
a[nC + i, nN + (1 - i), i, 1 - i]*
c[nC + i, nN + (1 - i)][t], {i, {0, 1}}];
Eq[nC_, nN_] := EqD[nC, nN] == tMax Eqk[nC, nN];
(*Definition of equilibrium concentrations for each special size*)
Module[{nC, nN}, nC = nCmax;
For[nN = 1, nN < nNmax, nN++,
Eqk[nC, nN] = (b[nC, nN - 1, 0, 1]*
c[nC, nN - 1][t] - (b[nC, nN, 0, 1] + a[nC, nN, 0, 1])*
c[nC, nN][t] +
a[nC, nN + 1, 0, 1]*
c[nC, nN + 1][t]) + (b[nC - 1, nN, 1, 0]*c[nC - 1, nN][t] -
a[nC, nN, 1, 0]*c[nC, nN][t])];
nN = nNmax;
For[nC = 1, nC < nCmax, nC++,
Eqk[nC, nN] = (b[nC - 1, nN, 1, 0]*
c[nC - 1, nN][t] - (b[nC, nN, 1, 0] + a[nC, nN, 1, 0])*
c[nC, nN][t] +
a[nC + 1, nN, 1, 0]*
c[nC + 1, nN][t]) + (b[nC, nN - 1, 0, 1]*c[nC, nN - 1][t] -
a[nC, nN, 0, 1]*c[nC, nN][t])];
nC = 0;
For[nN = 2, nN < nNmax, nN++,
Eqk[nC, nN] = (b[nC, nN - 1, 0, 1]*
c[nC, nN - 1][t] - (b[nC, nN, 0, 1] + a[nC, nN, 0, 1])*
c[nC, nN][t] +
a[nC, nN + 1, 0, 1]*
c[nC, nN + 1][t]) + (-b[nC, nN, 1, 0] c[nC, nN][t] +
a[nC + 1, nN, 1, 0]*c[nC + 1, nN][t])];
nN = 0;
For[nC = 2, nC < nCmax, nC++,
Eqk[nC, nN] = (b[nC - 1, nN, 1, 0]*
c[nC - 1, nN][t] - (b[nC, nN, 1, 0] + a[nC, nN, 1, 0])*
c[nC, nN][t] +
a[nC + 1, nN, 1, 0]*
c[nC + 1, nN][t]) + (-b[nC, nN, 0, 1] c[nC, nN][t] +
a[nC, nN + 1, 0, 1]*c[nC, nN + 1][t])];
nC = nCmax; nN = 0;
Eqk[nC,
nN] = (-b[nC, nN, 0, 1]*c[nC, nN][t] +
a[nC, nN + 1, 0, 1]*c[nC, nN + 1][t]) + (b[nC - 1, nN, 1, 0]*
c[nC - 1, nN][t] - a[nC, nN, 1, 0]*c[nC, nN][t]);
nC = 0; nN = nNmax;
Eqk[nC,
nN] = (-b[nC, nN, 1, 0]*c[nC, nN][t] +
a[nC + 1, nN, 1, 0]*c[nC + 1, nN][t]) + (b[nC, nN - 1, 0, 1]*
c[nC, nN - 1][t] - a[nC, nN, 0, 1]*c[nC, nN][t]);
nC = nCmax; nN = nNmax;
Eqk[nC,
nN] = (b[nC, nN - 1, 0, 1]*c[nC, nN - 1][t] -
a[nC, nN, 0, 1]*c[nC, nN][t]) + (b[nC - 1, nN, 1, 0]*
c[nC - 1, nN][t] - a[nC, nN, 1, 0]*c[nC, nN][t]);
nC = 0; nN = 0;
CL[nC, nN] = c[nC, nN][tMin] == 0;
Eqk[nC, nN] = 0;
nC = \[Alpha]C; nN = 0;
CL[nC, nN] = c[nC, nN][tMin] == Cinit + c0;
Eqk[nC,
nN] = (-b[nC, nN, 1, 0]*c[nC, nN][t] +
a[nC + 1, nN, 1, 0]*c[nC + 1, nN][t]) + (-b[nC, nN, 0, 1]*
c[nC, nN][t] +
a[nC, nN + 1, 0, 1]*
c[nC, nN + 1][
t]) - (Sum[(b[x, y, nC, nN] - a[x, y, nC, nN])*
c[x, y][t], {x, 0, nCmax - 1}, {y, 0, nNmax}] +
Sum[(-a[nCmax, i, nC, nN]*c[nCmax, i][t]), {i, 0, nNmax}]);
nC = 0; nN = \[Alpha]N;
CL[nC, nN] = c[nC, nN][tMin] == Ninit + c0;
Eqk[nC,
nN] = (-b[nC, nN, 1, 0]*c[nC, nN][t] +
a[nC + 1, nN, 1, 0]*c[nC + 1, nN][t]) + (-b[nC, nN, 0, 1]*
c[nC, nN][t] +
a[nC, nN + 1, 0, 1]*
c[nC, nN + 1][
t]) - (Sum[(b[x, y, nC, nN] - a[x, y, nC, nN])*
c[x, y][t], {x, 0, nCmax}, {y, 0, nNmax - 1}] +
Sum[(-a[i, nNmax, nC, nN]*c[i, nNmax][t]), {i, 0, nCmax}]);];
Bc :=
Flatten[ParallelTable[
c[nC, nN], {nC, 0, nCmax}, {nN, 0, nNmax}]] // Evaluate];
DistributeDefinitions[Eq, CL];
Sys = Join[
Flatten[ParallelTable[
Eq[nC, nN], {nC, 0, nCmax}, {nN, 0, nNmax}]],
Flatten[ParallelTable[
CL[nC, nN], {nC, 0, nCmax}, {nN, 0, nNmax}]]] // Flatten //
Evaluate;
{Sys, Bc}];
tMin = 0; tMax = 7.75*10^5;
Here we have replaced only one equation Eq[nC_, nN_] := EqD[nC, nN] == tMax Eqk[nC, nN];
.Now we call
PrepareEquations[tMin, tMax, 2000, 200]; // AbsoluteTiming
And it takes {536.24, Null}
. Now we solve the system on {t, 0, 1}
:
RSol = NDSolve[Sys, Bc, {t, tMin, 1},
Method -> {"EquationSimplification" ->
"Residual"}]; // AbsoluteTiming
It takes only {1148.03, Null}
. Thus, we saved 9 minutes with a simple replacement t->tmax t
. However, if we can write the equation in matrix form, then we can use exponential Rosenbrock-type integrators. Then we can reduce the time to 1 minute.
Cinit = 0.439673 %
inside aModule
, which is obviously incorrect. Please notice%
doesn't represent percentage in Mathematica, it's the short form ofOut
. $\endgroup${Sys,Bc} = PrepareEquations[tMin,tMax,NoC,NoN];
take? "So, what does the optionMethod->{"EquationSimplification"->"Residual"}
really means?" We already have this post: mathematica.stackexchange.com/a/158519/1871 $\endgroup$