Four layer neutron reflectivity - multi_reflec.c

    //
//  multi_reflec.c
//  NREFLEC
//
//  Created by Simon Martin on 16/10/2017.
//


//2 component vector to hold the real and imaginary parts of a complex number:
typedef double complex cfloat;

//#define I ((cfloat)(0.0, 1.0))
#define SLABS 4

#include <complex.h>

//double Iq(double q,double sld_cap,double t1,double sld1,double r1,double sld_s,double r_s);
double Iq(double q,
          double sld_cap,
          double sld1,double t1,double r1,
          double sld2,double t2,double r2,
          double sld3,double t3,double r3,
          double sld4,double t4,double r4,
          double sld_s,double r_s);

double complex fresnel(cfloat k1, cfloat k2, double rough);

double complex k_medium(cfloat qi,double sld_medium);




double Iq(double q,
          double sld_cap,
          double sld1,double t1,double r1,
          double sld2,double t2,double r2,
          double sld3,double t3,double r3,
          double sld4,double t4,double r4,
          double sld_s,double r_s)
{
    // arrays: space for each slab plus cap and substrate
    double sld_array[SLABS+2]   = {0.};    /* array of sld */
    double thick_array[SLABS+2] = {0.};  /* array of thickness */
    double rough_array[SLABS+2] = {0.};  /* array of roughness */
    double complex r_array[SLABS+2]     = {(double complex)(0.,0.)};      /* array of reflectivity terms*/
    double complex rn = (double complex)(0.,0.);  // fresnel term for nth layer
    double complex numer=(double complex)(0.,0.); // calculation numerator
    double complex denom=(double complex)(0.,0.); // calculation denominator
    int nlayers=SLABS; /*total layers in system */
    // set up arrays of sld etc
    // will need to update this code if/when other layers are added
    // parameters are not passed as block/list, so have to set up arrays row by ro
    sld_array[0]=sld_cap*1.e-6;
    sld_array[1]=sld1*1.e-6;
    sld_array[2]=sld2*1.e-6;
    sld_array[3]=sld3*1.e-6;
    sld_array[4]=sld4*1.e-6;
    sld_array[5]=sld_s*1.e-6;
    // set up array of thicknesses
    thick_array[0]=0.;
    thick_array[1]=t1;
    thick_array[2]=t2;
    thick_array[3]=t3;
    thick_array[4]=t4;
    thick_array[5]=0.;
    // array of roughness
    rough_array[0]=0.;
    rough_array[1]=r1;
    rough_array[2]=r2;
    rough_array[3]=r3;
    rough_array[4]=r4;
    rough_array[5]=r_s;
    double ko=q/2.; // external wavevector
    // calculate wavevector in capping medium
    double complex kcap=cabs(csqrt(ko*ko+4.*M_PI*sld_cap+4.*M_PI*I*0.));// add complex sld later
    
    r_array[nlayers+1]=(double complex)(0.,0.); // reflection term, builds up iteratively
    // no reflection from bulk of substrate
    double complex kzn=k_medium(kcap,sld_array[nlayers]);
    double complex kznp1=k_medium(kcap,sld_array[nlayers+1]);
    r_array[nlayers]=fresnel(kzn,kznp1,rough_array[nlayers+1]);
    for (int i=nlayers-1;i>=0;i--)
    {
        kzn   = k_medium(kcap,sld_array[i]);
        kznp1 = k_medium(kcap,sld_array[i+1]);
        rn    = fresnel(kzn,kznp1,rough_array[i+1]); // nth layer fresnel term
        //double complex delta=cmult_imag(kznp1,2.*thick_array[i+1]);
        double complex delta=kznp1*2.*I*thick_array[i+1];
        double complex expon=cexp(delta); //               exp(I*q*t)
        double complex rnexp=r_array[i+1]*expon;
        numer=rn+rnexp;
        denom=1.+rn*rnexp;
        
        r_array[i]=numer/denom;
        
        //numer=kznp1;
    }
    
    return (r_array[0]*conj(r_array[0]));
    //return c_abs2(numer);
}

double complex fresnel(double complex k1,double complex k2,double rough)
{
    //return c_exp(-0.5*q1*q2*rough*rough)*(q1-q2)/(q1+q2);
    double complex fres = (k1-k2)/(k1+k2);
    // now calculate effect of interface roughness (Nevot and Croce method)
    double complex kprod=k1*k2;
    double complex expon=kprod*(-2.)*rough*rough;
    return (fres*cexp(expon));
    
}

double complex k_medium(double complex k,double sld_medium)
{
    double complex term;
    double delta;
    delta= 4.*M_PI*sld_medium;
    double complex k2=(k*k);
    //cfloat term=cfloat(16.*M_PI*sld_medium,0.);
    term=(k2-delta);
    return csqrt(term);
}


Back to Model Download