I define a test function in order to stop my While
loop:
J[g_, phiT_, y_] := NIntegrate[Dot[g[y], g[y]], {y, Ly, Uy}]/NIntegrate[Dot[phiT[y], phiT[y]], {y, Ly, Uy}];
where Ly
and Uy
are constants to specify the spatial domain, both g[y]
and phiT[y]
are functions that are obtained within a loop.
In my code, I want to evaluate and save J[[iter]]
continuously in the loop with an iterator iter
. Then J[[iter]]
will be used for stopping the While
loop as follows:
While[True,
(*some code here*)
J[[iter]] = J[g, phiT, y]; AppendTo[J, J[[iter]]];
If[Abs[J[[iter]] - J[[iter - 1]]] < acc, Break[]];
(*some code here*)
iter++;];
As indicated by @xzczd, J[[iter]] = J[g, phiT, y]
is meaningless.
My understanding is as follows:
J[[iter]]
means that one is going to access an element (indexed by iter
) of a list, named J
. However, J
is the name of a fucntion defined in the beginning. This is an apparent contradiction.
But I cannot figure out how to resolve this problem. The main reason, I think, is that I do not know how many loops are needed and that's why I used the While
loop.
In contrast, if I know how many loops are involved, then I can come up with, for example, the following code using Do
loop:
ti = 0; tf = 10; \[Delta]t = 0.01;
ItrNo = Round[(tf - ti)/\[Delta]t];
Jtest = ConstantArray[0, ItrNo - 1];
Do[(*some code here*);
Jtest[[iter]] = J[g, phiT, y];
(*some code here*),
{iter, ItrNo - 1}]
Can anybody help me? Thank you in advance!
Here is a small example, though may not be minimal, since I want to use pdetoode.
Please copy the function pdetoode
from the above link.
feqSolver[s_, T_, g_] := Module[{s0 = s, Tend = T, feqIC = g},
With[{\[Phi] = \[Phi][t, y]},
feq = {D[\[Phi], t] + y*D[\[Phi], y] -
D[\[Phi], {y, 2}] - (s0 - 1/20*y^2)*\[Phi] == 0};
fic = {\[Phi] == feqIC[y]} /. t -> 0;
fbc = {{\[Phi] == 0} /. y -> Ly, {\[Phi] == 0} /. y -> Uy};];
fptoofunc = pdetoode[\[Phi][t, y], t, grid, difforder];
fdel = #[[2 ;; -2]] &;
fode = fdel@fptoofunc@feq[[1]];
fodeic = fptoofunc@fic;
fodebc = fptoofunc@fbc;
fsollst = NDSolveValue[{fodebc, fodeic, fode},
Map[\[Phi], grid], {t, 0, Tend}];
fsol = ListInterpolation[Developer`ToPackedArray@#["ValuesOnGrid"] & /@ fsollst//Transpose, {Flatten@fsollst[[1]]["Grid"], grid}];
phisol[t_, y_] = \[Phi][t, y] /. \[Phi] -> fsol[[1]];]
s0 = 0.4; Tend = 5; acc = 10^-4;
Ly = -20; Uy = 20; iter = 1;
(*Random IC*)
SetAttributes[g0, Listable];
SeedRandom[1];
g0[y_?NumericQ] = BSplineFunction[Join[{0.}, RandomReal[{-1, 1}, 39], {0.}],
SplineClosed -> False][(y + 20)/40];
g[y] = g0[y];
J[g_, phiT_, y_] := g[y]/phiT[y];
While[True, gOld[y] = g[y];
phisol[t, y] = feqSolver[s0, Tend, gOld];
phiT[y] = phisol[Tend, y];
Jtest[[iter]] = J[g, phiT, y];
AppendTo[Jtest, Jtest[[iter]]];
If[Abs[Jtest[[iter]] - Jtest[[iter - 1]]] < acc, Break[]];
g[y] = -1/2*phiT[y];
iter++;];
J
doesn't need to be that complicated. You can even simplify it to e.g.J[x_]=x^2
. (The stopping criterion should be adjusted accordingly, of course. ) $\endgroup$Clear[J]; J[x_, y_] = x^2 + y; iter = 1; lst = {}; AppendTo[lst, J[iter, RandomReal[]]]; While[True, iter++; AppendTo[lst, J[iter, RandomReal[]]]; If[lst[[iter]] - lst[[iter - 1]] > 20, Break[]]]; lst
; 2. How does this sample work?:Clear[J]; J[x_, y_] = x^2 + y; iter = 1; J[iter] = J[iter, RandomReal[]]; While[True, iter++; J[iter] = J[iter, RandomReal[]]; If[J[iter] - J[iter - 1] > 20, Break[]]]; Print@DownValues[J]; Table[J[i], {i, 1, iter}]
$\endgroup$