1
votes

So, I am aware that there are a number of other posts about eliminating for loops but I still haven't been able to figure this out.

I am looking to rewrite my code so that it has fewer for loops and runs a little faster. The code describes an optics problem calculating the intensity of different colors after the light has propagated through a medium. I have already gotten credit for this assignment but I would like to learn of better ways than just throwing in for loops all over the place. I tried rewriting the innermost loop using recursion which worked and looked nice but was a little slower.

Any other comments/improvements are also welcome.

Thanks!

n_o=1.50;
n_eo=1.60;
d=20e-6;
N_skiv=100;
lambda=[650e-9 510e-9 475e-9];
E_in=[1;1]./sqrt(2);

alfa=pi/2/N_skiv;
delta=d/N_skiv;

points=100;
int=linspace(0,pi/2,points);
I_ut=zeros(3,points);
n_eo_theta=@(theta)n_eo*n_o/sqrt(n_o^2*cos(theta)^2+n_eo^2*sin(theta)^2);

hold on

for i=1:3

    for j=1:points
        J_last=J_pol2(0);
        theta=int(j);

        for n=0:N_skiv
            alfa_n=alfa*n;
            J_last=J_ret_uppg2(alfa_n, delta , n_eo_theta(theta) , n_o , lambda(i) ) * J_last;
        end

        E_ut=J_pol2(pi/2)*J_last*E_in;
        I_ut(i,j)=norm(E_ut)^2;

    end

end

theta_grad=linspace(0,90,points);

plot(theta_grad,I_ut(1,:),'r')
plot(theta_grad,I_ut(2,:),'g')
plot(theta_grad,I_ut(3,:),'b')

And the functions:

function matris=J_proj(alfa)
matris(1,1)=cos(alfa);
matris(1,2)=sin(alfa);
matris(2,1)=-sin(alfa);
matris(2,2)=cos(alfa);
end


function matris=J_pol2(alfa)
J_p0=[1 0;0 0];
matris=J_proj(-alfa)*J_p0*J_proj(alfa);
end


function matris=J_ret_uppg2(alfa_n,delta,n_eo_theta,n_o,lambda)

k0=2*pi/lambda;
J_r0_u2(1,1)=exp(1i*k0*delta*n_eo_theta);
J_r0_u2(2,2)=exp(1i*k0*n_o*delta);
matris=J_proj(-alfa_n)*J_r0_u2*J_proj(alfa_n);

end
2

2 Answers

1
votes

Typically you cannot get rid of a for-loop if you are doing a calculation that depends on a previous answer, which seems to be the case with the J_last-variable.

However I saw at least one possible improvement with the n_eo_theta inline-function, instead of doing that calculation 100 times, you could instead simply change this line:

n_eo_theta=@(theta)n_eo*n_o/sqrt(n_o^2*cos(theta)^2+n_eo^2*sin(theta)^2);

into:

theta_0 = 1:100;
n_eo_theta=n_eo*n_o./sqrt(n_o^2*cos(theta_0).^2+n_eo^2*sin(theta_0).^2);

This would run as is, although you should also want to remove the variable "theta" in the for-loop. I.e. simply change

n_eo_theta(theta)

into

n_eo_theta(j) 

The way of using the "." prefix in the calculations is the furthermost tool for getting rid of for-loops (i.e. using element-wise calculations). For instance; see element-wise multiplication.

0
votes

You can use matrices!!!!

For example, you have the statement:

theta=int(j)

which is inside a nested loop. You can replace it by:

theta = [int(1:points);int(1:points);int(1:points)];

or:

theta = int(repmat((1:points), 3, 1));

Then, you have

alfa_n=alfa * n;

you can replace it by:

alfa_n = alfa .* (0:N_skiv);

And have all the calculation done in a row like fashion. That means, instead looping, you will have the values of a loop in a row. Thus, you perform the calculations at the rows using the MATLAB's functionalities and not looping.