Search code examples
matlabmathnumerical-integration

Code wont produce the value of a definite integral in MATLAB


I've had problems with my code as I've tried to make an integral compute, but it will not for the power, P2.

I've tried using anonymous function handles to use the integral() function on MATLAB as well as just using int(), but it will still not compute. Are the values too small for MATLAB to integrate or am I just missing something small?

Any help or advice would be appreciated to push me in the right direction. Thanks!

The problem in the code is in the bottom of the section labelled "Power Calculations". My integral also gets quite messy if that makes a difference.

%%%%%%%%%%% Parameters %%%%%%%%%%%%

n0 = 1;                                         %air 
n1 = 1.4;                                       %layer 1
n2 = 2.62;                                      %layer 2
n3 = 3.5;                                       %silicon
L0 = 650*10^(-9);                               %centre wavelength
L1 = 200*10^(-9): 10*10^(-9): 2200*10^(-9);     %lambda from 200nm to 2200nm
x = ((pi./2).*(L0./L1));                        %layer phase thickness

r01 = ((n0 - n1)./(n0 + n1));                   %reflection coefficient 01
r12 = ((n1 - n2)./(n1 + n2));                   %reflection coefficient 12
r23 = ((n2 - n3)./(n2 + n3));                   %reflection coefficient 23

t01 = ((2.*n0)./(n0 + n1));                     %transmission coefficient 01
t12 = ((2.*n1)./(n1 + n2));                     %transmission coefficient 12
t23 = ((2.*n2)./(n2 + n3));                     %transmission coefficient 23

Q1 = [1 r01; r01 1];                            %Matrix Q1
Q2 = [1 r12; r12 1];                            %Matrix Q2
Q3 = [1 r23; r23 1];                            %Matrix Q3

%%%%%%%%%%%% Graph of L vs R %%%%%%%%%%%

R = zeros(size(x));

for i = 1:length(x)

P = [exp(j.*x(i)) 0; 0 exp(-j.*x(i))];          %General Matrix P

T = ((1./(t01.*t12.*t23)).*(Q1*P*Q2*P*Q3));     %Transmission

T11 = T(1,1);                                   %T11 value
T21 = T(2,1);                                   %T21 value

R(i) = ((abs(T21./T11))^2).*100;                %Percent reflectivity

end 

plot(L1,R)
title('Percent Reflectance vs. wavelength for 2 Layers')
xlabel('Wavelength (m)')
ylabel('Reflectance (%)')

%%%%%%%%%%% Power Calculation %%%%%%%%%%

syms L;                                             %General lamda

y = ((pi./2).*(L0./L));                             %Layer phase thickness with variable Lamda
P1 = [exp(j.*y) 0; 0 exp(-j.*y)];                   %Matrix P with variable Lambda
T1 = ((1./(t01.*t12.*t23)).*(Q1*P1*Q2*P1*Q3));      %Transmittivity matrix T1
I = ((6.16^(15))./((L.^(5)).*exp(2484./L) - 1));    %Blackbody Irradiance

Tf11 = T1(1,1);                                     %New T11 section of matrix with variable Lambda

Tf2 = (((abs(1./Tf11))^2).*(n3./n0));               %final transmittivity                     
P1 = Tf2.*I;                                        %Power before integration

L_initial = 200*10^(-9);                            %Initial wavelength
L_final = 2200*10^(-9);                             %Final wavelength

P2 = int(P1, L, L_initial, L_final)                 %Power production

