/* In: tau (lattice parameter) Out: g2 -> g[0] g3 -> g[1] */ void compute_invariants(gsl_complex tau, gsl_complex *g) { gsl_complex q, q14; gsl_complex t2,t3,t24,t34; gsl_complex g3_term1, g3_term2; gsl_complex g2, g3; q = gsl_complex_exp(gsl_complex_mul_imag(tau,M_PI)); q14 = gsl_complex_exp(gsl_complex_mul_imag(tau,M_PI_4)); t2=theta20(q,q14); t3=theta30(q); t24 = pow4(t2); t34 = pow4(t3); g2 = gsl_complex_mul_real(gsl_complex_sub(gsl_complex_add(gsl_complex_mul(t24,t24),gsl_complex_mul(t34,t34)),gsl_complex_mul(t24,t34)),_CONST_43PI4); g3_term1 = gsl_complex_add(gsl_complex_mul(t24,gsl_complex_mul(t24,t24)),gsl_complex_mul(t34,gsl_complex_mul(t34,t34))); g3_term2 = gsl_complex_mul(gsl_complex_add(t24,t34),gsl_complex_mul(t24,t34)); g3 = gsl_complex_sub( gsl_complex_mul_real(g3_term1, _CONST_827PI6), gsl_complex_mul_real(g3_term2, _CONST_49PI6) ); g[0] = g2; g[1] = g3; }
void expm(gsl_matrix_complex * L, gsl_complex t, gsl_matrix * m) { int i,j,s; gsl_vector_complex *eval = gsl_vector_complex_alloc(4); gsl_matrix_complex *evec = gsl_matrix_complex_alloc(4, 4); gsl_eigen_nonsymmv_workspace * w = gsl_eigen_nonsymmv_alloc(4); gsl_matrix_complex *evalmat = gsl_matrix_complex_alloc(4, 4); gsl_matrix_complex *vd = gsl_matrix_complex_alloc(4, 4); gsl_complex one = gsl_complex_rect(1, 0); gsl_complex zero = gsl_complex_rect(0, 0); gsl_matrix_complex *K = gsl_matrix_complex_alloc(4, 4); gsl_permutation *p = gsl_permutation_alloc(4); gsl_vector_complex *x = gsl_vector_complex_alloc(4); gsl_vector_complex_view bp; gsl_complex z; gsl_eigen_nonsymmv(m, eval, evec, w); gsl_eigen_nonsymmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC); gsl_eigen_nonsymmv_free(w); // clear workspace for (i = 0; i < 4; i++) { gsl_complex eval_i = gsl_vector_complex_get(eval, i); gsl_complex expeval = gsl_complex_mul(eval_i,t); expeval = gsl_complex_exp(expeval); gsl_matrix_complex_set(evalmat, i, i, expeval); } gsl_vector_complex_free(eval); // clear vector for eigenvalues // v'L'=De'v' gsl_blas_zgemm(CblasTrans, CblasTrans, one, evalmat, evec, zero, vd); gsl_matrix_complex_transpose(evec);//transpose v gsl_matrix_complex_memcpy(K,evec); for (i = 0; i < 4; i++) { bp = gsl_matrix_complex_column(vd, i); gsl_linalg_complex_LU_decomp(evec, p, &s); gsl_linalg_complex_LU_solve(evec, p, &bp.vector, x); for (j = 0; j < 4; j++) { z = gsl_vector_complex_get(x, j); gsl_matrix_complex_set(L,i,j,z); //'through the looking glass' transpose } gsl_matrix_complex_memcpy(evec,K); } gsl_permutation_free(p); gsl_vector_complex_free(x); gsl_matrix_complex_free(vd); gsl_matrix_complex_free(evec); gsl_matrix_complex_free(evalmat); gsl_matrix_complex_free(K); }
gsl_complex f_integrand(gsl_complex p, const Params *params) { double r = params->r; return gsl_complex_mul( f_envelope(p, params), gsl_complex_exp(gsl_complex_mul_imag(p, r))); }
/****************************************************************************** * calc_I() * Calculate the field intensity at an arbitrary point within layer * * Parameters * --------- * * Returns * ------- * * Notes * ----- * Note assume that 0 <= z <= d[j] (but we dont check that here) * except for the base layer (j==0), in that case z <= 0 * ******************************************************************************/ double calc_I(int layer_idx, double z, ref_model *ref, angle_calc *ang_c, layer_calc *lay_c){ double I, k; gsl_complex Ai, Ar, Ei, Er, g, phase_i, phase_r; k = ref->k; GSL_REAL(Ai) = ang_c->Re_Ai[layer_idx]; GSL_IMAG(Ai) = ang_c->Im_Ai[layer_idx]; GSL_REAL(Ar) = ang_c->Re_Ar[layer_idx]; GSL_IMAG(Ar) = ang_c->Im_Ar[layer_idx]; GSL_REAL(g) = ang_c->Re_g[layer_idx]; GSL_IMAG(g) = ang_c->Im_g[layer_idx]; // calculate Ei at z within layer j // make sure z is neg for base layer if (layer_idx == 0){ if (z > 0) z = -1.0*z; } else { if (z < 0) z = -1.0*z; } GSL_REAL(phase_i) = 0.0; GSL_IMAG(phase_i) = 1.0*k*z; phase_i = gsl_complex_exp( gsl_complex_mul(phase_i,g)); Ei = gsl_complex_mul(Ai,phase_i); // calculate Er at z within layer j if (layer_idx > 0) { GSL_REAL(phase_r) = 0.0; GSL_IMAG(phase_r) = -1.0*k*z; phase_r = gsl_complex_exp( gsl_complex_mul(phase_r,g)); Er = gsl_complex_mul(Ar,phase_r); } else { GSL_REAL(phase_r) = 0.0; GSL_IMAG(phase_r) = 0.0; GSL_REAL(Er) = 0.0; GSL_IMAG(Er) = 0.0; } I = gsl_complex_abs2(gsl_complex_add(Ei,Er)); return (I); }
gsl_complex f_envelope(gsl_complex p, const Params *params) { double m = params->m; gsl_complex env = gsl_complex_div( p, gsl_complex_sqrt(gsl_complex_add_real(gsl_complex_mul(p,p), m*m))); if (params->smear) { gsl_complex sp = gsl_complex_mul_real(p, params->sigma); env = gsl_complex_mul(env, gsl_complex_exp(gsl_complex_negative(gsl_complex_mul(sp, sp)))); } return env; }
/** exponentioal of a complex number \ingroup complex \param[in] z Complex number \return \f$ e^z \f$*/ complex exp(const complex& z) { return complex(gsl_complex_exp(z.as_gsl_type())); }
void Spectrometer::countAmplitudes_bulk_B(Medium &Osrodek, QString DataName, QProgressBar *Progress, QTextBrowser *Browser, double kx, double ky, double w, int polarisation, double x_lenght, double y_lenght, double precision) { double a=Osrodek.itsBasis.getLatticeConstant(); int RecVec=itsRecVectors; int dimension=3*(2*RecVec+1)*(2*RecVec+1); std::ofstream plik; DataName="results/amplitudes/"+ DataName + ".dat"; QByteArray bytes = DataName.toAscii(); const char * CDataName = bytes.data(); plik.open(CDataName); //inicjalizacje wektorów i macierzy gsl_matrix *gamma=gsl_matrix_calloc(dimension, dimension); gsl_matrix *V=gsl_matrix_calloc(dimension, dimension); gsl_vector *S=gsl_vector_calloc(dimension); gsl_vector *work=gsl_vector_calloc(dimension); //gamma dla Podłoża /* S - numeruje transformaty tensora sprężystoci i gestosci i - numeruje wiersze macierzy j - numeruje kolumny macierzy */ for(int Nx=-RecVec, i=0, S=0; Nx<=RecVec; Nx++) { for(int Ny=-RecVec; Ny<=RecVec; Ny++, i=i+3) { for(int Nx_prim=-RecVec, j=0; Nx_prim<=RecVec; Nx_prim++) { for(int Ny_prim=-RecVec; Ny_prim<=RecVec; Ny_prim++, j=j+3, S++) { double Elasticity[6][6]; itsRecBasisSubstance[S].getElasticity(Elasticity); double Density=itsRecBasisSubstance[S].getDensity(); double gx=2*M_PI*Nx/a; double gy=2*M_PI*Ny/a; double gx_prim=2*M_PI*Nx_prim/a; double gy_prim=2*M_PI*Ny_prim/a; gsl_matrix_set(gamma, i, j, Elasticity[0][0]*(kx+gx)*(kx+gx_prim)+Elasticity[3][3]*(ky+gy)*(ky+gy_prim)-Density*w*w); gsl_matrix_set(gamma, i+1, j, Elasticity[0][1]*(kx+gx_prim)*(ky+gy)+Elasticity[3][3]*(ky+gy_prim)*(kx+gx)); gsl_matrix_set(gamma, i, j+1, Elasticity[0][1]*(ky+gy_prim)*(kx+gx)+Elasticity[3][3]*(kx+gx_prim)*(ky+gy)); gsl_matrix_set(gamma, i+1, j+1, Elasticity[0][0]*(ky+gy_prim)*(ky+gy)+Elasticity[3][3]*(kx+gx_prim)*(kx+gx)-Density*w*w); gsl_matrix_set(gamma, i+2, j+2, Elasticity[3][3]*(ky+gy_prim)*(ky+gy)+Elasticity[3][3]*(kx+gx_prim)*(kx+gx)-Density*w*w); } } } } //rozwiązanie układu równań gsl_linalg_SV_decomp(gamma, V, S, work); gsl_complex u; double Gx, Gy; if (polarisation==3) { gsl_complex ux, uy, uz; for(double x=0; x < x_lenght; x=x+precision) { for(double y=0; y < y_lenght; y=y+precision) { ux = gsl_complex_rect(0, 0); uy = gsl_complex_rect(0, 0); uz = gsl_complex_rect(0, 0); //pasek postepu int postep=int(100*x/x_lenght); Progress->setValue(postep); Progress->update(); QApplication::processEvents(); for (int Nx=-RecVec, i=0; Nx <= RecVec; Nx++) { for (int Ny=-RecVec; Ny <= RecVec; Ny++, i=i+3) { Gx=2*M_PI*Nx/a; Gy=2*M_PI*Ny/a; double Ax = gsl_matrix_get(V, i, dimension-1); double Ay = gsl_matrix_get(V, i+1, dimension-1); double Az = gsl_matrix_get(V, i+2, dimension-1); gsl_complex expin1 = gsl_complex_rect(0, (kx+Gx)*x+(ky+Gy)*y); gsl_complex exp1 = gsl_complex_exp(expin1); gsl_complex multiply = gsl_complex_mul_real(exp1, Ax); ux = gsl_complex_add(ux, multiply); expin1 = gsl_complex_rect(0, (kx+Gx)*x+(ky+Gy)*y); exp1 = gsl_complex_exp(expin1); multiply = gsl_complex_mul_real(exp1, Ay); uy = gsl_complex_add(uy, multiply); expin1 = gsl_complex_rect(0, (kx+Gx)*x+(ky+Gy)*y); exp1 = gsl_complex_exp(expin1); multiply = gsl_complex_mul_real(exp1, Az); uz = gsl_complex_add(uz, multiply); } } double U = sqrt(gsl_complex_abs(ux)*gsl_complex_abs(ux)+gsl_complex_abs(uy)*gsl_complex_abs(uy)+gsl_complex_abs(uz)*gsl_complex_abs(uz)); //zapisanie wartości do pliku QString nazwa = Osrodek.itsBasis.getFillingSubstance().getName(); if(nazwa=="Air") { double rad=Osrodek.itsBasis.getRadius(); if(sqrt(x*x+y*y) > rad && sqrt((a-x)*(a-x)+y*y) > rad && sqrt((a-x)*(a-x)+(a-y)*(a-y)) > rad && sqrt((a-y)*(a-y)+x*x) > rad) { plik << x << "\t" << y << "\t" << U << "\n"; } } else { plik << x << "\t" << y << "\t" << U << "\n"; } } plik << "\n"; } } else if (polarisation==4) { gsl_complex uxx, uxy, uxz, uyx, uyy, uyz, uzx, uzy, uzz; double Uxx, Uxy, Uxz, Uyx, Uyy, Uyz, Uzx, Uzy, Uzz; for(double x=0; x < x_lenght; x=x+precision) { for(double y=0; y < y_lenght; y=y+precision) { uxx = gsl_complex_rect(0, 0); uxy = gsl_complex_rect(0, 0); uxz = gsl_complex_rect(0, 0); uyx = gsl_complex_rect(0, 0); uyy = gsl_complex_rect(0, 0); uyz = gsl_complex_rect(0, 0); uzx = gsl_complex_rect(0, 0); uzy = gsl_complex_rect(0, 0); uzz = gsl_complex_rect(0, 0); double rad=Osrodek.itsBasis.getRadius(); double Ela[6][6]; if(sqrt(x*x+y*y) > rad && sqrt((a-x)*(a-x)+y*y) > rad && sqrt((a-x)*(a-x)+(a-y)*(a-y)) > rad && sqrt((a-y)*(a-y)+x*x) > rad) { Osrodek.itsBasis.getSubstance().getElasticity(Ela); } else { Osrodek.itsBasis.getFillingSubstance().getElasticity(Ela); } //pasek postepu int postep=int(100*x/x_lenght); Progress->setValue(postep); Progress->update(); QApplication::processEvents(); for (int Nx=-RecVec, i=0; Nx <= RecVec; Nx++) { for (int Ny=-RecVec; Ny <= RecVec; Ny++, i=i+3) { Gx=2*M_PI*Nx/a; Gy=2*M_PI*Ny/a; double Ax = gsl_matrix_get(V, i, dimension-1); double Ay = gsl_matrix_get(V, i+1, dimension-1); double Az = gsl_matrix_get(V, i+2, dimension-1); gsl_complex expin1 = gsl_complex_rect(0, (kx+Gx)*x+(ky+Gy)*y); gsl_complex exp1 = gsl_complex_exp(expin1); gsl_complex multiply = gsl_complex_mul_real(exp1, Ax); //uxx gsl_complex multidiff = gsl_complex_mul(multiply, gsl_complex_mul_real(gsl_complex_rect(0,1), kx+Gx)); uxx = gsl_complex_add(uxx, multidiff); //uxy multidiff = gsl_complex_mul(multiply, gsl_complex_mul_real(gsl_complex_rect(0,1), ky+Gy)); uxy = gsl_complex_add(uxy, multidiff); expin1 = gsl_complex_rect(0, (kx+Gx)*x+(ky+Gy)*y); exp1 = gsl_complex_exp(expin1); //uy multiply = gsl_complex_mul_real(exp1, Ay); //uyx multidiff = gsl_complex_mul(multiply, gsl_complex_mul_real(gsl_complex_rect(0,1), kx+Gx)); uyx = gsl_complex_add(uyx, multidiff); //uyy multidiff = gsl_complex_mul(multiply, gsl_complex_mul_real(gsl_complex_rect(0,1), ky+Gy)); uyy = gsl_complex_add(uyy, multidiff); expin1 = gsl_complex_rect(0, (kx+Gx)*x+(ky+Gy)*y); exp1 = gsl_complex_exp(expin1); multiply = gsl_complex_mul_real(exp1, Az); //uzx multidiff = gsl_complex_mul(multiply, gsl_complex_mul_real(gsl_complex_rect(0,1), kx+Gx)); uzx = gsl_complex_add(uzx, multidiff); //uzy multidiff = gsl_complex_mul(multiply, gsl_complex_mul_real(gsl_complex_rect(0,1), ky+Gy)); uzy = gsl_complex_add(uzy, multidiff); } } Uxx=gsl_complex_abs(uxx); Uxy=gsl_complex_abs(uxy); Uxz=gsl_complex_abs(uxz); Uyx=gsl_complex_abs(uyx); Uyy=gsl_complex_abs(uyy); Uyz=gsl_complex_abs(uyz); Uzx=gsl_complex_abs(uzx); Uzy=gsl_complex_abs(uzy); Uzz=gsl_complex_abs(uzz); double U = Ela[0][0]*(Uxx*Uxx+Uyy*Uyy+Uzz*Uzz)+2*Ela[0][1]*(Uxx*Uyy+Uxx*Uzz+Uyy*Uzz)+0.25*Ela[3][3]*((Uyz+Uzy)*(Uyz+Uzy)+(Uxz+Uzx)*(Uxz+Uzx)+(Uxy+Uyx)*(Uxy+Uyx)); //zapisanie wartości do pliku QString nazwa = Osrodek.itsBasis.getFillingSubstance().getName(); if(nazwa=="Air") { double rad=Osrodek.itsBasis.getRadius(); if(sqrt(x*x+y*y) > rad && sqrt((a-x)*(a-x)+y*y) > rad && sqrt((a-x)*(a-x)+(a-y)*(a-y)) > rad && sqrt((a-y)*(a-y)+x*x) > rad) { plik << x << "\t" << y << "\t" << U << "\n"; } } else { plik << x << "\t" << y << "\t" << U << "\n"; } } plik << "\n"; } } else { for(double x=0; x < x_lenght; x=x+precision) { for(double y=0; y < y_lenght; y=y+precision) { u = gsl_complex_rect(0, 0); //pasek postepu int postep=int(100*x/x_lenght); Progress->setValue(postep); Progress->update(); QApplication::processEvents(); for (int Nx=-RecVec, i=0; Nx <= RecVec; Nx++) { for (int Ny=-RecVec; Ny <= RecVec; Ny++, i=i+3) { Gx=2*M_PI*Nx/a; Gy=2*M_PI*Ny/a; double A = gsl_matrix_get(V, i+polarisation, dimension-1); gsl_complex expin1 = gsl_complex_rect(0, (kx+Gx)*x+(ky+Gy)*y); gsl_complex exp1 = gsl_complex_exp(expin1); gsl_complex multiply = gsl_complex_mul_real(exp1, A); u = gsl_complex_add(u, multiply); } } double U = gsl_complex_abs(u); //zapisanie wartości do pliku plik << x << "\t" << y << "\t" << U << "\n"; } plik << "\n"; } } plik.close(); gsl_matrix_free(gamma); gsl_matrix_free(V); gsl_vector_free(S); gsl_vector_free(work); }
ComplexGSL exp( ComplexGSL& c ) { return ComplexGSL(gsl_complex_exp(c.z)); }
gsl_complex integrate_line_segment(Params *params, gsl_complex p0, gsl_complex p1) { gsl_complex k = gsl_complex_sub(p1, p0); const double r = params->r; const double a = 0.0; // parameter interval start const double b = 1.0; // parameter interval end const double L = b - a; // length of parameter interval const size_t table_size = 1000; // calculate frequency of oscillatory part double omega = GSL_REAL(k) * r; gsl_integration_workspace *ws = gsl_integration_workspace_alloc(table_size); // prepare sine/cosine tables for integration gsl_integration_qawo_table *table_cos = gsl_integration_qawo_table_alloc(omega, L, GSL_INTEG_COSINE, table_size); gsl_integration_qawo_table *table_sin = gsl_integration_qawo_table_alloc(omega, L, GSL_INTEG_SINE, table_size); LineSegmentParams lsp; lsp.p0 = p0; lsp.k = k; lsp.damping = params->r * GSL_IMAG(k); lsp.params = params; //fprintf(stderr, "p0 = %g %g, p1 = %g %g, k = %g %g, r = %g, omega = %g, damping = %g\n", // GSL_REAL(p0), GSL_IMAG(p0), GSL_REAL(p1), GSL_IMAG(p1), // GSL_REAL(k), GSL_IMAG(k), r, omega, lsp.damping); gsl_function F; F.function = &line_segment_integrand_wrapper; F.params = &lsp; double result_real_cos, abserr_real_cos; double result_real_sin, abserr_real_sin; double result_imag_cos, abserr_imag_cos; double result_imag_sin, abserr_imag_sin; double epsabs = 1e-9; double epsrel = 1e-9; lsp.part = REAL; gsl_integration_qawo(&F, a, epsabs, epsrel, table_size, ws, table_cos, &result_real_cos, &abserr_real_cos); gsl_integration_qawo(&F, a, epsabs, epsrel, table_size, ws, table_sin, &result_real_sin, &abserr_real_sin); lsp.part = IMAG; gsl_integration_qawo(&F, a, epsabs, epsrel, table_size, ws, table_cos, &result_imag_cos, &abserr_imag_cos); gsl_integration_qawo(&F, a, epsabs, epsrel, table_size, ws, table_sin, &result_imag_sin, &abserr_imag_sin); //fprintf(stderr, " cos: %g (+- %g) %g (+- %g) sin: %g (+- %g) %g (+- %g)\n", // result_real_cos, abserr_real_cos, result_imag_cos, abserr_imag_cos, // result_real_sin, abserr_real_sin, result_imag_sin, abserr_imag_sin); gsl_complex cos_part = gsl_complex_rect(result_real_cos, result_imag_cos); gsl_complex sin_part = gsl_complex_rect(-result_imag_sin, result_real_sin); gsl_complex sum = gsl_complex_add(cos_part, sin_part); gsl_complex result = gsl_complex_mul( k, gsl_complex_mul(sum, gsl_complex_exp(gsl_complex_mul_imag(p0, params->r)))); gsl_integration_qawo_table_free(table_sin); gsl_integration_qawo_table_free(table_cos); gsl_integration_workspace_free(ws); return result; }
void AbsArg(param_ param, abs_info_ *abs_info, gsl_complex *W, double *absW, double *argW, gsl_complex *complex_rot) { /* * In this function, we calculate the abs and arg * values for every point on the lattice. We also * find the total and max values for the abs across * the entire lattice. */ int i, j, tmp_int; gsl_complex complex_I; double *max_array, tmp; int max_num_threads; int L=param.L; GSL_SET_COMPLEX(&complex_I,0.,1.); tmp = 0.; tmp_int = 0; (*abs_info).max=0.; #pragma omp parallel { /* * The optimization here creates an array once in the * main thread, of length equal to the total number * of threads, and then updates local maxima along * the individual threads, storing them in the newly * created array. At the end, the local maxima are * compared. */ #pragma omp master { max_num_threads = omp_get_num_threads(); max_array = (double *)calloc(max_num_threads,sizeof(double)); } int num; num=omp_get_thread_num(); #pragma omp barrier //this barrier ensures the array //is visible to all threads #pragma omp for reduction(+:tmp) for(i=0; i<L*L; i++) { absW[i]=gsl_complex_abs(W[i]); tmp += absW[i]; if(absW[i] > max_array[num]) max_array[num]=absW[i]; argW[i] = gsl_complex_arg(W[i]); complex_rot[i] = gsl_complex_exp(gsl_complex_mul_real(\ complex_I,(-0.5)*argW[i])); } #pragma omp barrier #pragma omp master { for(i=0; i<max_num_threads; i++) if(max_array[i] > (*abs_info).max) (*abs_info).max = max_array[i]; free(max_array); } } //end parallel construct (*abs_info).total = tmp; /* * Here, we find the total number of * points considered active according to * param.p_thresh. */ for(j=0; j<param.pr_range; j++) { tmp_int = 0; #pragma omp parallel for reduction(+:tmp_int) for(i=0; i<L*L; i++) if(absW[i] >= param.pr_thresh[j]*(*abs_info).max) tmp_int++; (*abs_info).int_total[j] = tmp_int; } }
/****************************************************************************** * calc_A() * This function calcs the A's for a given theta. * * Parameters * --------- * * Returns * ------- * * Notes * ----- * This function assumes that the X[j] and g[j] values have already * been calculated (see calc_X()) * * Note: X[j] = Ar[j]/Ai[j] * And we can derive: * * Ai[j] = phase*Ai[j+1]*t[j+1] / ( 1 + phase^2 * X[j] * r[j+1]) * Ar[j] = Ai[j]*X[j] * * where Ar[j] and Ai[j] are the field amplitudes within layer j at * the j/j-1 interface. * * For the top layer Ai[nlayer-1] = 1. ie everything is referenced to * unit intensity (Io=|Ai|^2) within the top layer. Therefore Ar[0] = X[0]. * * Given the known values for the top layer we can procede to calculate each Ai and Ar * value starting at the top. * * For the base layer X[0] = 0, ie Ar[0] = 0 * * The values of r[j+1] and t[j+1] are the reflection and transmission coefficients * for the j+1/j interface, respectively, and calculated from: * * r[j+1] = (g[j+1]-g[j])/(g[j+1]+g[j]) * t[j+1] = 2*g[j+1]/(g[j+1] + g[j]) = 1 + r[j+1] * * This function also includes an interfacial roughness term mult into * the reflection coefficient for the j+1/j interface: * * r[j+1] = r[j+1]*exp(-1.0(q*sig[j+1])^2) * * Note we include roughness in the t calc using the below: * t[j+1] = 1 + r[j+1]*exp(-1.0(q*sig[j+1])^2) * * Therefore as r-> 0, t-> 1. This is only done if calc_params[10] > 0. * Otherwise t is calc explicitley from the g's * * The phase term accounts for the phase shift and attentuation of the field * traversing the j layer (ie from the j+1/j interface to the j/j-1 interface), * ie the Ai[j] and Ar[j] are the field amplitudes at the j/j-1 interface: * * phase = exp( -i*k*d[j] * g[j]) * * Note if j == 0 then the phase for layer j is 0.0, and X[0] = 0 * ie in the infinitley thick base layer we assumer the is no reflected * field (Ar[0] = 0.0) and we are calculating the the field amplitude at the * top of layer 0 rather than the bottom of layer 0. * * * Note: double check how doing the phase calc below, is that the best way?? * e.g. could we use: * phase = gsl_complex_exp( gsl_complex_mul_real(g1,-1.0*k*d[j])); * instead of * phase = gsl_complex_exp( gsl_complex_mul(phase,g1)); * * ******************************************************************************/ int calc_A(double theta, ref_model *ref, angle_calc *ang_c, layer_calc *lay_c){ int i, j, idx; double cos_sqr_thet, k, q, dw; double *d, *sig; gsl_complex g1, g2, num, den, r, t, Ai_2, Ar_2, Ai_1, Ar_1, X1, phase, phase_sqr; //gsl_complex n1, n2; // convenience vars cos_sqr_thet = square(cos(theta*M_PI/180.)); k = ref->k; q = 2.0*k*sin((theta*M_PI/180.)); d = ref->d; sig = ref->sigma; // start at top idx = ref->nlayer - 1; // get g for upper layer, ie air/vaccum slab // ie del ~ bet ~ 0. // n = 1 - del -i*bet ~ 1 // g2 = sqrt( n^2 - cos(theta)^2 ) //GSL_REAL(n2) = 1.0 - lay_c->del[idx]; //GSL_IMAG(n2) = -1.0*lay_c->bet[idx]; //g2 = gsl_complex_sqrt( gsl_complex_sub_real(gsl_complex_mul(n2, n2), cos_sqr_thet) ); GSL_SET_COMPLEX(&g2,ang_c->Re_g[idx],ang_c->Im_g[idx]); // for the top (j=nlayer-1) layer, Ai =1.0 // therefore Ar = Ai*X = X // store these in A arrays ang_c->Re_Ai[idx] = GSL_REAL(Ai_2) = 1.0; ang_c->Im_Ai[idx] = GSL_IMAG(Ai_2) = 0.0; ang_c->Re_Ar[idx] = GSL_REAL(Ar_2) = ang_c->Re_X[idx]; ang_c->Im_Ar[idx] = GSL_IMAG(Ar_2) = ang_c->Im_X[idx]; // loop over all layers, start at top - 1 // ie loop from j = nlayer-2 --> j = 0 // note j is lower layer in the r and t calcs // therefore we are considering the j+1/j interface // i is the interface number, ie which interface // are the r's and t's calc for i = idx - 1; for ( j = idx - 1; j > -1 ; j--){ // calc g and phase for lower layer // n = 1 - del -i*bet // g1 = sqrt( n^2 - cos(theta)^2 ) //GSL_REAL(n1) = 1.0 - xpar->del[j]; //GSL_IMAG(n1) = -1.0 * xpar->bet[j]; //g1 = gsl_complex_sqrt( gsl_complex_sub_real(gsl_complex_mul(n1, n1), cos_sqr_thet) ); GSL_SET_COMPLEX(&g1,ang_c->Re_g[j],ang_c->Im_g[j]); //calc phase and attenuation // phase = exp( -i*k*d[j] * g1) // phase_sqr = (phase)^2 if (j == 0){ GSL_REAL(phase) = 1.0; GSL_IMAG(phase) = 0.0; GSL_REAL(phase_sqr) = 1.0; GSL_IMAG(phase_sqr) = 0.0; } else { GSL_REAL(phase) = 0.0; GSL_IMAG(phase) = -1.0*k*d[j]; phase = gsl_complex_exp( gsl_complex_mul(phase,g1)); GSL_REAL(phase_sqr) = 0.0; GSL_IMAG(phase_sqr) = -2.0*k*d[j]; phase_sqr = gsl_complex_exp( gsl_complex_mul(phase_sqr,g1)); } // calc r for upper layer // r = (g2-g1)/(g2+g1) GSL_SET_COMPLEX(&num,0.0,0.0); GSL_SET_COMPLEX(&den,0.0,0.0); num = gsl_complex_sub(g2,g1); den = gsl_complex_add(g2,g1); r = gsl_complex_div(num,den); // include simple dw type roughness // r = r*exp(-1.0(q*sig)^2) if (ref->sigma[j+1] > 0.0){ //dw = exp(-1.0*square(q*ref->sigma[j+1])); dw = exp(-1.0*square(q*ref->sigma[i])); r = gsl_complex_mul_real(r,dw); } // calc t for upper layer // t = 2*g2/(g2 + g1) if (ref->calc_params[10] == 0.0){ GSL_SET_COMPLEX(&num,0.0,0.0); num = gsl_complex_mul_real(g2, 2.0); t = gsl_complex_div(num,den); } else { // note as as r->0, t->1 // ie t = 1+r, so we could just calc t from r? t = gsl_complex_add_real(r,1.0); } // calc Ai_1 and Ar_1 // these are field mag in the lower slab (layer j) // at the bottom of the slab, relative to Ai in the top layer (j=nlayer-1) // Ai_1 = phase*Ai_2*t / ( 1 + phase^2 * X1 * r) // Ar_1 = Ai_1*X1 GSL_REAL(X1) = ang_c->Re_X[j]; GSL_IMAG(X1) = ang_c->Im_X[j]; GSL_SET_COMPLEX(&num,0.0,0.0); GSL_SET_COMPLEX(&den,0.0,0.0); num = gsl_complex_mul(t,gsl_complex_mul(Ai_2,phase)); den = gsl_complex_add_real(gsl_complex_mul(phase_sqr,gsl_complex_mul(X1,r)),1.0); Ai_1 = gsl_complex_div(num,den); if (fabs(GSL_REAL(Ai_1)) < 1.0e-12){ GSL_REAL(Ai_1) = 0.0; } if (fabs(GSL_IMAG(Ai_1)) < 1.0e-12){ GSL_IMAG(Ai_1) = 0.0; } Ar_1 = gsl_complex_mul(Ai_1,X1); //store results ang_c->Re_Ai[j] = GSL_REAL(Ai_1); ang_c->Im_Ai[j] = GSL_IMAG(Ai_1); ang_c->Re_Ar[j] = GSL_REAL(Ar_1); ang_c->Im_Ar[j] = GSL_IMAG(Ar_1); // this is the field intensity at the bottom of layer j // except for layer j = 0, this is the intensity at the top // of the base layer (bc of how phase is calc above) // use bottom layer as top for next time through GSL_REAL(Ai_2) = GSL_REAL(Ai_1); GSL_IMAG(Ai_2) = GSL_IMAG(Ai_1); GSL_REAL(Ar_2) = GSL_REAL(Ar_1); GSL_IMAG(Ar_2) = GSL_IMAG(Ar_1); // do the same for g's GSL_REAL(g2) = GSL_REAL(g1); GSL_IMAG(g2) = GSL_IMAG(g1); // increment interface number i--; } return (SUCCESS); }
/****************************************************************************** * calc_X() * This function calcs the X's and g's for a given theta. * * Parameters * --------- * * Returns * ------- * * Notes * ----- * This function computes * X[j] = Ar[j]/Ai[j] * where Ar[j] and Ai[j] are the field amplitdues within layer j at * the j/j-1 interface. For the base layer X[0] = 0, * ie there is no reflected field in the substrate. While * X[nlayers-1] is the field intensity at the top of the multilayer, * therefore |X[nlayers-1]|^2 = R * * The X's are calculated using the optical recursion formlua, starting at the bottom * where X[0] = 0 and calc X[1], and proceding to calc of X[nlayer-1]: * * X[j] = ( r[j] + X[j-1]*phase) / (1 + r[j]*X[j-1]*phase) * * The r[j] values are the reflection coefficients for the j/j-1 interface, * and calculated from: * * r[j] = (g[j]-g[j-1])/(g[j]+g[j-1]) * * This function also includes an interfacial roughness term mult into * the reflection coefficient for the j/j-1 interface: * * r[j] = r[j]*exp(-1.0(q*sig[j])^2) * * The phase term accounts for the phase shift and attentuation of the field * traversing the j-1 layer (ie from the j-1/j-2 interface to the j/j-1 interface) * * phase = exp( -i* 2*k*d[j-1] * g[j-1]) * * Note if j == 1 then the phase for layer j-1 is 0.0, * ie infinitley thick base layer * * Note: g[j] = sqrt( n[j]^2 - cos(theta)^2 ) * where n[j] is the layers index of refraction: n[j] = 1-del[j]-i*bet[j] * Hence, each layer has a unique g value. We assume here * that the del[j] and bet[j] have already been calculated * (see calc_del_bet(), this should be called before this function). * * * Note: double check how doing the phase calc below, is that the best way?? * e.g. could we use: * phase = gsl_complex_exp( gsl_complex_mul_real(g1,-1.0*k*d[j])); * instead of * phase = gsl_complex_exp( gsl_complex_mul(phase,g1)); * * Note we should move the g and r calc to a new function, possibly calc the * t values as well and store these so we dont have to recalc in calc_A() (???) * ******************************************************************************/ int calc_X(double theta, ref_model *ref, angle_calc *ang_c, layer_calc *lay_c){ int i, j; double cos_sqr_thet, k, q, dw; double *d, *sig; gsl_complex g1, g2, num, den, r, X2, X1, n1, n2, phase; // convenience vars cos_sqr_thet = square(cos(theta*M_PI/180.)); k = ref->k; q = 2.0*k*sin((theta*M_PI/180.)); d = ref->d; sig = ref->sigma; // start at bottom // ie interface 0 ang_c->Re_X[0] = GSL_REAL(X1) = 0.0; ang_c->Im_X[0] = GSL_IMAG(X1) = 0.0; // calc g for base layer (g[0]) // n = 1 - del -i*bet // g = sqrt( n^2 - cos(theta)^2 ) GSL_REAL(n1) = 1.0 - lay_c->del[0]; GSL_IMAG(n1) = -1.0*lay_c->bet[0]; g1 = gsl_complex_sqrt( gsl_complex_sub_real(gsl_complex_mul(n1, n1), cos_sqr_thet) ); // store g for base layer ang_c->Re_g[0] = GSL_REAL(g1); ang_c->Im_g[0] = GSL_IMAG(g1); // loop over all layers // note j is upper layer and i is the interface number // the loop starts considering the first interface (i=0) // which is the interface between the base layer (j=0) // and the first layer (j=1) ie the 1/0 interface // note there are nlayer-1 interfaces... i = 0; for ( j = 1; j < ref->nlayer; j++){ // calc g for upper layer // n = 1 - del -i*bet // g2 = sqrt( n^2 - cos(theta)^2 ) GSL_REAL(n2) = 1.0 - lay_c->del[j]; GSL_IMAG(n2) = -1.0 * lay_c->bet[j]; g2 = gsl_complex_sqrt( gsl_complex_sub_real(gsl_complex_mul(n2, n2), cos_sqr_thet) ); // store g for layer j ang_c->Re_g[j] = GSL_REAL(g2); ang_c->Im_g[j] = GSL_IMAG(g2); // calculate r for the j/j-1 interface // r_j = (g2-g1)/(g2+g1) //GSL_SET_COMPLEX(&num,0.0,0.0); //GSL_SET_COMPLEX(&den,0.0,0.0); //GSL_SET_COMPLEX(&r,0.0,0.0); num = gsl_complex_sub(g2,g1); den = gsl_complex_add(g2,g1); r = gsl_complex_div(num,den); // calc r including roughness // simple dw roughness model // r = r*exp(-1.0(q*sig)^2) // sigma[i] if (ref->sigma[j] > 0.0){ //dw = exp(-1.0*square(q*ref->sigma[j])); dw = exp(-1.0*square(q*ref->sigma[i])); r = gsl_complex_mul_real(r,dw); } //calc phase shift and attentuation for //field traversing the j-1 layer //phase = exp( -i* 2*k*d[j-1] * g1) // if j == 1 then the phase for layer j-1 // is 0.0, ie infinitley thick base layer if (j == 1){ GSL_REAL(phase) = 0.0; GSL_IMAG(phase) = 0.0; } else { // check here GSL_REAL(phase) = 0.0; GSL_IMAG(phase) = -2.0*k*d[j-1]; phase = gsl_complex_exp( gsl_complex_mul(phase,g1)); } // calc Xj // X2 = ( r + X1*phase) / (1 + r*X1*phase) //GSL_SET_COMPLEX(&num,0.0,0.0); //GSL_SET_COMPLEX(&den,0.0,0.0); num = gsl_complex_add(r,gsl_complex_mul(X1,phase)); den = gsl_complex_add_real(gsl_complex_mul(r,gsl_complex_mul(X1,phase)), 1.0); X2 = gsl_complex_div(num,den); if (fabs(GSL_REAL(X2)) < 1e-10){ GSL_REAL(X2) = 0.0; } if (fabs(GSL_IMAG(X2)) < 1e-10){ GSL_IMAG(X2) = 0.0; } // store values of Xj ang_c->Re_X[j] = GSL_REAL(X2); ang_c->Im_X[j] = GSL_IMAG(X2); // use top layer as bottom for next time through GSL_REAL(X1) = GSL_REAL(X2); GSL_IMAG(X1) = GSL_IMAG(X2); // do the same for g's GSL_REAL(g1) = GSL_REAL(g2); GSL_IMAG(g1) = GSL_IMAG(g2); //increment the interface number i++; } return (SUCCESS); }