Cartoon of monolayer-for-monolayer thin film growth and monitoring with XRR
Matlab code 

% Cartoon of Frank-van-der-Merwe thin-film growth being monitored by XRR

close all; clear

 

vid = VideoWriter('filmGrowthFvdMcartoon.mp4','MPEG-4');

vid.Quality = 100;

vid.FrameRate = 60;

open(vid);

figure(1)

set(gcf,'units','pixels','position',[0 0 1920 1080],'ToolBar','none');

set(0,'defaultfigurecolor',[1 1 1]);

set(gca,'linewidth',7);

 

lp = [-0.3 -0.5 0.8]; % Lighting direction 

ec = [0.25 0.28 0.5]; % Phil blue

fc = [1.0 0.83 0]; % Gold

dr = [0.5 0.0 0]; % Dark red

 

pos1 = [0 0 1 1]; 

LL = 1;

noCells = 40; % Number of cells

 

% Cylinder for detector

theta = 0:pi/180:2*pi;

circlex = sin(theta);

circlez = cos(theta);

[a,b,c] = cylinder(0.1,500);

 

[V,F] = platonic_solid(2,sqrt(3.00)); % Cube, side length = 1

V(:,3) = 0.14*V(:,3)-0.14; % Substrate, top surface (+/- 1)^2 @ z = 0

 

[V2,F2] = platonic_solid(2,sqrt(3)/noCells); % Unit cell of deposited material, edge length = 2/noCells

V2(:,3) = V2(:,3)+1/noCells; % Shift upwards by half a u.c. so bottom surface @ z = 0

 

% % Subplot of 3D cartoon of film growth being monitored by XRR

subplot('position',pos1);

% Draw substrate

ps = patch('Faces',F,'Vertices',V,'FaceColor',ec,...

    'FaceAlpha',1,'EdgeColor','none','FaceLighting','flat',...

    'DiffuseStrength',1,'AmbientStrength',1,'SpecularStrength',0); 

hold on

% Draw detector 

detWall = surf(a,b,c/4+1.7,'FaceColor',[0.7 0.7 0.7],'LineStyle','none',...

    'FaceLighting','flat','DiffuseStrength',0.5);

rotate(detWall,[0 1 0],90-atand(0.25/1.5),[0,0,2/noCells]);

detEnd = fill3(0.1*circlex,0.1*circlez,0*circlez+1.95,[0.5 0.5 0.5],'LineStyle','none',...

    'FaceLighting','flat','DiffuseStrength',0.5,'SpecularStrength',0.5);

rotate(detEnd,[0 1 0],90-atand(0.25/1.5),[0,0,2/noCells]);

 

 

% Draw incident and reflected x-ray beams

kinArrow = mArrow3([-1.5 0 0.25],[0 0 0],'color',fc, ...

    'stemWidth',0.01,'tipWidth',0.025,'facealpha',1);

koutArrow = mArrow3([0 0 0],[1.5 0 0.25],'color',fc, ...

    'stemWidth',0.01,'tipWidth',0.025,'facealpha',0.5);

 

set(gca, 'Projection','perspective');

light('Position',lp,'Style','infinite');

axis equal;

axis off;

view(35,35);

xlim([-LL*1.5 LL*2]);

ylim([-LL LL]);

zlim([-0.25 0.6]);

 

ii = 0; % Controls when a frame is recorded

frame = getframe(gcf);

writeVideo(vid,frame);

S(1) = 0;