Solution

  • I've refactored your code

    1. to make it easier to read
    2. to improve code reuse
    3. to improve performance
    4. to make it easier to understand

    Why do you use so many unnecessary parentheses?!

    Anyway, there's a few problems I saw in your code.

    1. You used i as a loop variable, and j as the imaginary unit. It was OK for this one instance, but just barely so. In the future it's better to use 1i or 1j for the imaginary unit, and/or m or ii or something other than i or j as the loop index variable. You're helping yourself and your colleagues; it's just less confusing that way.

    2. Towards the end, you used the variable name P1 twice in a row, and in two different ways. Although it works here, it's confusing! Took me a while to unravel why a matrix-producing function was producing scalars instead...

    3. But by far the biggest problem in your code is the numerical problems with the blackbody irradiance computation. The term

       L⁵ · exp(2484/L) - 1
      

      for λ₀ = 200 · 10⁻⁹ m will require computing the quantity

       exp(1.242 · 10¹⁰)
      

      which, needless to say, is rather difficult for a computer :) Actually, the problem with your computation is two-fold. First, the exponentiation is definitely out of range of 64 bit IEEE-754 double precision, and will therefore result in ∞. Second, the parentheses are wrong; Planck's law should read

      C/L⁵ · 1/(exp(D) - 1)
      

      with C and D the constants (involving Planck's constant, speed of light, and Boltzmann constant), which you've presumably precomputed (I didn't check the values. I do know choice of units can mess these up, so better check).

    So, aside from the silly parentheses error, I suspect the main problem is that you simply forgot to rescale λ to nm. Changing everything in the blackbody equation to nm and correcting those parentheses gives the code

    I  = 6.16^(15) / ( (L*1e+9)^5 * (exp(2484/(L*1e+9)) - 1) );
    

    With this, I got a finite value for the integral of

    P2 = 1.052916498836486e-010
    

    But, again, you'd better double-check everything.

    Note that I used quadgk(), because it's one of the better ones available on R2010a (which I'm stuck with), but you can just as easily replace this with integral() available on anything newer than R2012a.

    Here's the code I ended up with:

    function pwr = my_fcn()
    
        % Parameters
        n0 = 1;      % air
        n1 = 1.4;    % layer 1
        n2 = 2.62;   % layer 2
        n3 = 3.5;    % silicon
        L0 = 650e-9; % centre wavelength
    
        % Reflection coefficients
        r01 = (n0 - n1)/(n0 + n1); 
        r12 = (n1 - n2)/(n1 + n2); 
        r23 = (n2 - n3)/(n2 + n3); 
    
        % Transmission coefficients
        t01 = (2*n0) / (n0 + n1); 
        t12 = (2*n1) / (n1 + n2); 
        t23 = (2*n2) / (n2 + n3);
    
        % Quality factors
        Q1  = [1 r01; r01 1];
        Q2  = [1 r12; r12 1];
        Q3  = [1 r23; r23 1];
    
        % Initial & Final wavelengths
        L_initial = 200e-9;
        L_final   = 2200e-9;
    
        % plot reflectivity for selected lambda range
        plot_reflectivity(L_initial, L_final, 1000);
    
        % Compute power production
        pwr = quadgk(@power_production, L_initial, L_final);
    
    
        % Helper functions
        % ========================================
    
        % Graph of lambda vs reflectivity
        function plot_reflectivity(L_initial, L_final, N)
    
            L = linspace(L_initial, L_final, N);
    
            R = zeros(size(L));
            for ii = 1:numel(L)
    
                % Transmission
                T = transmittivity(L(ii));
    
                % Percent reflectivity
                R(ii) = 100 * abs(T(2,1)/T(1,1))^2 ;
    
            end
    
            plot(L, R)
            title('Percent Reflectance vs. wavelength for 2 Layers')
            xlabel('Wavelength (m)')
            ylabel('Reflectance (%)')
    
        end
    
        % Compute transmittivity matrix for a single wavelength
        function T = transmittivity(L)
    
            % Layer phase thickness with variable Lamda
            y  = pi/2 * L0/L;
    
            % Matrix P with variable Lambda
            P1 = [exp(+1j*y) 0
                  0           exp(-1j*y)];
    
            % Transmittivity matrix T1
            T = 1/(t01*t12*t23) * Q1*P1*Q2*P1*Q3;
    
        end
    
        % Power for a specific wavelength. Note that this function 
        % accepts vector-valued wavelengths; needed for quadgk()
        function pwr = power_production(L)
    
            pwr = zeros(size(L));
    
            for ii = 1:numel(L)
    
                % Transmittivity matrix
                T1 = transmittivity(L(ii));
    
                % Blackbody Irradiance
                I  = 6.16^(15) / ( (L(ii)*1e+9)^5 * (exp(2484/(L(ii)*1e+9)) - 1) );
    
                % final transmittivity
                Tf2 = abs(1/T1(1))^2 * n3/n0;
    
                % Power before integration
                pwr(ii) = Tf2 * I;   
    
            end
    
        end
    
    end