How to improve the performance of this code - performance

I have implemented a code in Mathematica 9 to simulate a scattering problem, and I got really disappointed about its performance when compared to Matlab. Since I am a newbie in Mathematica, would someone give me clues here?
ClearAll["Global`*"];
integrand[k_, P0_, P1_, rho_, l_] = Module[{x, h},
x = P1*l + P0*(1. - l) - rho;
h = HankelH2[0, Norm[x, 2]*k];
h
];
innerInt[k_, P0_, P1_, rho_] := Module[{d, r, v, x},
d = Norm[P0 - P1, 2];(* distancia entre os pontos *)
v = integrand[k, P0, P1, rho, x];
r = NIntegrate[v, {x, 0, 1}]*d;
r
];
solveSystemCylinder[segsStart_, segsEnd_, Ei_, k_, eta_] :=
Module[{colocPts, r, x, t, eiVals},
colocPts = (segsStart + segsEnd)/2;
t[x_] := MapThread[innerInt[k, #1, #2, x] &, {segsStart, segsEnd}];
r = Map[t, colocPts];
eiVals = Map[Ei[#, k] &, colocPts];
N[LinearSolve[r, eiVals]]
];
Ei[p_, k_] := Exp[I*k*First[p]];
k := 2*Pi/Lambda;
Lambda := 1;
raio := Lambda;
eta := 1;
ND := 30;(* num de divisões *)
pts := N[raio*{Cos[#], Sin[#]} & /# (Range[0, ND]*(2*Pi/ND))];
pts2 := ({0, 2*Lambda} + #) & /# pts;
allPts := Join[pts, pts2];
startPts := Take[pts, Length[pts] - 1];
endPts := Take[pts, -(Length[pts] - 1)];
startPts2 := Take[pts2, Length[pts2] - 1];
endPts2 := Take[pts2, -(Length[pts2] - 1)];
(*resolve*)
Js = solveSystemCylinder[Join[startPts, startPts2],
Join[endPts, endPts2], Ei, k, eta];

Related

Mathematica: Error fitting function to data using NIntegrate and ' (differentiation)

I've been trying to fit a function to a data set. IT works with functions without integrals (like NIntegrate) and differentiations ( ' ). I'm trying to get it to work using both integrals and differentiations:
deltaData = {{1.00, 0}, {0.96, 0.3416}, {0.92, 0.4749}, {0.88, 0.5715}, {0.84, 0.648}, {0.80, 0.711}, {0.76, 0.764}, {0.72, 0.8089}, {0.66, 0.864}, {0.62, 0.8939}, {0.58, 0.919}, {0.54, 0.9399}, {0.50, 0.9569}, {0.46, 0.9704}, {0.42, 0.9809}, {0.38, 0.9885}, {0.34, 0.9938}, {0.30, 0.9971}, {0.26, 0.9989}, {0.22, 0.9997}, {0.16, 1}, {0.14, 1}};
deltaFit =
NonlinearModelFit[
deltaData, (1 + a*T + c*T^2 + e*T^3 + g*T^4 + i*T^5 + k*T^6)/(1 +
b*T + d*T^2 + f*T^3 + h*T^4 + j*T^5 + l*T^6), {a, b, c, d, e, f,
g, h, i, j, k, l}, T];
Plot[deltaFit[T], {T, 0, 1}]
data = {{0.203, 0.031}, {0.203, 0.030}, {0.246, 0.055}, {0.267, 0.072}, {0.300, 0.105}, {0.300, 0.105}, {0.330, 0.147}, {0.373, 0.214}, {0.397, 0.255}, {0.415, 0.293}, {0.445, 0.351}, {0.477, 0.430}, {0.493, 0.463}, {0.520, 0.538}, {0.541, 0.590}, {0.582, 0.717}, {0.589, 0.733}, {0.625, 0.847}, {0.645, 0.911}, {0.685, 1.029}, {0.688, 1.043}, {0.730, 1.181}, {0.751, 1.247}, {0.782, 1.338}, {0.793, 1.375}, {0.830, 1.472}, {0.856, 1.531}, {0.878, 1.585}};
AlphaBCS = 1.746;
delta[T_, p_, alpha_] := p*deltaFit[T] + (1 - p)*deltaFit[T]/alpha;
fx[T_, x_, p_, alpha_] := (Exp[AlphaBCS/T*(x^2 + delta[T, p, alpha]^2)^(1/2)] + 1)^(-1);
Ses[T_, p_, alpha_] := -6*AlphaBCS/Pi^2* NIntegrate[fx[T, x, p, alpha]*Log[fx[T, x, p, alpha]] + (1 - fx[T, x, p, alpha])*Log[1 - fx[T, x, p, alpha]], {x, 0,100}];
Ces[T_, p_, alpha_] := T*Ses'[T, p, alpha];
cesFit = NonlinearModelFit[data, Ces[T, p, alpha], {{p, 0.5}, {alpha, 1.764}}, T];
I don't know why I'm getting an Error as the code is working in the first fit I'm performing. This is the error message:
The function value ... a bunch of numbers ... Ses' ... more numbers ... is not a list of real numbers with dimensions {28} at {p,alpha} = {0.5`,1.764`}.
Does anybody know what I'm doing wrong? Is there anything I can replace the fit or integral with to make this work?
#Bill: Thank you for pointing that out! Here is my corrected code:
dSes[T_, p_, alpha_] = D[Ses[T, p, alpha], T];
Ces[T_, p_, alpha_] := T*dSes[T, p, alpha];
now the differentiation works. But when I run the fit, I get the following error:
a long list of numbers, brackets, Compile'$... is not a list of real numbers with dimensions {28} at {p,alpha} = {0.5,1.764}.

How can i fix a multiplicity issue in mathematica 10.0 loop?

I am solving a project in Mathematica 10 and I think that the best way to do it is using a loop like For or Do. After build it I obtain the results I looking for but with a to much big multiplicity. Here is the isolated part of the code:
(*Initializing variables*)
epot[0] = 1; p[0] = 1; \[Psi][0] = HermiteH[0, x] E^(-(x^2/2));
e[n_] := e[n] = epot[n];
(*Defining function*)
\[Psi][n_] := \[Psi][n] = (Sum[p[k]*x^k,{k,0,4*n}]) [Psi][0];
(*Differential equation*)
S = - D[D[\[Psi][n], x], x] + x^2 \[Psi][n] + x^4 \[Psi][n - 1] - Sum[e[n-k]*\[Psi][k],{k,0,n}];
(*Construction of the loop*)
S1 = Collect[E^(x^2/2) S, x, Simplify];
c = Coefficient[S1, x, 0];
sol = Solve[c == 0, epot[n]]; e[n] = epot[n] /. sol;
For[j = 1, j <= 4 n, j++,
c = Coefficient[S1, x, j];
sol = Solve[c == 0, p[j]];
p[j] = p[j] /. sol;];
(*Results*)
Print[Subscript[e, n], "= ", e[n] // InputForm];
Subscript[e, 1]= {{{3/4}}}
Print[ArrayDepth[e[n]]];
3 (*Multiplicity, it should be 1*)
Print[Subscript[\[Psi], n], "= ", \[Psi][n]];
Subscript[\[Psi], 1]= {{E^(-(x^2/2)) (1-(3 x^2)/8-x^4/8)}}
Print[ArrayDepth[\[Psi][n]]];
2 (*Multiplicity, it should be 1*)
After this calculation, the question remaining is how do i substitute this results in the original functions. Thank you very much.

a width of interval on each step of iteration

Tell me please , is in Mathematica a standard function which can find a width of interval?
I have to find it for each iteration.
(*Newton's method*)
step[f_, iter_, inter_] :=
Module[{x = Mean#First#(List ## inter)//N},
Print["Iteration ", iter, ".\n", "Interval is: ", inter,
"; \nx0_=", x, "; \nf(x0_)=", f[x], "; \nf'(interval)=", f'[inter],
";","\nIntervalsWidth=",(*??????????*),"\nX1=",IntervalIntersection[inter, x - (f[x])/(f'[inter])]]; IntervalIntersection[inter, x - (f[x])/(f'[inter])]]
newton[f_, inter0_, eps_] :=
Module[{iter = 0},
N#Mean#First#(List ##
NestWhile[(++iter; step[f, iter, #]) &, inter0,
Abs[Subtract ## First#(List ## #)] > eps &])];
f[x_] := x*x - 8*x + 7 ;
inter := Interval[{5, 17}] ;
newton[f, inter, 0.00001];
//////tried to do
(*Newton's method*)
step[f_, iter_, {a_, b_}] :=
Module[{inter = Interval[{a, b}],x =(a+b)/2},
Print["Iteration ", iter, ".\n", "Interval is: ", inter,";\nIntervalsWidth=",b-a,
"; \nx0_=", x, "; \nf(x0_)=", f[x], "; \nf'(interval)=", f'[inter],
";","\nX1=",IntervalIntersection[inter, x - (f[x])/(f'[inter])]]; IntervalIntersection[inter, x - (f[x])/(f'[inter])]]
newton[f_, {a_, b_}, eps_] :=
Module[{iter = 0},
N#Mean#First#(List ##
NestWhile[(++iter; step[f, iter, #]) &, {a,b},
Abs[b-a] > eps &])];
f[x_] := x*x - 8*x + 7 ;
newton[f, {5, 17}, 0.00001];

Efficient numerical calculation of 2d data sets

I'm trying to calculate the fourier transform of a gaussian beam. Later I want to ad some modifications to the following example code. With the required stepsize of 1e-6 the calculation with 8 kernel takes 1244s on my workstation. The most consuming part is obviously the generation of uaperture. Has anyone ideas to improve the performance? Why does mathematica not create a packed list from my expression, when I'm having both real and complex values in it?
uin[gx_, gy_, z_] := Module[{w0 = L1[[1]], z0 = L1[[3]], w, R, \[Zeta], k},
w = w0 Sqrt[1 + (z/z0)^2];
R = z (1 + (z0/z)^2);
\[Zeta] = ArcTan[z/z0];
k = 2*Pi/193*^-9;
Developer`ToPackedArray[
ParallelTable[
w0/w Exp[-(x^2 + y^2)/w^2] Exp[-I k/2/R (x^2 + y^2)/2] Exp[-I k z*0 +
I \[Zeta]*0], {x, gx}, {y, gy}]
]
]
AbsoluteTiming[
dx = 1*^-6;
gx = Range[-8*^-3, 8*^-3, dx];
gy = gx;
d = 15*^-3;
uaperture = uin[gx, gy, d];
ufft = dx*dx* Fourier[uaperture];
uout = RotateRight[
Abs[ufft]*dx^2, {Floor[Length[gx]/2], Floor[Length[gx]/2]}];
]
Thanks in advance,
Johannes
You can speed it up by first vectorizing it (uin2), then compiling it (uin3):
In[1]:= L1 = {0.1, 0.2, 0.3};
In[2]:= uin[gx_, gy_, z_] :=
Module[{w0 = L1[[1]], z0 = L1[[3]], w, R, \[Zeta], k},
w = w0 Sqrt[1 + (z/z0)^2];
R = z (1 + (z0/z)^2);
\[Zeta] = ArcTan[z/z0];
k = 2*Pi/193*^-9;
ParallelTable[
w0/w Exp[-(x^2 + y^2)/
w^2] Exp[-I k/2/R (x^2 + y^2)/2] Exp[-I k z*0 +
I \[Zeta]*0], {x, gx}, {y, gy}]
]
In[3]:= uin2[gx_, gy_, z_] :=
Module[{w0 = L1[[1]], z0 = L1[[3]], w, R, \[Zeta], k, x, y},
w = w0 Sqrt[1 + (z/z0)^2];
R = z (1 + (z0/z)^2);
\[Zeta] = ArcTan[z/z0];
k = 2*Pi/193*^-9;
{x, y} = Transpose[Outer[List, gx, gy], {3, 2, 1}];
w0/w Exp[-(x^2 + y^2)/
w^2] Exp[-I k/2/R (x^2 + y^2)/2] Exp[-I k z*0 + I \[Zeta]*0]
]
In[4]:= uin3 =
Compile[{{gx, _Real, 1}, {gy, _Real, 1}, z},
Module[{w0 = L1[[1]], z0 = L1[[3]], w, R, \[Zeta], k, x, y},
w = w0 Sqrt[1 + (z/z0)^2];
R = z (1 + (z0/z)^2);
\[Zeta] = ArcTan[z/z0];
k = 2*Pi/193*^-9;
{x, y} = Transpose[Outer[List, gx, gy], {3, 2, 1}];
w0/w Exp[-(x^2 + y^2)/
w^2] Exp[-I k/2/R (x^2 + y^2)/2] Exp[-I k z*0 + I \[Zeta]*0]
],
CompilationOptions -> {"InlineExternalDefinitions" -> True}
];
In[5]:= dx = 1*^-5;
gx = Range[-8*^-3, 8*^-3, dx];
gy = gx;
d = 15*^-3;
In[9]:= r1 = uin[gx, gy, d]; // AbsoluteTiming
Out[9]= {67.9448862, Null}
In[10]:= r2 = uin2[gx, gy, d]; // AbsoluteTiming
Out[10]= {28.3326206, Null}
In[11]:= r3 = uin3[gx, gy, d]; // AbsoluteTiming
Out[11]= {0.4190239, Null}
We got a ~160x speedup even though this is not running in parallel.
Results are the same:
In[12]:= r1 == r2
Out[12]= True
There's a tiny difference here due to numerical errors:
In[13]:= r2 == r3
Out[13]= False
In[14]:= Max#Abs[r2 - r3]
Out[14]= 5.63627*10^-14

1)a workaround for "NMaximize" error "function unbounded." but don't know why 2) more importantly, how to speed up this 3d region plot (see update2)

When I was trying to find the maximum value of f using NMaximize, mathematica gave me a error saying
NMaximize::cvdiv: Failed to converge to a solution. The function may be unbounded.
However, if I scale f with a large number, say, 10^5, 10^10, even 10^100, NMaximize works well.
In the two images below, the blue one is f, and the red one is f/10^10.
Here come my questions:
Is scaling a general optimization trick?
Any other robust, general workarounds for the optimizations such
needle-shape functions?
Because the scaling barely changed the shape of the needle-shape of
f, as shown in the two images, how can scaling work here?
thanks :)
Update1: with f included
Clear["Global`*"]
d = 1/100;
mu0 = 4 Pi 10^-7;
kN = 97/100;
r = 0.0005;
Rr = 0.02;
eta = 1.3;
e = 3*10^8;
s0 = 3/100;
smax = 1/100; ks = smax/s0;
fre = 1; tend = 1; T = 1;
s = s0*ks*Sin[2*Pi*fre*t];
u = D[s, t];
umax = N#First[Maximize[u, t]];
(*i=1;xh=0.1;xRp=4.5`;xLc=8.071428571428573`;
i=1;xh=0.1;xRp=4.5;xLc=8.714285714285715;*)
i = 1; xh = 0.1; xRp = 5.5; xLc = 3.571428571428571`;
(*i=1;xh=0.1`;xRp=5.`;xLc=6.785714285714287`;*)
h = xh/100; Rp = xRp/100; Lc = xLc/100;
Afai = Pi ((Rp + h + d)^2 - (Rp + h)^2);
(*Pi (Rp-Hc)^2== Afai*)
Hc = Rp - Sqrt[Afai/Pi];
(*2Pi(Rp+h/2) L/2==Afai*)
L = (2 Afai)/(\[Pi] (h + 2 Rp));
B = (n mu0 i)/(2 h);
(*tx = -3632B+2065934/10 B^2-1784442/10 B^3+50233/10 B^4+230234/10 \
B^5;*)
tx = 54830.3266978739 (1 - E^(-3.14250266080741 B^2.03187556833859));
n = Floor[(kN Lc Hc)/(Pi r^2)] ;
A = Pi*(Rp^2 - Rr^2);
b = 2*Pi*(Rp + h/2);
(* -------------------------------------------------------- *)
Dp0 = 2*tx/h*L;
Q0 = 0;
Q1 = ((1 - 3 (L tx)/(Dp h) + 4 (L^3 tx^3)/(Dp^3 h^3)) Dp h^3)/(
12 eta L) b;
Q = Piecewise[{{Q1, Dp > Dp0}, {Q0, True}}];
Dp = Abs[dp[t]];
ode = u A - A/e ((s0^2 - s^2)/(2 s0 )) dp'[t] == Q*Sign[dp[t]];
sol = First[
NDSolve[{ode, dp[0] == 0}, dp, {t, 0, tend} ,
MaxSteps -> 10^4(*Infinity*), MaxStepFraction -> 1/30]];
Plot[dp''[t] A /. sol, {t, T/4, 3 T/4}, AspectRatio -> 1,
PlotRange -> All]
Plot[dp''[t] A /10^10 /. sol, {t, T/4, 3 T/4}, AspectRatio -> 1,
PlotRange -> All, PlotStyle -> Red]
f = dp''[t] A /. sol;
NMaximize[{f, T/4 <= t <= 3 T/4}, t]
NMaximize[{f/10^5, T/4 <= t <= 3 T/4}, t]
NMaximize[{f/10^5, T/4 <= t <= 3 T/4}, t]
NMaximize[{f/10^10, T/4 <= t <= 3 T/4}, t]
update2: Here comes my real purpose. Actually, I am trying to make the following 3D region plot. But I found it is very time consuming (more than 3 hours), any ideas to speed up this region plot?
Clear["Global`*"]
d = 1/100;
mu0 = 4 Pi 10^-7;
kN = 97/100;
r = 0.0005;
Rr = 0.02;
eta = 1.3;
e = 3*10^8;
s0 = 3/100;
smax = 1/100; ks = smax/s0;
f = 1; tend = 1/f; T = 1/f;
s = s0*ks*Sin[2*Pi*f*t];
u = D[s, t];
umax = N#First[Maximize[u, t]];
du[i_?NumericQ, xh_?NumericQ, xRp_?NumericQ, xLc_?NumericQ] :=
Module[{Afai, Hc, L, B, tx, n, A, b, Dp0, Q0, Q1, Q, Dp, ode, sol,
sF, uF, width, h, Rp, Lc},
h = xh/100; Rp = xRp/100; Lc = xLc/100;
Afai = Pi ((Rp + h + d)^2 - (Rp + h)^2);
Hc = Rp - Sqrt[Afai/Pi];
L = (2 Afai)/(\[Pi] (h + 2 Rp));
B = (n mu0 i)/(2 h);
tx = 54830.3266978739 (1 - E^(-3.14250266080741 B^2.03187556833859));
n = Floor[(kN Lc Hc)/(Pi r^2)] ;
A = Pi*(Rp^2 - Rr^2);
b = 2*Pi*(Rp + h/2);
Dp0 = 2*tx/h*L;
Q0 = 0;
Q1 = ((1 - 3 (L tx)/(Dp h) + 4 (L^3 tx^3)/(Dp^3 h^3)) Dp h^3)/(
12 eta L) b;
Q = Piecewise[{{Q1, Dp > Dp0}, {Q0, True}}];
Dp = Abs[dp[t]];
ode = u A - A/e ((s0^2 - s^2)/(2 s0 )) dp'[t] == Q*Sign[dp[t]];
sol = First[
NDSolve[{ode, dp[0] == 0}, dp, {t, 0, tend} , MaxSteps -> 10^4,
MaxStepFraction -> 1/30]];
sF = ParametricPlot[{s, dp[t] A /. sol}, {t, 0, tend},
AspectRatio -> 1];
uF = ParametricPlot[{u, dp[t] A /. sol}, {t, 0, tend},
AspectRatio -> 1];
tdu = NMaximize[{dp''[t] A /10^8 /. sol, T/4 <= t <= 3 T/4}, {t,
T/4, 3 T/4}, AccuracyGoal -> 6, PrecisionGoal -> 6];
width = Abs[u /. tdu[[2]]];
{uF, width, B}]
RegionPlot3D[
du[1, h, Rp, Lc][[2]] <= umax/6, {h, 0.1, 0.2}, {Rp, 3, 10}, {Lc, 1,
10}, LabelStyle -> Directive[18]]
NMaximize::cvdiv is issued if the optimum improved a couple of orders of magnitude during the optimization process, and the final result is "large" in an absolute sense. (To prevent the message in a case where we go from 10^-6 to 1, for example.)
So yes, scaling the objective function can have an effect on this.
Strictly speaking this message is a warning, and not an error. My experience is that if you see it, there's a good chance that your problem is unbounded for some reason. In any case, this warning is a hint that you might want to double check your system to see if that might be the case.

Resources