I am doing an iterative program, which uses large arrays/vectors and where the output of one round is used as an input for the next steps but works slowly when dimensions are bigger. In brief, we create firstly the complex matrix s (dimension dos x dos) using SparseArray
dos=101;
s = SparseArray[{{i_, i_} :> 1. + I, Band[{2, 1}] -> 2.,
Band[{1, 2}] -> 2., Band[{dos + 1, 1}] -> 2.0,
Band[{1, dos + 1}] -> 2.0}, {dos*dos, dos*dos}, 0.];
And initial condition
input=ConstantArray[1,{dos,dos}];
input=Flatten[input];
u1=input;
And finally, we do the iterative steps following some conditions/rules related to which position in the array is used
lr = Table[i, {i, 1 + dos, dos*dos - dos, dos}];
ll = Table[i, {i, dos + dos, dos*dos - dos, dos}];
lt = Table[i, {i, 1, dos, 1}];
lb = Table[i, {i, dos*dos - dos + 1, dos*dos, 1}];
lll = Sort[Join[lr, ll, lt, lb]]; (*rules*)
steps=50;
Do[f = SparseArray[{{i_} :>
If[MemberQ[lll, i],
0, -2.0*u1[[i - 1]] - 2.0*u1[[i + 1]] - 2.0*u1[[i + dos]] -
2.0*u1[[i - dos]] + (1.+I)*u1[[i]]]}, {dos*dos}];
u1 = LinearSolve[s, f];, {j, 1, steps, 1}]
This takes around 15 sec on my computer but with increasing dimensions, the time needed grows quickly. I noticed that applying LinearSolve is not slow, but creating the array f is where almost all the time is consumed. Is there a way to create f more efficiently? I tried to use Compile but not good results. Thanks in advance
SparseArray
. Have you enabled Evaluation>Debugger to see the timings of each call? $\endgroup$Do
ing theLinearSolve
50 times? Presumablyj
should be referenced somewhere in the loop. I think your construction off
can be simplified by looking at small cases, and I thinkSparseArray
isn't helping at all since you're manually specifying even 0 elements. The speedup ofSparseArray
comes from specifying only a few nonzero ones. $\endgroup$SparseArray
not helping at all since I am manually specifying elements, I didn't know that, but for the moment is my fastest way to createf
. $\endgroup$sinv = LinearSolve[s];
once. This will compute and store an LU-factorization ofs
. In the loop, you can simply useu1 = sinv[f];
unstead ofu1 = LinearSolve[s, f];
. On my machine, this gets down the solve time from 3 seconds to only0.06
seconds for the factorization and0.08
seconds all the solves in the loop. $\endgroup$