Skip to content

Commit 2951481

Browse files
committed
Implementation of point-dipole incident field (issue 149). Should work both for free space and in the presence of surface (dipole should be above the surface). Controlled by new beam type: '-beam dipole <x> <y> <z>', dipole is assumed to have unity amplitude with direction, given by '-prop ...' command line option (e_z by default).
To do this the logic in interaction.c/h was significantly modified. Now two types of functions are defined (visible outside) for both direct and reflected interaction, accepting either integers (in units of d, used for filling interaction matrix) or real values (in um, useful for other applications, such as incident dipole field or nearfields). Thus the whole existing machinery of interaction.c/h (all formulations, numerical routines, etc.) can easily be accessed from other parts of the code. - internally, those functions are usually wrappers which reuse most of the code by calling inline functions. - some of the interaction formulations (igt_so and so) are incompatible with arbitrary real arguments, since they are tightly linked to existing tables. If used they produce a careful exception (new flag InteractionRealArgs added for that). - computing reflected Green's tensor (based on Sommerfeld integrals) was split into modules, including the tabulation. Now further optimization efforts can be directed precisely. Still a lot to do - to test, integrate (add exceptions) to other parts of ADDA, add enhancement rates (radiative and non-radiative) to the output. Other (related) changes: - a number of exceptions with respect to combination of different beam types, -prop, and -surf were moved from VariablesInterconnect to InitBeam. Now they are more accurate. - beam info for Gaussian beam was made more uniform. For centered beams, "Center is in the origin" was changed to "Center position: (0,0,0)". - new functions cSymMatrVecReal and cReflMatrVecReal in cmplx.h - version incremented to 1.3b2. - test suites in tests/2exec/ were updated to include new features.
1 parent 3fd68c9 commit 2951481

File tree

11 files changed

+412
-167
lines changed

11 files changed

+412
-167
lines changed