for jj = 1:2 % Two monolayers of growth

    kk = 0; % Runs from 0 to noCells^2 for each ML and describes the ML coverage

    fillArray = zeros(noCells);

    while (any(fillArray(:) == 0)) % Incomplete monolayer

        x1 = randi([1 noCells],1); % Random integer x-coordinate between 1 and noCells

        y1 = randi([1 noCells],1); % Random integer y-coordinate between 1 and noCells

        % Limit 3x3 box neighborhood to within boundaries of substrate

        if (x1 == 1)

            xlo = x1;

            xhi = x1 + 2;

        else

            xlo = x1 - 1;

            xhi = x1 + 1;

        end

        if (x1 == noCells)

            xhi = x1;

            xlo = x1 - 2;

        end

        if (y1 == 1)

            ylo = y1;

            yhi = y1 + 2;

        else

            ylo = y1 - 1;

            yhi = y1 + 1;

        end

        if (y1 == noCells)

            yhi = y1;

            ylo = y1 - 2;

        end

        % Neighborhood of position (x1,y1)

        neighborBox = fillArray(xlo:xhi,ylo:yhi);

        if (sum(neighborBox(:)) < (xhi - xlo + 1)*(yhi - ylo + 1)) % At least one unoccupied site in 3 x 3 neighborhood

            % Position list of unoccupied sites within 3 x 3 neighborhood 

            [row,column] = find(neighborBox==0);

            rowSize = size(row,1); % Number of unoccupied sites within 3 x 3 neighborhood 

            selectedUCidx = randi([1 rowSize]); % Pick one of unoccupied sites at random 

            % Shift 3 x 3 region by one u.c. if selected site is on the

            % edge of the substrate 

            if (x1 == 1)

                x1 = x1 + row(selectedUCidx)-1;

            elseif (x1 == noCells)

                x1 = x1 + row(selectedUCidx)-3;

            else

                x1 = x1 + row(selectedUCidx)-2;

            end

            if (y1 == 1)

                y1 = y1 + column(selectedUCidx)-1;

            elseif (y1 == noCells)

                y1 = y1 + column(selectedUCidx)-3;

            else

                y1 = y1 + column(selectedUCidx)-2;

            end

            kk = kk + 1; % Increment number of occupied sites by one

            V3(:,1) = -1 + 1/noCells + V2(:,1) + 2*(x1-1)/noCells;

            x1 = round(V3(1,1)*noCells/2+(1+noCells/2)); % x-coordinate of u.c. in units of u.c.

            V3(:,2) = -1 + 1/noCells + V2(:,2) + 2*(y1-1)/noCells;

            y1 = round(V3(1,2)*noCells/2+(1+noCells/2)); % y-coordinate of u.c. in units of u.c.

            V3(:,3) = V2(:,3)+(jj-1)*2/noCells; % z-coordinate of u.c. in units of u.c.

            % Draw u.c. in position (x1,y1) 

            ps2 = patch('Faces',F2,'Vertices',V3,'FaceColor',dr*(1+(jj-1)/8),...

                'FaceAlpha',1,'EdgeColor','none','FaceLighting','flat',...

                'DiffuseStrength',1,'AmbientStrength',1,'SpecularStrength',0);

            fillArray(x1,y1) = 1; % Flag this site as occupied            

        end

        

        delete(kinArrow);

        delete(koutArrow);

        

        arrowHt = kk*(2/noCells)/noCells^2 + (jj-1)*2/noCells;

        kinArrow = mArrow3([-1.5 0 0.25+arrowHt],[0 0 0+arrowHt],'color',fc, ...

            'stemWidth',0.01,'tipWidth',0.025,'facealpha',1);

        roughNow = 1.4*(1 - abs((noCells^2/2)-kk)/(noCells^2/2));

        koutAlpha = exp(-roughNow.^2);        

        koutArrow = mArrow3([0 0 0+arrowHt],[1.5 0 0.25+arrowHt],'color',fc, ...

            'stemWidth',0.01,'tipWidth',0.025,'facealpha',koutAlpha);

        ii = ii + 1; % Number of attempts within an incomplete monolayer to complete that monolayer

        % Add frame to video every second attempt to fill a u.c. in order

        % to speed things up, even at 60 Hz frame rate 

        if (mod(ii,2) == 0) 

            frame = getframe(gcf);

            writeVideo(vid,frame);

            S(ii/2) = kk;

        end

    end

end

frame = getframe(gcf);

writeVideo(vid,frame);

 

noFrames = floor(ii/2);

 

% _________________________________________________________________________

% Plot out of reflectivity and monolayer coverage 

 

close all

clear vid

figure(2)

set(gcf,'ToolBar','none');

 

vid = VideoWriter('filmGrowthFvdMxrrSignal.mp4','MPEG-4');

vid.Quality = 100;

vid.FrameRate = 60;

open(vid);

set(0,'defaultfigurecolor',[1 1 1]);

set(gca,'linewidth',7); 

% Equation describing roughness, which is greatest when occupancy of ML is

% 50% 

rough = 1.4*(1 - abs((noCells^2/2)-S)/(noCells^2/2));

refl = exp(-rough.^2);

 

for jj = 1:noFrames

    newplot

    hold off

    yyaxis left 

    % Plot reflectivity

    plot(refl(1:jj)/max(refl(:)),'r','LineWidth', 2.0)

    set(gca,'fontsize',18);

    set(gca,'TickLength',[0.02, 1]);

    set(gca,'linewidth',2);

    xlabel('Time [arb. units]');

    set(gca,'YTickLabel',[]);

    set(gca,'XTickLabel',[]);

    set(gca,'xtick',[])

    set(gca,'ytick',[])

    xlim([0 noFrames]);

    ylim([0 1.05]);

    set(gca, 'YColor','k')

    ylabel('Reflectivity [arb. units]','Color','r');

 

    yyaxis right 

    % Plot monolayer coverage 

    plot(S(1:jj)/max(S(:)),'b','LineWidth', 2.0)

    set(gca,'fontsize',18);

    set(gca,'TickLength',[0.02, 1]);

    set(gca,'linewidth',2);

    set(gca,'YTickLabel',[])

    set(gca,'XTickLabel',[])

    set(gca,'xtick',[])

    set(gca,'ytick',[])

    xlim([0 noFrames]);

    ylim([0 1.05]);

    set(gca, 'YColor','k')

    ylabel('Monolayer coverage','Color','b');

    frame = getframe(gcf);

    writeVideo(vid,frame);

end

close(vid)