#ifndef RTS_ESPHERE #define RTS_ESPHERE #include "../math/complex.h" #include "../math/bessel.h" #include "../visualization/colormap.h" #include "../optics/planewave.h" #include "../cuda/devices.h" #include "../optics/efield.cuh" namespace stim{ /* This class implements a discrete representation of an electromagnetic field in 2D scattered by a sphere. This class implements Mie scattering. */ template class esphere : public efield

{ private: stim::complex

n; //sphere refractive index P a; //sphere radius //parameters dependent on wavelength unsigned int Nl; //number of orders for the calculation rts::complex

* A; //internal scattering coefficients rts::complex

* B; //external scattering coefficients void calcNl(P kmag) { //return ceil( ((P)6.282 * a) / lambda + 4 * pow( ((P)6.282 * a) / lambda, ((P)1/(P)3)) + 2); Nl = ceil( kmag*a + 4 * pow(kmag * a, (P)1/(P)3) + 2); } void calcAB(P k, unsigned int Nl, rts::complex

* A, rts::complex

* B) { /* These calculations require double precision, so they are computed using doubles and converted to P at the end. Input: k = magnitude of the k vector (tau/lambda) Nl = highest order coefficient ([0 Nl] are computed) */ //clear the previous coefficients rts::complex

* cpuA = (rts::complex

*)malloc(sizeof(rts::complex

) * (Nl+1)); rts::complex

* cpuB = (rts::complex

*)malloc(sizeof(rts::complex

) * (Nl+1)); //convert to an std complex value complex nc = (rts::complex)n; //compute the magnitude of the k vector complex kna = nc * k * (double)a; //compute the arguments k*a and k*n*a complex ka(k * a, 0.0); //allocate space for the Bessel functions of the first and second kind (and derivatives) unsigned int bytes = sizeof(complex) * (Nl + 1); complex* cjv_ka = (complex*)malloc(bytes); complex* cyv_ka = (complex*)malloc(bytes); complex* cjvp_ka = (complex*)malloc(bytes); complex* cyvp_ka = (complex*)malloc(bytes); complex* cjv_kna = (complex*)malloc(bytes); complex* cyv_kna = (complex*)malloc(bytes); complex* cjvp_kna = (complex*)malloc(bytes); complex* cyvp_kna = (complex*)malloc(bytes); //allocate space for the spherical Hankel functions and derivative complex* chv_ka = (complex*)malloc(bytes); complex* chvp_ka = (complex*)malloc(bytes); //compute the bessel functions using the CPU-based algorithm double vm; cbessjyva_sph(Nl, ka, vm, cjv_ka, cyv_ka, cjvp_ka, cyvp_ka); cbessjyva_sph(Nl, kna, vm, cjv_kna, cyv_kna, cjvp_kna, cyvp_kna); //compute A for each order complex i(0, 1); complex a, b, c, d; complex An, Bn; for(int l=0; l<=Nl; l++) { //compute the Hankel functions from j and y chv_ka[l] = cjv_ka[l] + i * cyv_ka[l]; chvp_ka[l] = cjvp_ka[l] + i * cyvp_ka[l]; //Compute A (internal scattering coefficient) //compute the numerator and denominator for A a = cjv_ka[l] * chvp_ka[l] - cjvp_ka[l] * chv_ka[l]; b = cjv_kna[l] * chvp_ka[l] - chv_ka[l] * cjvp_kna[l] * nc; //calculate A and add it to the list rts::complex An = (2.0 * l + 1.0) * pow(i, l) * (a / b); cpuA[l] = (rts::complex

)An; //Compute B (external scattering coefficient) c = cjv_ka[l] * cjvp_kna[l] * nc - cjv_kna[l] * cjvp_ka[l]; d = cjv_kna[l] * chvp_ka[l] - chv_ka[l] * cjvp_kna[l] * nc; //calculate B and add it to the list rts::complex Bn = (2.0 * l + 1.0) * pow(i, l) * (c / d); cpuB[l] = (rts::complex

)Bn; std::cout<<"A: "<) * (Nl+1)); //allocate memory for new coefficients cudaMalloc(&B, sizeof(rts::complex

) * (Nl+1)); //copy the calculations from the CPU to the GPU cudaMemcpy(A, cpuA, sizeof(rts::complex

) * (Nl+1), cudaMemcpyDeviceToHost); cudaMemcpy(B, cpuB, sizeof(rts::complex

) * (Nl+1), cudaMemcpyDeviceToHost); } public: esphere(unsigned int res0, unsigned int res1, P _a, rts::complex

_n, bool _scalar = false) : efield

(res0, res1, _scalar) { std::cout<<"Sphere scattered field created."< & operator= (const planewave

& rhs) { calcNl(rhs.kmag()); //compute the number of scattering coefficients std::cout<<"Nl: "<::str()<