pure_expr *wrap_gsl_complex_sqrt(pure_expr *x) { gsl_complex z; if (pure_is_complex(x, z.dat)) { gsl_complex ret = gsl_complex_sqrt(z); return pure_complex(ret.dat); } else return 0; }
void gtmiso(gsl_matrix_complex * Tiso, gsl_complex eiso, double k0, double eta, double diso) { double eta2 = pow(eta,2); gsl_complex rb = gsl_complex_rect(eta2,0); gsl_complex za = gsl_complex_sub_real(eiso,eta2); gsl_complex qiso = gsl_complex_sqrt(za); gsl_complex zb = gsl_complex_mul_real(qiso,k0); gsl_complex zc = gsl_complex_mul_real(zb,diso); gsl_complex zd = gsl_complex_div(rb,eiso); gsl_complex carg = gsl_complex_cos(zc); gsl_complex sarg = gsl_complex_sin(zc); gsl_complex i = gsl_complex_rect(0,1); gsl_complex one = gsl_complex_rect(1,0); gsl_matrix_complex_set_zero(Tiso); gsl_matrix_complex_set(Tiso,0,0,carg); gsl_matrix_complex_set(Tiso,1,1,carg); gsl_matrix_complex_set(Tiso,2,2,carg); gsl_matrix_complex_set(Tiso,3,3,carg); gsl_complex zd1 = gsl_complex_sub(one,zd); gsl_complex zd2 = eiso; gsl_complex zd3 = one; gsl_complex zd4 = gsl_complex_sub_real(eiso,eta2); gsl_complex zmult1 = gsl_complex_mul(zd1,i); gsl_complex zmult2 = gsl_complex_mul(zd2,i); gsl_complex zmult3 = gsl_complex_mul(zd3,i); gsl_complex zmult4 = gsl_complex_mul(zd4,i); gsl_complex zdiv1 = gsl_complex_div(zmult1,qiso); gsl_complex zdiv2 = gsl_complex_div(zmult2,qiso); gsl_complex zdiv3 = gsl_complex_div(zmult3,qiso); gsl_complex zdiv4 = gsl_complex_div(zmult4,qiso); gsl_complex zmult5 = gsl_complex_mul(zdiv1,sarg); gsl_complex zmult6 = gsl_complex_mul(zdiv2,sarg); gsl_complex zmult7 = gsl_complex_mul(zdiv3,sarg); gsl_complex zmult8 = gsl_complex_mul(zdiv4,sarg); gsl_matrix_complex_set(Tiso,0,1,zmult5); gsl_matrix_complex_set(Tiso,1,0,zmult6); gsl_matrix_complex_set(Tiso,2,3,zmult7); gsl_matrix_complex_set(Tiso,3,2,zmult8); }
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; }
/* NOTE: Assumes z is in fundamental parallelogram */ void wP_and_prime(gsl_complex z, gsl_complex tau, const gsl_complex *g, gsl_complex *p, gsl_complex *pp) { int N = 6; /* Enough iterations for good P, not so good P' */ int i; gsl_complex z0; gsl_complex z02; gsl_complex pout, ppout; gsl_complex ppsolve; z = near_origin(z,tau); z0 = gsl_complex_div_real(z,(double)(1 << N)); z02 = gsl_complex_mul(z0,z0); /* Laurent expansion: P \approx 1/z^2 + (g2/20)z^2 + (g3/28) z^4 */ pout = gsl_complex_add(gsl_complex_inverse(z02), gsl_complex_add(gsl_complex_mul(z02,gsl_complex_mul_real(g[0],0.05)), gsl_complex_mul(gsl_complex_mul(z02,z02),gsl_complex_mul_real(g[1],_CONST_1_28)))); /* Laurent expansion: P' \approx -2/z^3 + g2/10z + g3/7 z^3 */ ppout = gsl_complex_add(gsl_complex_mul_real(gsl_complex_inverse(gsl_complex_mul(z0,z02)),-2.0), gsl_complex_add(gsl_complex_mul(z0,gsl_complex_mul_real(g[0],0.1)), gsl_complex_mul(gsl_complex_mul(z0,z02),gsl_complex_mul_real(g[1],_CONST_1_7)))); for (i=0;i<N;i++) { P_and_Pprime_doubler(&pout, &ppout, g); } /* At this point ppout is a decent but not great approximation of P'(z) */ /* Instead of using it directly, we use it as a guide for which square root of */ /* (4P^3 - g2 P - g3) should be selected. */ ppsolve = gsl_complex_sqrt( gsl_complex_sub( gsl_complex_mul_real(gsl_complex_mul(pout,gsl_complex_mul(pout,pout)),4.0), gsl_complex_add(gsl_complex_mul(g[0],pout),g[1]) ) ); *p = pout; if (gsl_complex_abs(gsl_complex_sub(ppsolve,ppout)) < gsl_complex_abs(gsl_complex_add(ppsolve,ppout))) *pp = ppsolve; else *pp = gsl_complex_negative(ppsolve); }
/** Square root of a complex number \ingroup complex \param[in] z Complex number \return \f$ \sqrt z \f$*/ complex sqrt(const complex& z) { return complex(gsl_complex_sqrt(z.as_gsl_type())); }
ComplexGSL sqrt( ComplexGSL& c ) { return ComplexGSL(gsl_complex_sqrt(c.z)); }
/****************************************************************************** * 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); }