Skip to content

Commit 8881f9c

Browse files
committed
Implemented calculations of decay-rate enhancement for point-dipole incident beam. Total part is calculated with the help of a new function DecayCross() in crosssec.c/h (similar to Cext), non-radiative part - by normalizing Cabs. In case of surface, all parts of decay-rate enhancement (total, rad, nonrad) are normalized to that in free space, but additionally enhancement due to surface alone is shown.
Still, it is not clear whether the non-radiative part should be adjusted to account for absorption in the substrate (when it is absorbing). Also, incident polarizations (Y and X) are not shown in the log for point-dipole incident beam. This is a bit problematic for standard LDR polarizability, since its factor S depends on both prop and incPol. But it probably makes little sense to use LDR polarizability for such incident field anyway (recommendation should be added to the manual). One test was run for dipole near a sphere was run and matched exactly to first row of Table 1 in S. D'Agostino, F. Della Sala, and L.C. Andreani, “Dipole-excited surface plasmons in metallic nanoparticles: Engineering decay dynamics within the discrete-dipole approximation,” Phys. Rev. B 87, 205413 (2013). However, a few hacks were used to exactly match the simulation conditions (based on raw data provided by Stefania D'Agostino.
1 parent 2951481 commit 8881f9c

File tree

5 files changed

+84
-7
lines changed

5 files changed

+84
-7
lines changed

