How to make a two-dimensional matrix w/o for? - matlab

I'm coding the matrix for the 2-dimensional graph, now.
Although it's so simple equation, it takes a lot of time for performing. I think it could get faster.
especially, "for - command term" could be simplified I think.
How can I simplify this?
q=1:1:30
x(q)=330+q*0.3
F=1:30:8970
T=x(1)-0.3:0.001:x(30)+0.3
n=size(T,2)
k=1:1:n
for a=1:1:30
I(a,k)=F(a)*exp(-2.*(T(:,k)))
end
happy=sum(I)
plot(k,I)

I would say that the time is used to print results. Try to use ; at the end of each line, it will fasten computation.
You can also replace the for loop by the following element by element computation:
a = (1:1:30).';
aux = repmat(exp(-2.*(T(:,k))), length(a), 1);
a = repmat(a, 1, length(k));
I = a.'.*aux.';

Related

If and elseif, only the first line work?

L=1; Nx=51; PeriodicFlag=1; T=15; Nt=51;
spacedef='Pade6FirstDeriv'; casedef='LinearAdvection';
if (spacedef == 'Pade6FirstDeriv')
D1 = sparse(Pade6(Nx,dx,PeriodicFlag));
elseif (spacedef == 'Upwind3FirstDeriv')
D1 = sparse(Upwind3(Nx,dx,PeriodicFlag));
elseif (spacedef == 'Central4FirstDeriv')
D1 = sparse(Central4(Nx,dx,PeriodicFlag));
elseif (spacedef == 'Central2FirstDeriv')
D1 = sparse(Central2(Nx,dx,PeriodicFlag));
else
error(sprintf('Unknown spacedef = %s',spacedef));
end
In the above code, the if section is a small segment from a function I've constructed. I'm trying to get the function to know which methods to use based on my input (spacedef). Central2, Central4, Upwind3, and Pade6 are other functions I've written. The weird thing is that when spacedef =/= to 'Pade6FirstDeriv', I would get an error stating Error using ==, Matrix dimensions must agree. I've tried swapping the order of the if loop (by placing Central4, Central2, Pade6, and Upwind3 in the first line of the loop), and it seems like only the top line of the loop will work (the elseifs are not working). I'd greatly appreciate it if anybody can help me out. Thanks!
As has been noted in the comments, this is a common error when people first start comparing strings in MATLAB, and strcmp or strcmpi is generally the solution.
However, one solution the questions links in the comments don't present, and a solution I think looks much nicer, is the switch statement:
switch (spacedef)
case('Pade6FirstDeriv')
D1 = sparse(Pade6(Nx,dx,PeriodicFlag));
case('Upwind3FirstDeriv')
D1 = sparse(Upwind3(Nx,dx,PeriodicFlag));
case('Central4FirstDeriv')
D1 = sparse(Central4(Nx,dx,PeriodicFlag));
case('Central2FirstDeriv')
D1 = sparse(Central2(Nx,dx,PeriodicFlag));
otherwise
error(sprintf('Unknown spacedef = %s',spacedef));
end
Note: if I expect others to use my code with string comparisons, I usually lower the input such that the comparison is case-insensitive, although I have not done that here.

MATLAB Nesting Expression

Just a simple nesting question:
I've got a <100x100 double> matrix mat_B, with I cumsum. From the resulting matrix mat_A, I just need the last row vec_C, which I need to cumsum again. My code looks like this:
mat_A = cumsum(mat_B);
vec_C = cumsum(mat_A(end,:));
My question is, if it's possible to put all of this inside one line of code. I know that cumsum(mat_B) returns a matrix, but if I put (end, :) behind the expression, it won't work.
I know it sounds quite silly, but I'd like to know how nesting works in those kind of situations.
You could skip the first cumsum and just use sum, since the last line of cumsum is equivalent to the result of sum:
>> mat_B=rand(5);
>> cumsum(mat_B)
ans =
0.2517 0.4522 0.8838 0.3751 0.2527
0.6847 0.7778 1.3412 0.7487 0.8376
1.5270 1.1579 2.1404 1.2327 1.3613
1.7115 2.0444 2.2745 2.2021 1.5247
2.2197 2.8056 2.3398 2.5442 2.0111
>> sum(mat_B)
ans =
2.2197 2.8056 2.3398 2.5442 2.0111
Therefore
vec_C = cumsum(sum(mat_B));
should do what you want.