src/GenerateB.c

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "cmplx.h"
3131
#include "comm.h"
3232
#include "io.h"
33+
#include "interaction.h"
3334
#include "param.h"
3435
#include "vars.h"
3536
// system headers
@@ -89,6 +90,10 @@ void InitBeam(void)
8990
if (IFROOT) strcpy(beam_descr,"plane wave");
9091
beam_asym=false;
9192
if (surface) {
93+
if (prop_0[2]==0) PrintError("Ambiguous setting of beam propagating along the surface. Please specify "
94+
"the incident direction to have (arbitrary) small positive or negative z-component");
95+
if (msubInf && prop_0[2]>0) PrintError("Perfectly reflecting surface ('-surf ... inf') is incompatible "
96+
"with incident direction from below (including the default one)");
9297
// Here we set ki,kt,ktVec and propagation directions prIncRefl,prIncTran
9398
if (prop_0[2]>0) { // beam comes from the substrate (below)
9499
// here msub should always be defined
@@ -119,17 +124,30 @@ void InitBeam(void)
119124
}
120125
}
121126
return;
127+
case B_DIPOLE:
128+
vCopy(beam_pars,beam_center_0);
129+
if (surface && beam_center_0[2]<=-hsub)
130+
PrintErrorHelp("External dipole should be placed strictly above the surface");
131+
// in weird scenarios the dipole can be positioned exactly at the origin; reused code from Gaussian beams
132+
beam_asym=(beam_center_0[0]!=0 || beam_center_0[1]!=0 || beam_center_0[2]!=0);
133+
if (beam_asym) { // if necessary break the symmetry of the problem
134+
if (beam_center_0[0]!=0) symX=symR=false;
135+
if (beam_center_0[1]!=0) symY=symR=false;
136+
if (beam_center_0[2]!=0) symZ=false;
137+
}
138+
else vInit(beam_center);
139+
if (IFROOT) sprintf(beam_descr,"point dipole at "GFORMDEF3V,COMP3V(beam_center_0));
140+
return;
122141
case B_LMINUS:
123142
case B_DAVIS3:
124143
case B_BARTON5:
125-
if (surface) PrintErrorHelp("Currently, Gaussian incident beam is not supported for '-surf'");
144+
if (surface) PrintError("Currently, Gaussian incident beam is not supported for '-surf'");
126145
// initialize parameters
127146
w0=beam_pars[0];
128147
TestPositive(w0,"beam width");
129-
beam_asym=(beam_Npars==4 && (beam_pars[1]!=0 || beam_pars[2]!=0 || beam_pars[3]!=0));
130-
if (beam_asym) {
131-
vCopy(beam_pars+1,beam_center_0);
132-
// if necessary break the symmetry of the problem
148+
vCopy(beam_pars+1,beam_center_0);
149+
beam_asym=(beam_Npars==4 && (beam_center_0[0]!=0 || beam_center_0[1]!=0 || beam_center_0[2]!=0));
150+
if (beam_asym) { // if necessary break the symmetry of the problem
133151
if (beam_center_0[0]!=0) symX=symR=false;
134152
if (beam_center_0[1]!=0) symY=symR=false;
135153
if (beam_center_0[2]!=0) symZ=false;
@@ -154,10 +172,8 @@ void InitBeam(void)
154172
break;
155173
default: break;
156174
}
157-
sprintf(beam_descr+strlen(beam_descr),"\tWidth="GFORMDEF" (confinement factor s="GFORMDEF")\n",w0,s);
158-
if (beam_asym)
159-
sprintf(beam_descr+strlen(beam_descr),"\tCenter position: "GFORMDEF3V,COMP3V(beam_center_0));
160-
else strcat(beam_descr,"\tCenter is in the origin");
175+
sprintf(beam_descr+strlen(beam_descr),"\tWidth="GFORMDEF" (confinement factor s="GFORMDEF")\n"
176+
"\tCenter position: "GFORMDEF3V,w0,s,COMP3V(beam_center_0));
161177
}
162178
return;
163179
case B_READ:
@@ -186,6 +202,8 @@ void InitBeam(void)
186202
* beam_asym - whether beam center does not coincide with the reference frame origin. If it is set to true, then
187203
* set also beam_center_0 - 3D radius-vector of beam center in the laboratory reference frame (it
188204
* will be then automatically transformed to particle reference frame, if required).
205+
* 5) Consider the case of surface (substrate near the particle). If the new beam type is incompatible with it, add
206+
* an explicit exception, like "if (surface) PrintErrorHelp(...);".
189207
* All other auxiliary variables, which are used in beam generation (GenerateB(), see below), should be defined in
190208
* the beginning of this file. If you need temporary local variables (which are used only in this part of the code),
191209
* define them in the beginning of this function.
@@ -200,7 +218,7 @@ void GenerateB (const enum incpol which, // x - or y polarized incident light
200218
{
201219
size_t i,j;
202220
doublecomplex psi0,Q,Q2;
203-
doublecomplex v1[3],v2[3],v3[3];
221+
doublecomplex v1[3],v2[3],v3[3],gt[6];
204222
double ro2,ro4;
205223
double x,y,z,x2_s,xy_s;
206224
doublecomplex t1,t2,t3,t4,t5,t6,t7,t8,ctemp;
@@ -296,6 +314,20 @@ void GenerateB (const enum incpol which, // x - or y polarized incident light
296314
cvMultScal_RVec(ctemp,ex,b+j); // b[i]=ctemp*ex
297315
}
298316
return;
317+
case B_DIPOLE:
318+
for (i=0;i<local_nvoid_Ndip;i++) { // here we explicitly use that dipole moment (prop) is real
319+
j=3*i;
320+
LinComb(DipoleCoord+j,beam_center,1,-1,r1);
321+
(*InterTerm_real)(r1,gt);
322+
cSymMatrVecReal(gt,prop,b+j);
323+
if (surface) { // add reflected field
324+
r1[2]=DipoleCoord[j+2]+beam_center[2]+2*hsub;
325+
(*ReflTerm_real)(r1,gt);
326+
cReflMatrVecReal(gt,prop,v1);
327+
cvAdd(v1,b+j,b+j);
328+
}
329+
}
330+
return;
299331
case B_LMINUS:
300332
case B_DAVIS3:
301333
case B_BARTON5:
@@ -372,6 +404,8 @@ void GenerateB (const enum incpol which, // x - or y polarized incident light
372404
* 4) 'ey' – complementary unity vector of polarization (orthogonal to both 'prop' and 'ex');
373405
* 5) 'beam_center' – beam center in the particle reference frame (automatically calculated from 'beam_center_0'
374406
* defined in InitBeam).
407+
* If the new beam type is compatible with '-surf', include here the corresponding code. For that you will need
408+
* the variables, related to surface - see vars.c after "// related to a nearby surface".
375409
* If you need temporary local variables (which are used only in this part of the code), either use 't1'-'t8' or
376410
* define your own (with more informative names) in the beginning of this function.
377411
*/

src/cmplx.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,17 @@ static inline void cSymMatrVec(const doublecomplex matr[static 6],const doubleco
308308

309309
//======================================================================================================================
310310

311+
static inline void cSymMatrVecReal(const doublecomplex matr[static 6],const double vec[static 3],
312+
doublecomplex res[static 3])
313+
// multiplication of complex symmetric matrix[6] by vec[3]; res=matr.vec; !!! vec and res must not alias
314+
{
315+
res[0] = matr[0]*vec[0] + matr[1]*vec[1] + matr[2]*vec[2];
316+
res[1] = matr[1]*vec[0] + matr[3]*vec[1] + matr[4]*vec[2];
317+
res[2] = matr[2]*vec[0] + matr[4]*vec[1] + matr[5]*vec[2];
318+
}
319+
320+
//======================================================================================================================
321+
311322
static inline void cReflMatrVec(const doublecomplex matr[static 6],const doublecomplex vec[static 3],
312323
doublecomplex res[static 3])
313324
/* multiplication of matrix[6] by complex vec[3]; res=matr.vec; passed components are the same as for symmetric matrix:
@@ -320,6 +331,20 @@ static inline void cReflMatrVec(const doublecomplex matr[static 6],const doublec
320331
res[2] = - matr[2]*vec[0] - matr[4]*vec[1] + matr[5]*vec[2];
321332
}
322333

334+
//======================================================================================================================
335+
336+
static inline void cReflMatrVecReal(const doublecomplex matr[static 6],const double vec[static 3],
337+
doublecomplex res[static 3])
338+
/* multiplication of matrix[6] by complex vec[3]; res=matr.vec; passed components are the same as for symmetric matrix:
339+
* 11,12,13,22,23,33, but the matrix has the following symmetry - M21=M12, M31=-M13, M32=-M23
340+
* !!! vec and res must not alias
341+
*/
342+
{
343+
res[0] = matr[0]*vec[0] + matr[1]*vec[1] + matr[2]*vec[2];
344+
res[1] = matr[1]*vec[0] + matr[3]*vec[1] + matr[4]*vec[2];
345+
res[2] = - matr[2]*vec[0] - matr[4]*vec[1] + matr[5]*vec[2];
346+
}
347+
323348
//======================================================================================================================
324349
// operations on real vectors
325350

@@ -420,6 +445,14 @@ static inline double DotProd(const double a[static 3],const double b[static 3])
420445

421446
//======================================================================================================================
422447

448+
static inline double vNorm(const double a[static 3])
449+
// norm of a real vector[3]
450+
{
451+
return sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
452+
}
453+
454+
//======================================================================================================================
455+
423456
static inline void CrossProd(const double a[static 3],const double b[static 3],double c[static 3])
424457
// cross product of two real vectors; c = a x b; !!! vectors must not alias
425458
{

src/const.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#define __const_h
1919

2020
// version number (string)
21-
#define ADDA_VERSION "1.3b1"
21+
#define ADDA_VERSION "1.3b2"
2222

2323
/* ADDA uses certain C99 extensions, which are widely supported by GNU and Intel compilers. However, they may be not
2424
* completely supported by e.g. Microsoft Visual Studio compiler. Therefore, we check the version of the standard here
@@ -256,6 +256,7 @@ enum incpol {
256256
enum beam { // beam types
257257
B_BARTON5, // 5th order description of the Gaussian beam
258258
B_DAVIS3, // 3rd order description of the Gaussian beam
259+
B_DIPOLE, // field of a point dipole
259260
B_LMINUS, // 1st order description of the Gaussian beam
260261
B_PLANE, // infinite plane wave
261262
B_READ // read from file

src/fft.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,7 @@ static void InitRmatrix(const double invNgrid)
803803
// fill Rmatrix with values of reflected Green's tensor
804804
for(k=0;k<local_Nz_Rm;k++) for (j=jstartR;j<boxY;j++) for (i=1-boxX;i<boxX;i++) {
805805
index=NDCOMP*Index2matrix(i,j,k,R2sizeY);
806-
(*CalcReflTerm)(i,j,k,Rmatrix+index);
806+
(*ReflTerm_int)(i,j,k,Rmatrix+index);
807807
} // end of i,j,k loop
808808
if (IFROOT) printf("Fourier transform of Rmatrix");
809809
for(Rcomp=0;Rcomp<NDCOMP;Rcomp++) { // main cycle over components of Rmatrix
@@ -1105,7 +1105,7 @@ void InitDmatrix(void)
11051105
* 1) complicate the loops to remove the zero element in the beginning (move tests to the upper level)
11061106
* 2) call the function with zero - it will produce NaN. Then set this element to zero after the loop.
11071107
*/
1108-
if (i!=0 || j!=0 || kcor!=0) (*CalcInterTerm)(i,j,kcor,Dmatrix+index);
1108+
if (i!=0 || j!=0 || kcor!=0) (*InterTerm_int)(i,j,kcor,Dmatrix+index);
11091109
}
11101110
} // end of i,j,k loop
11111111
if (IFROOT) printf("Fourier transform of Dmatrix");

0 commit comments

Comments
 (0)