Disable "hard" examples in CI
[qpms.git] / qpms / apps / hexlattice_wrongewald.c
blobe8bc873b5350653968d90a0a848e0d89d92de2df
1 // c99 -ggdb -O2 -DLATTICESUMS -I .. hexlattice_ewald.c ../translations.c ../bessels.c ../lrhankel_recspace_dirty.c ../gaunt.c -lm -lgsl -lblas
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stddef.h>
5 #include <math.h>
6 #include <stdio.h>
7 #include "kahansum.h"
8 #include "vectors.h"
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
15 #define MAXKCOUNT 100
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;
36 else return 0;
39 typedef struct {
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
43 cart2_t *points;
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) {
51 free(c->points);
52 c->capacity = 0;
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;
58 lat.maxR = R;
59 lat.npoints = 0;
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;
79 lat.npoints++;
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;
85 lat.npoints++;
88 sort_cart2points_by_r(lat.points, lat.npoints);
89 return lat;
92 latticepoints_circle_t generate_tripoints_ver(double a, double R, cart2_t offset /* if zero, an A is in the origin */) {
93 double h = a / s3;
94 latticepoints_circle_t lat;
95 lat.maxR = R;
96 lat.npoints = 0;
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;
114 lat.npoints++;
117 sort_cart2points_by_r(lat.points, lat.npoints);
118 return lat;
121 latticepoints_circle_t generate_tripoints_hor(double a, double R, cart2_t offset /* if zero, an A is in the origin */) {
122 double h = a / s3;
123 latticepoints_circle_t lat;
124 lat.maxR = R;
125 lat.npoints = 0;
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;
143 lat.npoints++;
146 sort_cart2points_by_r(lat.points, lat.npoints);
147 return lat;
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");
165 int omegacount = 0;
166 while (fscanf(f, "%lf", scuffomegas + omegacount) == 1){
167 assert(omegacount < MAXOMEGACOUNT);
168 ++omegacount;
170 fclose(f);
171 /*f = fopen(kfile, "r");
172 int kcount = 100;
173 while (fscanf(f, "%lf %lf", &(klist[kcount].x), &(klist[kcount].y)) == 2) {
174 assert(kcount < MAXKCOUNT);
175 ++kcount;
177 fclose(f);
180 int kcount = MAXKCOUNT;
181 for (int i = 0; i < kcount; ++i) {
182 klist[i].x = 0;
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];
281 // WS DONE
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);
285 double phase_AB =
286 #ifdef SWAPSIGN1
288 #endif
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);
323 fputc('\n', out);
326 fclose(out);
327 fclose(outlong);
328 fclose(outshort);
335 #if 0
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);
344 #endif