1 // c99 -ggdb -O2 -DLATTICESUMS -I .. hexlattice_ewald.c ../translations.c ../bessels.c ../lrhankel_recspace_dirty.c ../gaunt.c -lm -lgsl -lblas
9 #include <gsl/gsl_const_mksa.h>
10 #include <gsl/gsl_math.h>
11 #include "qpms_types.h"
12 #include "translations.h"
14 #define MAXOMEGACOUNT 1000
16 const double s3
= 1.732050807568877293527446341505872366942805253810380628055;
18 // IMPORTANT: lattice properties here
19 const qpms_y_t lMax
= 2;
20 const double REFINDEX
= 1.52;
21 const double LATTICE_H
= 576e-9;
22 static const double SCUFF_OMEGAUNIT
= 3e14
;
23 static const double hbar
= GSL_CONST_MKSA_PLANCKS_CONSTANT_HBAR
;
24 static const double eV
= GSL_CONST_MKSA_ELECTRON_CHARGE
;
25 static const double c0
= GSL_CONST_MKSA_SPEED_OF_LIGHT
;
26 static const double CC
= 0.1;
28 // For sorting the points by distance from origin / radius
29 int cart2_cmpr (const void *p1
, const void *p2
) {
30 const cart2_t
*p1t
= (const cart2_t
*)p1
;
31 const cart2_t
*p2t
= (const cart2_t
*)p2
;
32 double r21
= cart2norm(*p1t
);
33 double r22
= cart2norm(*p2t
);
34 if (r21
< r22
) return -1;
35 else if (r21
> r22
) return 1;
40 ptrdiff_t npoints
; // number of lattice points.
41 ptrdiff_t capacity
; // for how much points memory is allocated
42 double maxR
; // circle radius, points <= R
44 } latticepoints_circle_t
;
46 void sort_cart2points_by_r(cart2_t
*points
, size_t nmemb
) {
47 qsort(points
, nmemb
, sizeof(cart2_t
), cart2_cmpr
);
50 void latticepoints_circle_free(latticepoints_circle_t
*c
) {
55 // "horizontal" orientation of the adjacent A, B points
56 latticepoints_circle_t
generate_hexpoints_hor(double h
, double R
, cart2_t offset
/* if zero, an A is in the origin */) {
57 latticepoints_circle_t lat
;
60 int nmax
= R
/ (1.5 * h
) + 2; // max no of lattice shifts in each direction (with reserve)
61 double unitcellS
= s3
* 3 / 2 * h
* h
; // unit cell area
62 double flcapacity
= 5 + 2 * (R
+ 5*h
) * (R
+ 5*h
) * M_PI
/ unitcellS
; // should be enough with some random reserve
63 lat
.capacity
= flcapacity
;
65 lat
.points
= malloc(lat
.capacity
*sizeof(cart2_t
));
67 cart2_t BAoffset
= {h
, 0};
69 cart2_t a1
= {-1.5*h
, s3
/2 *h
};
70 cart2_t a2
= {1.5*h
, s3
/2 *h
};
72 for (ptrdiff_t i1
= -nmax
; i1
<= nmax
; ++i1
)
73 for (ptrdiff_t i2
= -nmax
; i2
<= nmax
; ++i2
) {
74 cart2_t Apoint
= cart2_add(offset
, cart2_add(cart2_scale(i1
, a1
), cart2_scale(i2
, a2
)));
75 if (lat
.npoints
>= lat
.capacity
)
76 printf("%zd %zd %g %g %g %g\n", lat
.npoints
, lat
.capacity
, flcapacity
, R
, h
, unitcellS
); if (cart2norm(Apoint
) <= R
) {
77 assert(lat
.npoints
< lat
.capacity
);
78 lat
.points
[lat
.npoints
] = Apoint
;
81 cart2_t Bpoint
= cart2_add(Apoint
, BAoffset
);
82 if (cart2norm(Bpoint
) <= R
) {
83 assert(lat
.npoints
< lat
.capacity
);
84 lat
.points
[lat
.npoints
] = Bpoint
;
88 sort_cart2points_by_r(lat
.points
, lat
.npoints
);
92 latticepoints_circle_t
generate_tripoints_ver(double a
, double R
, cart2_t offset
/* if zero, an A is in the origin */) {
94 latticepoints_circle_t lat
;
97 int nmax
= R
/ (1.5 * h
) + 2; // max no of lattice shifts in each direction (with reserve)
98 double unitcellS
= (s3
* 3) / 2 * h
* h
; // unit cell area
99 double flcapacity
= 5 + (R
+ 3*a
) * (R
+ 3*a
) * M_PI
/ unitcellS
; // should be enough with some random reserve
100 lat
.capacity
= flcapacity
; // should be enough with some random reserve
101 lat
.points
= malloc(lat
.capacity
*sizeof(cart2_t
));
103 cart2_t a1
= {-1.5*h
, s3
/2 *h
};
104 cart2_t a2
= {1.5*h
, s3
/2 *h
};
106 for (ptrdiff_t i1
= -nmax
; i1
<= nmax
; ++i1
)
107 for (ptrdiff_t i2
= -nmax
; i2
<= nmax
; ++i2
) {
108 cart2_t Apoint
= cart2_add(offset
, cart2_add(cart2_scale(i1
, a1
), cart2_scale(i2
, a2
)));
109 if (cart2norm(Apoint
) <= R
) {
110 if (lat
.npoints
>= lat
.capacity
)
111 printf("%zd %zd %g %g %g %g\n", lat
.npoints
, lat
.capacity
, flcapacity
, R
, a
, unitcellS
);
112 assert(lat
.npoints
< lat
.capacity
);
113 lat
.points
[lat
.npoints
] = Apoint
;
117 sort_cart2points_by_r(lat
.points
, lat
.npoints
);
121 latticepoints_circle_t
generate_tripoints_hor(double a
, double R
, cart2_t offset
/* if zero, an A is in the origin */) {
123 latticepoints_circle_t lat
;
126 int nmax
= R
/ (1.5 * h
) + 2; // max no of lattice shifts in each direction (with reserve)
127 double unitcellS
= s3
* 3 / 2 * h
* h
; // unit cell area
128 double flcapacity
= 5 + (R
+ 3*a
) * (R
+ 3*a
) * M_PI
/ unitcellS
; // should be enough with some random reserve
129 lat
.capacity
= flcapacity
; // should be enough with some random reserve
130 lat
.points
= malloc(lat
.capacity
*sizeof(cart2_t
));
132 cart2_t a1
= {s3
/2 *h
, -1.5*h
};
133 cart2_t a2
= {s3
/2 *h
, 1.5 * h
};
135 for (int i1
= -nmax
; i1
<= nmax
; ++i1
)
136 for (int i2
= -nmax
; i2
<= nmax
; ++i2
) {
137 if (lat
.npoints
>= lat
.capacity
)
138 printf("%zd %zd %.12g %g %g %g\n", lat
.npoints
, lat
.capacity
, flcapacity
, R
, a
, unitcellS
);
139 cart2_t Apoint
= cart2_add(offset
, cart2_add(cart2_scale(i1
, a1
), cart2_scale(i2
, a2
)));
140 if (cart2norm(Apoint
) <= R
) {
141 assert(lat
.npoints
< lat
.capacity
);
142 lat
.points
[lat
.npoints
] = Apoint
;
146 sort_cart2points_by_r(lat
.points
, lat
.npoints
);
150 int main (int argc
, char **argv
) {
151 const double LATTICE_A
= s3
*LATTICE_H
;
152 const double INVLATTICE_A
= 4 * M_PI
/ s3
/ LATTICE_A
;
153 const double MAXR_REAL
= 100 * LATTICE_H
;
154 const double MAXR_K
= 100 * INVLATTICE_A
;
157 char *omegafile
= argv
[1];
158 // char *kfile = argv[2]; // not used
159 char *outfile
= argv
[3];
160 char *outlongfile
= argv
[4];
161 char *outshortfile
= argv
[5];
162 double scuffomegas
[MAXOMEGACOUNT
];
163 cart2_t klist
[MAXKCOUNT
];
164 FILE *f
= fopen(omegafile
, "r");
166 while (fscanf(f
, "%lf", scuffomegas
+ omegacount
) == 1){
167 assert(omegacount
< MAXOMEGACOUNT
);
171 /*f = fopen(kfile, "r");
173 while (fscanf(f, "%lf %lf", &(klist[kcount].x), &(klist[kcount].y)) == 2) {
174 assert(kcount < MAXKCOUNT);
180 int kcount
= MAXKCOUNT
;
181 for (int i
= 0; i
< kcount
; ++i
) {
183 klist
[i
].y
= 2. * 4. * M_PI
/ 3. / LATTICE_A
/ kcount
* i
;
186 const double refindex
= REFINDEX
;
187 const double h
= LATTICE_H
;
188 const double a
= h
* s3
;
189 const double rec_a
= 4*M_PI
/s3
/a
;
191 // generation of the real-space lattices
192 const cart2_t cart2_0
= {0, 0};
193 const cart2_t ABoffset
= {h
, 0};
194 const cart2_t BAoffset
= {-h
, 0};
195 //const cart2_t ab_particle_offsets[2][2] = {{ {0, 0}, {h, 0} }, {-h, 0}, {0, 0}};
197 // THIS IS THE LATTICE OF r_b
198 latticepoints_circle_t lattice_0offset
= generate_tripoints_ver(a
, MAXR_REAL
, cart2_0
);
199 // these have to have the same point order, therefore we must make the offset verision manually to avoid sorting;
200 latticepoints_circle_t lattice_ABoffset
, lattice_BAoffset
;
201 lattice_ABoffset
.points
= malloc(lattice_0offset
.npoints
* sizeof(cart2_t
));
202 lattice_ABoffset
.capacity
= lattice_0offset
.npoints
* sizeof(cart2_t
);
203 lattice_ABoffset
.npoints
= lattice_ABoffset
.capacity
;
204 lattice_BAoffset
.points
= malloc(lattice_0offset
.npoints
* sizeof(cart2_t
));
205 lattice_BAoffset
.capacity
= lattice_0offset
.npoints
* sizeof(cart2_t
);
206 lattice_BAoffset
.npoints
= lattice_BAoffset
.capacity
;
207 for (int i
= 0; i
< lattice_0offset
.npoints
; ++i
) {
208 lattice_ABoffset
.points
[i
] = cart2_add(lattice_0offset
.points
[i
], ABoffset
);
209 lattice_BAoffset
.points
[i
] = cart2_add(lattice_0offset
.points
[i
], BAoffset
);
212 // reciprocal lattice, without offset – DON'T I NEED REFINDEX HERE? (I DON'T THINK SO.)
213 latticepoints_circle_t reclattice
= generate_tripoints_hor(rec_a
, MAXR_K
, cart2_0
);
215 qpms_trans_calculator
*c
= qpms_trans_calculator_init(lMax
, QPMS_NORMALISATION_POWER_CS
);
217 FILE *out
= fopen(outfile
, "w");
218 FILE *outlong
= fopen(outlongfile
, "w");
219 FILE *outshort
= fopen(outshortfile
, "w");
221 // as in eq. (5) in my notes
222 double WL_prefactor
= 4*M_PI
/(a
*a
)/s3
/ /*??*/ (4*M_PI
*M_PI
);
224 for (int omegai
= 0; omegai
< omegacount
; ++omegai
) {
225 double scuffomega
= scuffomegas
[omegai
];
226 double omega
= scuffomega
* SCUFF_OMEGAUNIT
;
227 double EeV
= omega
* hbar
/ eV
;
228 double k0_vac
= omega
/ c0
;
229 double k0_eff
= k0_vac
* refindex
; // this one will be used with the real x geometries
230 double cv
= CC
* k0_eff
;
232 complex double Abuf
[c
->nelem
][c
->nelem
], Bbuf
[c
->nelem
][c
->nelem
];
233 // indices : destpart (A/B-particle), srcpart (A/B-particle), coeff type (A/B- type), desty, srcy
234 complex double WS
[2][2][2][c
->nelem
][c
->nelem
];
235 complex double WS_comp
[2][2][2][c
->nelem
][c
->nelem
];
236 complex double WL
[2][2][2][c
->nelem
][c
->nelem
];
237 complex double WL_comp
[2][2][2][c
->nelem
][c
->nelem
];
239 for (int ki
= 0; ki
< kcount
; ++ki
) {
240 cart2_t k
= klist
[ki
];
241 memset(WS
, 0, sizeof(WS
));
242 memset(WS_comp
, 0, sizeof(WS_comp
));
243 memset(WL
, 0, sizeof(WL
));
244 memset(WL_comp
, 0, sizeof(WL_comp
));
246 for (int bi
= 0; bi
< lattice_0offset
.npoints
; ++bi
) {
247 cart2_t point0
= lattice_0offset
.points
[bi
];
248 double phase
= cart2_dot(k
,point0
);
249 complex double phasefac
= cexp(I
*phase
);
251 if (point0
.x
|| point0
.y
) { // skip the singular point
252 qpms_trans_calculator_get_shortrange_AB_arrays(c
, (complex double *) Abuf
, (complex double *) Bbuf
, c
->nelem
, 1,
253 cart22sph(cart2_scale(k0_eff
,lattice_0offset
.points
[bi
])), 3, 2, 5, CC
);
254 for (int desty
= 0; desty
< c
->nelem
; ++desty
)
255 for (int srcy
= 0; srcy
< c
->nelem
; ++srcy
) {
256 ckahanadd(&(WS
[0][0][0][desty
][srcy
]),&(WS_comp
[0][0][0][desty
][srcy
]),Abuf
[desty
][srcy
] * phasefac
);
257 ckahanadd(&(WS
[0][0][1][desty
][srcy
]),&(WS_comp
[0][0][1][desty
][srcy
]),Bbuf
[desty
][srcy
] * phasefac
);
260 qpms_trans_calculator_get_shortrange_AB_arrays(c
, (complex double *) Abuf
, (complex double *) Bbuf
, c
->nelem
, 1,
261 cart22sph(cart2_scale(k0_eff
,lattice_ABoffset
.points
[bi
])), 3, 2, 5, CC
);
262 for (int desty
= 0; desty
< c
->nelem
; ++desty
)
263 for (int srcy
= 0; srcy
< c
->nelem
; ++srcy
) {
264 ckahanadd(&(WS
[0][1][0][desty
][srcy
]),&(WS_comp
[0][1][0][desty
][srcy
]),Abuf
[desty
][srcy
] * phasefac
);
265 ckahanadd(&(WS
[0][1][1][desty
][srcy
]),&(WS_comp
[0][1][1][desty
][srcy
]),Bbuf
[desty
][srcy
] * phasefac
);
268 qpms_trans_calculator_get_shortrange_AB_arrays(c
, (complex double *) Abuf
, (complex double *) Bbuf
, c
->nelem
, 1,
269 cart22sph(cart2_scale(k0_eff
,lattice_BAoffset
.points
[bi
])), 3, 2, 5, CC
);
270 for (int desty
= 0; desty
< c
->nelem
; ++desty
)
271 for (int srcy
= 0; srcy
< c
->nelem
; ++srcy
) {
272 ckahanadd(&(WS
[1][0][0][desty
][srcy
]),&(WS_comp
[1][0][0][desty
][srcy
]),Abuf
[desty
][srcy
] * phasefac
);
273 ckahanadd(&(WS
[1][0][1][desty
][srcy
]),&(WS_comp
[1][0][1][desty
][srcy
]),Bbuf
[desty
][srcy
] * phasefac
);
275 // WS[1][1] is the same as WS[0][0], so copy in the end rather than double-summing
277 for (int desty
= 0; desty
< c
->nelem
; ++desty
)
278 for (int srcy
= 0; srcy
< c
->nelem
; ++srcy
)
279 for (int ctype
= 0; ctype
< 2; ctype
++)
280 WS
[1][1][ctype
][desty
][srcy
] = WS
[0][0][ctype
][desty
][srcy
];
282 for (int Ki
= 0; Ki
< reclattice
.npoints
; ++Ki
) {
283 cart2_t K
= reclattice
.points
[Ki
];
284 cart2_t k_K
= cart2_substract(k
, K
);
289 cart2_dot(k_K
, ABoffset
); // And maybe the sign is excactly opposite!!! FIXME TODO CHECK
290 complex double phasefacs
[2][2];
291 phasefacs
[0][0] = phasefacs
[1][1] = 1;
292 phasefacs
[1][0] = cexp(I
* phase_AB
); // sign???
293 phasefacs
[0][1] = cexp(- I
* phase_AB
); // sign???
295 // FIXME should I skip something (such as the origin?)
296 qpms_trans_calculator_get_2DFT_longrange_AB_arrays(c
, (complex double *) Abuf
, (complex double *) Bbuf
, c
->nelem
, 1,
297 cart22sph(k_K
), 3, 2, 5, cv
, k0_eff
);
298 for (int dp
= 0; dp
< 2; dp
++)
299 for (int sp
= 0; sp
< 2; sp
++)
300 for (int dy
= 0; dy
< c
->nelem
; dy
++)
301 for (int sy
= 0; sy
< c
->nelem
; sy
++) {
302 ckahanadd(&(WL
[dp
][sp
][0][dy
][sy
]), &(WL_comp
[dp
][sp
][0][dy
][sy
]), phasefacs
[dp
][sp
] * Abuf
[dy
][sy
] * WL_prefactor
);
303 ckahanadd(&(WL
[dp
][sp
][1][dy
][sy
]), &(WL_comp
[dp
][sp
][1][dy
][sy
]), phasefacs
[dp
][sp
] * Bbuf
[dy
][sy
] * WL_prefactor
);
306 fprintf(outshort
, "%.16g\t%.16g\t%16g\t%.16g\t%.16g\t",
307 scuffomega
, EeV
, k0_eff
, k
.x
, k
.y
);
308 fprintf(outlong
, "%.16g\t%.16g\t%16g\t%.16g\t%.16g\t",
309 scuffomega
, EeV
, k0_eff
, k
.x
, k
.y
);
310 fprintf(out
, "%.16g\t%.16g\t%16g\t%.16g\t%.16g\t",
311 scuffomega
, EeV
, k0_eff
, k
.x
, k
.y
);
312 size_t totalelems
= sizeof(WL
) / sizeof(complex double);
313 for (int i
= 0; i
< totalelems
; ++i
) {
314 complex double ws
= ((complex double *)WS
)[i
];
315 complex double wl
= ((complex double *)WL
)[i
];
316 complex double w
= ws
+wl
;
317 fprintf(outshort
, "%.16g\t%.16g\t", creal(ws
), cimag(ws
));
318 fprintf(outlong
, "%.16g\t%.16g\t", creal(wl
), cimag(wl
));
319 fprintf(out
, "%.16g\t%.16g\t", creal(w
), cimag(w
));
321 fputc('\n', outshort
);
322 fputc('\n', outlong
);
336 int main (int argc
, char **argv
) {
337 cart2_t offset
= {0,0};
339 latticepoints_circle_t lat
= generate_tripoints_ver(1, 200, offset
);
340 for (int i
= 0; i
< lat
.npoints
; ++i
)
341 printf("%g %g %g\n", lat
.points
[i
].x
, lat
.points
[i
].y
, cart2norm(lat
.points
[i
]));
342 latticepoints_circle_free(&lat
);