The solution to Laplace PDE on rectangle is usually written using hyperbolic trig functions. I solve this PDE using Maple. Verified Maple solution is correct. But having hard time figuring how to make its result match the book result.
I tried sol:=convert(rhs(sol),trigh): then simplify(sol,trig); and it become little closer to the book solution, but is still can be more simplified.
Are there any tricks to do this?
Here is MWE
restart;
interface(showassumed=0):
pde:=diff(u(x,y),x$2)+diff(u(x,y),y$2)=0:
bc:=u(0,y)=0,u(a,y)=f(y),u(x,0)=0,u(x,b)=0:
sol:=pdsolve([pde,bc],u(x,y)) assuming(0<=x and x<=a and 0<=y and y<=b):
sol:=subs(infinity=20,sol);
Which gives
The above is same as the following, which I am trying to convert the above to
textbookU:= Sum(2*sin(n*Pi*y/b)*(Int(sin(n*Pi*y/b)*f(y),
y = 0 .. b))*sinh(n*Pi*x/b)/(b*sinh(n*Pi*a/b)), n = 1 .. 20);
The above are the same. I checked few points, and they give same answer. They must be the same, as the above textbook solution is correct, and I am assuming Maple solution is correct.
Now I tried to convert Maple sol to the above as follows
sol:=convert(rhs(sol),trigh):
simplify(sol,trig);
May be someone knows a better way to obtain the textbook solution form, starting from the Maple solution above.
Using Maple 2017.3 on windows
After the convert you can first expand it, to then simplify it again:
s := convert(sol, trigh):
s := expand(s):
simplify(s);
which gives:
Last week I asked the following:
https://stackoverflow.com/questions/32658199/vectorizing-gibbs-sampler-in-matlab
Perhaps it was not that clear what I want to do, so this might be more clear.
I would like to vectorize a "for" loop in matlab, where some variables inside of the loop are bidirectionally related. So, here is an example:
A=2;
B=3;
for i=1:10000
A=3*B;
B=exp(A*(-1/2))
end
Thank you once again for your time.
A quick Excel calculation indicates that this quickly converges to 0.483908 (after much less than 10000 loops - so one way of speeding it up would be to check for convergence). If A and B are always 2 and 3 respectively, you could just replace the loop with this value.
Alternatively, using some series analysis you might be able to come up with an analytical expression for B when i is large - although with the nested exponents deriving this is a bit beyond my own abilities!
Edit
A bit of googling reveals this. Wikipedia states that for a tetration of x to infinity (i.e. x^x^x^x^x...), the solution y satisfies y = x^y. In your case, for example, 0.483908 = e^(-3/2)^0.483908, so 0.483908 is a solution. Not sure how you would exploit this though.
Wikipedia also gives a convergence condition, which might be of use to you: x lies between e^-e and e^1/e.
Final Edit (?)
Turns out you need Lambert's W function to solve for equations of the form of y = x^y. There seems to be no native function for this, but there seems to be something in the FileExchange - see here and here.
I am using MATLAB to execute a triple integral using integral3 and it is running very slow. I was wondering if there ways to speed it. I am guessing its due to the fact that I set the abstol wrong. Not sure how to handle it. PS the code below works with no syntax error. There are a couple of things I dont know how to pick, abstol, method etc..
clear all
syms gamma1
syms gamma2
syms z
syms v
Nt=16; sigmanoise=10^(-7.9); c3=0.129; c1=(1-c3)/2;a2=0;b2=0;
a1=0.0030; b1= 0.0030; A1= 1.5625e-04,A2=0; B1= 7.8125e-05;B2=0;
theta= 3.1623;lambda1= 4.9736e-05;lambda2=0;p1=1;p2=0; alpha1=2; alpha2=4;delta1=2/alpha1; delta2=2/alpha2;beta1=0.025; beta2=0.025;
a= gamma1^-1+gamma2^-1+2*gamma1^(-0.5)*gamma2^(-0.5);
laplacesgi=(exp(+2*pi*j.*z*a)-1)./(2*pi*j*z);
laplacesgi=matlabFunction(laplacesgi);
laplacenoi=exp(-2*pi*j.*z*theta*sigmanoise/Nt);
laplacenoi=matlabFunction(laplacenoi);
interfere= #(gamma1,gamma2,v,z)( (1 -2*c1-c3./(1+2*pi*j*z*theta*v.^(-1))).*(A1.*(v).^(delta1-1).*exp(-a1.*(v).^ (delta1./2))+B1.*(v).^(delta2-1) .*(1-exp(-b1.*(v).^ (delta2./2)))));
gscalar =#(gamma1,gamma2,z)integral(#(v)(interfere(gamma1,gamma2,v,z)),gamma2,inf);
g = #(gamma1,gamma2,z)arrayfun(gscalar,gamma1,gamma2,z);
lp= A1*(gamma1)^(delta1-1)*exp(-a1*(gamma1)^ (delta1/2))+B1*(gamma1)^(delta2-1)*(1-exp(-b1*(gamma1)^ (delta2/2)))+A2*gamma1^(delta1-1)*exp(-a2*gamma1^(delta1/2))+ B2*gamma1^(delta2-1)*(1-exp(-b2*gamma1^ (delta2/2)));%;
dk1=((2*pi*lambda1))/(beta1^2)*(1-exp(-a1*(gamma2)^(delta1/2))*(1+(gamma2)^(delta1/2)*a1))+ pi*lambda1*gamma2^(delta2)*p1^delta2-((2*pi*lambda1)/(beta1^2))*(1-exp(-b1*(gamma2)^(delta2/2))*(1+(gamma2)^(delta2/2)*b1));
dk2=((2*pi*lambda2))/(beta2^2)*(1-exp(-a2*(gamma2)^(delta1/2))*(1+(gamma2)^(delta1/2)*a2))+ pi*lambda2*gamma2^(delta2)*p2^delta2-((2*pi*lambda2)/(beta2^2))*(1-exp(-b2*(gamma2)^(delta2/2))*(1+(gamma2)^(delta2/2)*b2));
dk=dk1+dk2;
lcp= A1*(gamma2)^(delta1-1)*exp(-a1*(gamma2)^ (delta1/2))+B1*(gamma2)^(delta2-1)*(1-exp(-b1*(gamma2)^ (delta2/2)))+A2*gamma2^(delta1-1)*exp(-a2*gamma2^ (delta1/2))+ B2*gamma2^(delta2-1)*(1-exp(-b2*gamma2^(delta2/2)));%;
pdflast=lp*lcp*exp(-dk);
pdflast=matlabFunction(pdflast);
pdflast= #(gamma1,gamma2)arrayfun(pdflast,gamma1,gamma2);
gamma2min=#(gamma1)gamma1;
warning('off','MATLAB:integral:MinStepSize');
T = integral3(#(gamma1,gamma2,z)(laplacenoi(z).*laplacesgi(gamma1,gamma2,z).*pdflast(gamma1,gamma2).*exp(-g(gamma1,gamma2,z))),0,inf,#(gamma2)gamma2,inf,0.05,1000,'abstol',1e-3)
I appreciate any ideas or suggestions.
This is getting way too long for a comment, and while it doesn't really give an answer either, I think it may be helpful anyway, so I will slightly abuse the answer form for it.
Code Readability
I don't think your code as it stands fulfills the basic fundamental purpose of code: Communicating with a human being, probably yourself down the road.
I don't know if the variable names are unambiguous enough that in six months, they will still tell you exactly what is what. If they are, great. If not, you may want to improve upon them. (And yes, naming stuff is one of the hardest parts of programming, but that doesn't make it less important.)
The same holds true for comments: If you don't need comments on your formulas, more power to you. I have no idea what you are computing, so the fact that I don't understand your formulas doesn't mean much. But again, think of yourself in a few months, looking for a problem: Would you have wished for a comment such that you know if that factor is really correct or off by one?
Here's something I do know: Your formulas are simply too wide to be comprehended at once. Simple reformatting helps to see the structure better. Here's how I reformatted your code to start making heads or tails from it:
clear all
syms gamma1
syms gamma2
syms z
syms v
Nt=16;
sigmanoise=10^(-7.9);
c3=0.129;
c1=(1-c3)/2;
a2=0;
b2=0;
a1=0.0030;
b1=0.0030;
A1=1.5625e-04;
A2=0;
B1=7.8125e-05;
B2=0;
theta=3.1623;
lambda1=4.9736e-05;
lambda2=0;
p1=1;
p2=0;
alpha1=2;
alpha2=4;
delta1=2/alpha1;
delta2=2/alpha2;
beta1=0.025;
beta2=0.025;
a=gamma1^(-1)+gamma2^(-1)+2*gamma1^(-0.5)*gamma2^(-0.5);
laplacesgi=matlabFunction((exp(2*pi*1j*z*a)-1)./(2*pi*1j*z));
laplacenoi=matlabFunction(exp(-2*pi*1j*z*theta*sigmanoise/Nt));
interfere= #(gamma1,gamma2,v,z)( ...
(1 -2*c1-c3./(1+2*pi*j*z*theta*v.^(-1))).*(A1.*v.^(delta1-1).* ...
exp(-a1.*v.^(delta1./2))+B1.*v.^(delta2-1).*(1-exp(-b1.*v.^(delta2./2)))));
gscalar=#(gamma1,gamma2,z)integral(#(v)(interfere(gamma1,gamma2,v,z)),gamma2,inf);
g=#(gamma1,gamma2,z)arrayfun(gscalar,gamma1,gamma2,z);
lp=A1*gamma1^(delta1-1)*exp(-a1*gamma1^(delta1/2))+ ...
B1*gamma1^(delta2-1)*(1-exp(-b1*gamma1^(delta2/2)))+ ...
A2*gamma1^(delta1-1)*exp(-a2*gamma1^(delta1/2))+ ...
B2*gamma1^(delta2-1)*(1-exp(-b2*gamma1^(delta2/2)));
dk1=((2*pi*lambda1))/(beta1^2)*(1-exp(-a1*gamma2^(delta1/2))*(1+gamma2^(delta1/2)*a1))+ ...
pi*lambda1*gamma2^(delta2)*p1^delta2- ...
((2*pi*lambda1)/(beta1^2))*(1-exp(-b1*gamma2^(delta2/2))*(1+gamma2^(delta2/2)*b1));
dk2=((2*pi*lambda2))/(beta2^2)*(1-exp(-a2*gamma2^(delta1/2))*(1+gamma2^(delta1/2)*a2))+ ...
pi*lambda2*gamma2^(delta2)*p2^delta2- ...
((2*pi*lambda2)/(beta2^2))*(1-exp(-b2*gamma2^(delta2/2))*(1+gamma2^(delta2/2)*b2));
dk=dk1+dk2;
lcp=A1*gamma2^(delta1-1)*exp(-a1*gamma2^(delta1/2))+ ...
B1*gamma2^(delta2-1)*(1-exp(-b1*gamma2^(delta2/2)))+ ...
A2*gamma2^(delta1-1)*exp(-a2*gamma2^(delta1/2))+ ...
B2*gamma2^(delta2-1)*(1-exp(-b2*gamma2^(delta2/2)));
pdflast=matlabFunction(lp*lcp*exp(-dk));
pdflast=#(gamma1,gamma2)arrayfun(pdflast,gamma1,gamma2);
gamma2min=#(gamma1)gamma1;
T = integral3(#(gamma1,gamma2,z)( ...
laplacenoi(z).*laplacesgi(gamma1,gamma2,z).*pdflast(gamma1,gamma2).*exp(-g(gamma1,gamma2,z))), ...
0,inf,...
#(gamma2)gamma2,inf,...
0.05,1000,...
'abstol',1e-3)
A few notes one this:
MATLAB is one of the languages that require an indication that the logical line should continue after the physical line break. The indication in MATLAB is three dots.
Get rid of any and all warnings the MATLAB editor shows you. In very rare cases, by disabling the warning for this line; usually, by correcting your code. Some of these warnings may seem over-protective, but coe quickly reaches the point where none of us can have enough of it in our minds to see the more subtle problems, and linting helps avoid a fair number of them, in my experience.
Consistent spacing helps, in the same way “proper” (i.e., standardized) spelling makes reading English easier: The patterns are just much more obvious.
Line breaks should in general not be done haphazardly, but emphasizing the structure of commands and formulas. In several of your formulas, I have seen symmetries between input parameters and tried to make them obvious by placing the line breaks accordingly. That helps a lot when looking for typos.
Your code has lines such as these:
pdflast=lp*lcp*exp(-dk);
pdflast=matlabFunction(pdflast);
I used to recycle variables like that, too. Over time, I learned the hard way that it helps for debugging and readability not to, especially if your values have different types, as they do here.
There are a few points I would still clean up at this point. For example, pdflast works just fine on arrays and the line pdflast= #(gamma1,gamma2)arrayfun(pdflast,gamma1,gamma2); should be deleted, and the lower bound for gamma2 in the integral3 call is a function of gamma1 and should be changed to #(gamma1)gamma1.
Does the computer/MATLAB care about any of this? Maybe something slipped in where it does, but basically: No. All of these changes are for you, and if you send your code in an SO post, for us, the readers.
(Likely) Bug: Vectorization
I think your definition of g is wrong:
g=#(gamma1,gamma2,z)arrayfun(gscalar,gamma1,gamma2,z);
The cubature (i.e., integral3) will try to call this function with non-scalar values for one or more of the parameters. Most likely, these will not all be of the same size, and even if they were, it would expect to get a 3D result, not a vector. Try calling your g that way:
>> g(1:2,1,1)
Error using arrayfun
All of the input arguments must be of the same size and shape.
Previous inputs had size 2 in dimension 2. Input #3 has size 1
Error in #(gamma1,gamma2,z)arrayfun(gscalar,gamma1,gamma2,z)
It's really a good idea to check intermediate building blocks like that. What your really need to have is an arrayfun over gamma2, something like this:
gscalar=#(gamma1,gamma2,z) ...
integral(#(v)(interfere(gamma1,gamma2,v,z)),gamma2,inf, ...
'ArrayValued',true);
g = #(gamma1,gamma2,z)arrayfun(#(gamma2)gscalar(gamma1,gamma2,z),gamma2);
(Possible) Bug: Definition of interfere
I don't know if you tried checking interfere against any known or suspected values. (Sanity checks for formulas I just typed seem a really good idea to me.) I somehow doubt that the formula is correctly capturing your intent:
interfere=#(gamma1,gamma2,v,z)( ...
(1-2*c1-c3./(1+2*pi*1j*z*theta*v.^(-1))).*(A1.*v.^(delta1-1).* ...
exp(-a1.*v.^(delta1./2))+B1.*v.^(delta2-1).*(1-exp(-b1.*v.^(delta2./2)))));
The potential problem with this formula (apart from a somewhat inconsistent use of * vs. .* etc.) is that the values do not depend on gamma1 and gamma2 at all.
Of course, that can happen, but if you actually mean it to be the case, what is the rationale for including gamma1 in the formula in the first place?
If this is as it should be, you may need to still make the result the proper size: Right now, interfere simply ignores its first two inputs, which may trip up the integrator: interfere(1:3,1,1,1) should return a 3-element vector.
Concluding Thoughts
As you may have noticed, your question did not get a satisfying answer yet. Nor do I think in its current form it will. To get volunteers to look at your problem, you need to make it easy to understand what you are doing:
Start by simplifying your formulas. They may not be of interest to you anymore, but right now, they're just clutter.
Trim down your parameters. That is somehow part of the above.
Throw out things that are probably irrelevant. Apart from the point that you don't need (and probably don't want) an additional arrayfun around the matlabFunction results, symbolic math is likely to be irrelevant to your actua question on integral3. If you can ask your question without it, it may attract more attention.
For anything you cannot trim down, consider explaining what is happening.
Of course, in this process, for each iteration, test your code (after saying clear all or in a fresh MATLAB session!) to check if the problem is still there. If it is not, you may have found a hint where your basic problem is hiding.
For a longer discussion on the topic, see https://meta.stackexchange.com/questions/18584/how-to-ask-a-smart-question and the guides linked to within that discussion.
The following command
syms x real;
f = #(x) log(x^2)*exp(-1/(x^2));
fp(x) = diff(f(x),x);
fpp(x) = diff(fp(x),x);
and
solve(fpp(x)>0,x,'Real',true)
return the result
solve([0.0 < (8.0*exp(-1.0/x^2))/x^4 - (2.0*exp(-1.0/x^2))/x^2 -
(6.0*log(x^2)*exp(-1.0/x^2))/x^4 + (4.0*log(x^2)*exp(-1.0/x^2))/x^6],
[x == RD_NINF..RD_INF])
which is not what I expect.
The first question: Is it possible to force Matlab's solve to return the set of all solutions?
(This is related to this question.) Moreover, when I try to solve the equation
solve(fpp(x)==0,x,'Real',true)
which returns
ans =
-1.5056100417680902125994180096313
I am not satisfied since all solutions are not returned (they are approximately -1.5056, 1.5056, -0.5663 and 0.5663 obtained from WolframAlpha).
I know that vpasolve with some initial guess can handle this. But, I have no idea how I can generally find initial guessed values to obtain all solutions, which is my second question.
Other solutions or suggestions for solving these problems are welcomed.
As I indicated in my comment above, sym/solve is primarily meant to solve for analytic solutions of equations. When this fails, it tries to find a numeric solution. Some equations can have an infinite number of numeric solutions (e.g., periodic equations), and thus, as per the documentation: "The numeric solver does not try to find all numeric solutions for [the] equation. Instead, it returns only the first solution that it finds."
However, one can access the features of MuPAD from within Matlab. MuPAD's numeric::solve function has several additional capabilities. In particular is the 'AllRealRoots' option. In your case:
syms x real;
f = #(x)log(x^2)*exp(-1/(x^2));
fp(x) = diff(f(x),x);
fpp(x) = diff(fp(x),x);
s = feval(symengine,'numeric::solve',fpp(x)==0,x,'AllRealRoots')
which returns
s =
[ -1.5056102995536617698689500437312, -0.56633904710786569620564475006904, 0.56633904710786569620564475006904, 1.5056102995536617698689500437312]
as well as a warning message.
My answer to this question provides other way that various MuPAD solvers can be used, particularly if you can isolate and bracket your roots.
The above is not going to directly help with your inequalities other than telling you where the function changes sign. For those you could try:
s = feval(symengine,'solve',fpp(x)>0,x,'Real')
which returns
s =
(Dom::Interval(0, Inf) union Dom::Interval(-Inf, 0)) intersect solve(0 < 2*log(x^2) - 3*x^2*log(x^2) + 4*x^2 - x^4, x, Real)
Try plotting this function along with fpp.
While this is not a bug per se, The MathWorks still might be interested in this difference in behavior and poor performance of sym/solve (and the underlying symobj::solvefull) relative to MuPAD's solve. File a bug report if you like. For the life of me I don't understand why they can't better unify these parts of Matlab. The separation makes not sense from the perspective of a user.