IDL equivalent of MATLAB function accumarray()

I've been given the task of translating a piece of MATLAB code into IDL and have
hit a roadblock when I came across the MATLAB function accumarry(). The
function, described here
is used to sum elements in one array, based on indices given in another. Example
1 perhaps explains this better than the actual function description at the top
of the page. In trying to reproduce Example 1 in IDL, I haven't been able to avoid a for loop, but I'm confident that it is possible. My best attempt is the following:
vals = [101,102,103,104,105]
subs = [0,1,3,1,3]
n = max(subs)+1
accum = make_array(n)
for i = 0, n-1 do begin
wVals = where(subs eq i,count)
accum[i] = count eq 0 ? 0 : total(vals[wVals])
endfor
print,accum
; 101.000 206.000 0.00000 208.000
Any advice on improving this would be greatly appreciated! I expected IDL to have a similar built-in function, but haven't been able to track one down. Perhaps some magic with histogram binning?
I found a number of possible solutions to this problem on Coyote's IDL site (not surprisingly.)
http://www.idlcoyote.com/code_tips/drizzling.html
I ended up using the following, as a compromise between performance and readability:
function accumarray,data,subs
mx = max(subs)
accum = fltarr(mx+1)
h = histogram(subs,reverse_indices=ri,OMIN=om)
for j=0L,n_elements(h)-1 do if ri[j+1] gt ri[j] then $
accum[j+om] = total(vals[ri[ri[j]:ri[j+1]-1]])
return,accum

How do get loop results into a vector or matrix in matlab

Here is the thing:
I have while loop nested in a for loop.
I can get the results of each iteration as a result for the variable flp. But now i want all these results stored in a vector with same number of rows as another variable called eci. I'm aware that i have to preallocate the vector. But how do i move on from here?
Tank you!
Here is the code i've done so far:
for eci=0:0.0002:ecu
fl=0;
fcc=fc0*(2.254*sqrt(1+7.94*fl/fc0)-2*fl/fc0-1.254);
ecc=ec0*(1+5*(fcc/fc0-1));
r=Ec/(Ec-fcc/ecc);
x=eci/ecc;
fc=fcc*x*r/(r-1+x^r);
el=(Ec*eci-fc)/(2*beta*fc);
flp=ke*kr*2*nf*tf*Ef*1000*el/B;
while abs(fl-flp)>0.0001
fl=flp;
fcc=fc0*(2.254*sqrt(1+7.94*fl/fc0)-2*fl/fc0-1.254);
ecc=ec0*(1+5*(fcc/fc0-1));
r=Ec/(Ec-fcc/ecc);
x=eci/ecc;
fc=fcc*x*r/(r-1+x^r);
el=(Ec*eci-fc)/(2*beta*fc);
flp=ke*kr*2*nf*tf*Ef*1000*el/B
end
end
eci=[0:0.0002:ecu]';
m=size(eci);
m(:,2)=[];
mat_result=zeros(m,1)
Its quite stimple, start with an empty vector, for example:
results = zeros(length(0:0.0002:ecu),1);
Then just start counting with t=t+1 somewhere in the loop (initialize properly ofcourse) and store the restult:
results(t) = myResult

Switching even- and odd-indexed characters in Matlab

Using Matlab, write a function called tripFlip that takes in one string and switches each even-indexed charactar with the odd-indexed character immediately preceding it. Use iteration. Example: tripFlip('orange') ->'ronaeg'
I assume this is homework, so I won't give a complete answer. You can use double to convert a string to an array, and char to go back, if working with arrays makes the problem any easier. Otherwise, strings seem to work just like arrays in terms of indexing: s(1) gets the first character, length(s) gets the length, etc.
I agree its a homework question, and posting it here will only bite you back in the long run. But here goes:
a = 'orange';
b = '';
b(2:2:length(a))= a(1:2:end);
b(1:2:length(a))= a(2:2:end);
disp(b)
In one line:
>> input = 'orange';
>> output = input(reshape([2:2:end;1:2:end],1,[]))
output =
ronaeg
It's not a function and doesn't use iteration, but it's how you'd solve this if you were to learn Matlab.
Something like this should do the trick, perhaps you want to make it a bit more robust.
function b = TripFlip(a)
a = 'orange';
b = '';
for i = 2:2:length(a)
b=[b a(i) a(i-1)]
end