src/CalculateE.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ extern double * restrict muel_alpha;
4646
// defined and initialized in crosssec.c
4747
extern const Parms_1D phi_sg;
4848
extern const double ezLab[3],exSP[3];
49+
// defined and initialized in GenerateB.c
50+
extern const double C0dipole,C0dipole_refl;
4951
// defined and initialized in param.c
5052
extern const bool store_int_field,store_dip_pol,store_beam,store_scat_grid,calc_Cext,calc_Cabs,
5153
calc_Csca,calc_vec,calc_asym,calc_mat_force,store_force,store_ampl;
@@ -716,6 +718,22 @@ static void CalcIntegralScatQuantities(const enum incpol which)
716718
CCfile=FOpenErr(fname_cs,"w",ONE_POS);
717719
if (calc_Cext) PrintBoth(CCfile,"Cext\t= "GFORM"\nQext\t= "GFORM"\n",Cext,Cext*inv_G);
718720
if (calc_Cabs) PrintBoth(CCfile,"Cabs\t= "GFORM"\nQabs\t= "GFORM"\n",Cabs,Cabs*inv_G);
721+
if (beamtype==B_DIPOLE) {
722+
double self=1;
723+
if (surface) self+=C0dipole_refl/C0dipole;
724+
double tot=self+DecayCross()/C0dipole;
725+
fprintf(CCfile,"\nDecay-rate enhancement\n\n");
726+
printf("\nDecay-rate enhancement:\n");
727+
PrintBoth(CCfile,"Total\t= "GFORM"\n",tot);
728+
if (calc_Cabs) { // for simplicity we keep a single condition here
729+
double nonrad=Cabs/C0dipole;
730+
double rad=tot-nonrad;
731+
// TODO: !!! how nonrad should account for absorption inside the surface???
732+
PrintBoth(CCfile,"Radiat\t= "GFORM"\n",rad);
733+
PrintBoth(CCfile,"Nonrad\t= "GFORM"\n",nonrad);
734+
}
735+
if (surface) PrintBoth(CCfile,"Surface\t= "GFORM"\n",self);
736+
}
719737
if (all_dir) fprintf(CCfile,"\nIntegration\n\n");
720738
if (calc_Csca) {
721739
Csca=ScaCross(f_suf);

src/GenerateB.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ extern const char *beam_fnameY;
4646
extern const char *beam_fnameX;
4747
extern const opt_index opt_beam;
4848

49+
// used in CalculateE.c
50+
double C0dipole,C0dipole_refl; // inherent cross sections of exciting dipole (in free space and addition due to surface)
51+
4952
// used in crosssec.c
5053
double beam_center_0[3]; // position of the beam center in laboratory reference frame
5154
/* complex wave amplitudes of secondary waves (with phase relative to particle center);
@@ -327,6 +330,31 @@ void GenerateB (const enum incpol which, // x - or y polarized incident light
327330
cvAdd(v1,b+j,b+j);
328331
}
329332
}
333+
/* calculate dipole inherent cross sections (for decay rate enhancements)
334+
* General formula is C0=4pi*k*Im(p0*.G(r0,r0).p0) and it is used for reflection; but for direct
335+
* interaction it is expected to be singular, so we use an explicit formula for point dipole:
336+
* C0=(8pi/3)*k^4*|p0|^2. Thus we discard the choice of "-int ...", but still the used value should be
337+
* correct for most formulations, e.g. poi, fcd, fcd_st, igt_so. Moreover, it is also logical, since the
338+
* exciting dipole is really point one, in contrast to the dipoles composing the particle.
339+
*/
340+
C0dipole=2*FOUR_PI_OVER_THREE*WaveNum*WaveNum*WaveNum*WaveNum;
341+
printf("C0=%g\n",C0dipole);
342+
if (surface) {
343+
r1[0]=r1[1]=0;
344+
r1[2]=2*(beam_center[2]+hsub);
345+
(*ReflTerm_real)(r1,gt);
346+
double tmp;
347+
/* the following expression uses that prop is real and a specific (anti-)symmetry of the gt
348+
* a general expression is commented out below
349+
*/
350+
tmp=prop[0]*prop[0]*cimag(gt[0])+2*prop[0]*prop[1]*cimag(gt[1])+prop[1]*prop[1]*cimag(gt[3])
351+
+prop[2]*prop[2]*cimag(gt[5]);
352+
// v1[0]=prop[0]; v1[1]=prop[1]; v1[2]=prop[2];
353+
// cReflMatrVec(gt,v1,v2);
354+
// tmp=cDotProd_Im(v2,v1);
355+
C0dipole_refl=FOUR_PI*WaveNum*tmp;
356+
printf("C0refl=%g\n",C0dipole_refl);
357+
}
330358
return;
331359
case B_LMINUS:
332360
case B_DAVIS3:

src/crosssec.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,29 @@ double AbsCross(void)
948948

949949
//======================================================================================================================
950950

951+
double DecayCross(void)
952+
// computes total cross section for the dipole incident field; similar to Cext
953+
// 4pi*k*Im[p0(*).Escat(r0)]
954+
{
955+
double sum;
956+
size_t i;
957+
958+
/* This is a correct expression only _if_ exciting p0 is real, then
959+
* (using G(r1,r2) = G(r2,r1)^T, valid also for surface)
960+
* p0(*).Escat_i(r0) = p0(*).G_0i.p_i = p_i.G_i0.p0(*) = p_i.G_i0.p0 = p_i.Einc_i
961+
* => Im(p0(*).Escat(r0)) = sum{Im(P.E_inc)}
962+
*
963+
* For complex p0 an efficient calculation strategy (not to waste evaluations of interaction) is to compute an array
964+
* of G_i0.p0(*) together with Einc and use it here afterwards.
965+
*/
966+
sum=0;
967+
for (i=0;i<local_nvoid_Ndip;++i) sum+=cimag(cDotProd_conj(pvec+3*i,Einc+3*i)); // sum{Im(P.E_inc)}
968+
MyInnerProduct(&sum,double_type,1,&Timing_ScatQuanComm);
969+
return FOUR_PI*WaveNum*sum;
970+
}
971+
972+
//======================================================================================================================
973+
951974
void SetScatPlane(const double ct,const double st,const double phi,double robs[static restrict 3],
952975
double polPer[static restrict 3])
953976
/* Given theta (cos,sin) and phi, calculates scattering direction and unit vector perpendicular to the scattering plane.

src/crosssec.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ void CalcField(doublecomplex ebuff[static restrict 3],const double n[static rest
2525
void InitRotation(void);
2626
double ExtCross(const double * restrict incPol);
2727
double AbsCross(void);
28+
double DecayCross(void);
2829
double ScaCross(const char *f_suf);
2930
void ReadAlldirParms(const char * restrict fname);
3031
void ReadAvgParms(const char * restrict fname);

src/param.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ static struct opt_struct options[]={
544544
{PAR(prognosis),"","Do not actually perform simulation (not even memory allocation) but only estimate the required "
545545
"RAM. Implies '-test'.",0,NULL},
546546
{PAR(prop),"<x> <y> <z>","Sets propagation direction of incident radiation, float. Normalization (to the unity "
547-
"vector) is performed automatically.\n"
547+
"vector) is performed automatically. For point-dipole incident beam this determines its direction.\n"
548548
"Default: 0 0 1",3,NULL},
549549
{PAR(recalc_resid),"","Recalculate residual at the end of iterative solver.",0,NULL},
550550
#ifndef SPARSE
@@ -2198,9 +2198,12 @@ void PrintInfo(void)
21982198
// log incident beam and polarization
21992199
fprintf(logfile,"\n---In laboratory reference frame:---\nIncident beam: %s\n",beam_descr);
22002200
fprintf(logfile,"Incident propagation vector: "GFORMDEF3V"\n",COMP3V(prop_0));
2201-
fprintf(logfile,"Incident polarization Y(par): "GFORMDEF3V"\n",COMP3V(incPolY_0));
2202-
fprintf(logfile,"Incident polarization X(per): "GFORMDEF3V"\n",COMP3V(incPolX_0));
2203-
if (surface) { // include surface-specific vectors
2201+
if (beamtype==B_DIPOLE) fprintf(logfile,"(dipole orientation)\n");
2202+
else { // polarizations are not shown for dipole incident field
2203+
fprintf(logfile,"Incident polarization Y(par): "GFORMDEF3V"\n",COMP3V(incPolY_0));
2204+
fprintf(logfile,"Incident polarization X(per): "GFORMDEF3V"\n",COMP3V(incPolX_0));
2205+
}
2206+
if (surface && beamtype==B_DIPOLE) { // include surface-specific vectors
22042207
fprintf(logfile,"Reflected propagation vector: "GFORMDEF3V"\n",COMP3V(prIncRefl));
22052208
fprintf(logfile,"Transmitted propagation vector: ");
22062209
if (msubInf) fprintf (logfile,"none\n");
@@ -2221,10 +2224,14 @@ void PrintInfo(void)
22212224
if (beam_asym) fprintf(logfile,"Incident Beam center position: "GFORMDEF3V"\n",
22222225
beam_center[0],beam_center[1],beam_center[2]);
22232226
fprintf(logfile,"Incident propagation vector: "GFORMDEF3V"\n",COMP3V(prop));
2224-
fprintf(logfile,"Incident polarization Y(par): "GFORMDEF3V"\n",COMP3V(incPolY));
2225-
fprintf(logfile,"Incident polarization X(per): "GFORMDEF3V"\n\n",COMP3V(incPolX));
2227+
if (beamtype==B_DIPOLE) fprintf(logfile,"(dipole orientation)\n");
2228+
else { // polarizations are not shown for dipole incident field
2229+
fprintf(logfile,"Incident polarization Y(par): "GFORMDEF3V"\n",COMP3V(incPolY));
2230+
fprintf(logfile,"Incident polarization X(per): "GFORMDEF3V"\n",COMP3V(incPolX));
2231+
}
22262232
}
2227-
else fprintf(logfile,"Particle orientation: default\n\n");
2233+
else fprintf(logfile,"Particle orientation: default\n");
2234+
fprintf(logfile,"\n");
22282235
}
22292236
// log type of scattering matrices
22302237
if (store_mueller) {

0 commit comments

Comments
 (0)