Skip to content

Commit 171a32e

Browse files
committed
initial support for bott-indices function
1 parent 96cf487 commit 171a32e

File tree

5 files changed

+167
-40
lines changed

5 files changed

+167
-40
lines changed

mpb/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ EXTRA_DIST = mpb.scm.in epsilon.c mu.c
2020

2121
nodist_pkgdata_DATA = $(SPECIFICATION_FILE)
2222

23-
MY_SOURCES = medium.c epsilon_file.c field-smob.c fields.c \
23+
MY_SOURCES = bott.c medium.c epsilon_file.c field-smob.c fields.c \
2424
material_grid.c material_grid_opt.c matrix-smob.c mpb.c field-smob.h matrix-smob.h mpb.h my-smob.h
2525

2626
MY_LIBS = $(top_builddir)/src/matrixio/libmatrixio.a $(top_builddir)/src/libmpb@[email protected] $(NLOPT_LIB)

mpb/bott.c

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/* Copyright (C) 1999-2014 Massachusetts Institute of Technology.
2+
*
3+
* This program is free software; you can redistribute it and/or modify
4+
* it under the terms of the GNU General Public License as published by
5+
* the Free Software Foundation; either version 2 of the License, or
6+
* (at your option) any later version.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU General Public License
14+
* along with this program; if not, write to the Free Software
15+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16+
*/
17+
18+
#include <stdio.h>
19+
#include <stdlib.h>
20+
#include <math.h>
21+
22+
#include "config.h"
23+
24+
#include <check.h>
25+
#include <blasglue.h>
26+
#include <matrices.h>
27+
#include <matrixio.h>
28+
29+
#include "mpb.h"
30+
31+
sqmatrix shift_overlap(int band_start, int n_bands, int s1, int s2, int s3)
32+
{
33+
sqmatrix U, S1, S2;
34+
int final_band = band_start + n_bands, ib;
35+
36+
CHECK(mdata, "init-params must be called before shift_overlap");
37+
CHECK(band_start + n_bands <= num_bands, "not enough bands in shift_overlap");
38+
39+
U = create_sqmatrix(n_bands);
40+
41+
/* ...we have to do this in blocks of eigensolver_block_size since
42+
the work matrix W[0] may not have enough space to do it at once. */
43+
S1 = create_sqmatrix(n_bands);
44+
S2 = create_sqmatrix(n_bands);
45+
46+
for (ib = band_start; ib < final_band; ib += Hblock.alloc_p) {
47+
if (ib + Hblock.alloc_p > final_band) {
48+
maxwell_set_num_bands(mdata, final_band - ib);
49+
evectmatrix_resize(&Hblock, final_band - ib, 0);
50+
}
51+
maxwell_compute_H_from_shifted_B(mdata, H, Hblock,
52+
(scalar_complex *) mdata->fft_data,
53+
s1, s2, s3,
54+
ib, 0, Hblock.p);
55+
56+
evectmatrix_XtY_slice2(U, H, Hblock, band_start, 0, n_bands, Hblock.p,
57+
ib-band_start, S1, S2);
58+
}
59+
60+
/* Reset scratch matrix sizes: */
61+
evectmatrix_resize(&Hblock, Hblock.alloc_p, 0);
62+
maxwell_set_num_bands(mdata, Hblock.alloc_p);
63+
64+
destroy_sqmatrix(S2);
65+
destroy_sqmatrix(S1);
66+
return U;
67+
}
68+
69+
/* complex argument */
70+
static double scalar_carg(scalar_complex z)
71+
{
72+
return atan2(CSCALAR_IM(z), CSCALAR_RE(z));
73+
}
74+
75+
number_list bott_indices(integer band_start, integer n_bands)
76+
{
77+
sqmatrix U, W, S1, S2, Un, Wn;
78+
scalar_complex *eigvals;
79+
number_list bott;
80+
int i, n;
81+
82+
CHECK(mdata, "init-params must be called before shift_overlap");
83+
CHECK(mdata->nz == 1, "Bott index is not defined (yet) for 3d");
84+
85+
U = shift_overlap(band_start-1, n_bands, 0, 1, 0);
86+
W = shift_overlap(band_start-1, n_bands, 1, 0, 0);
87+
88+
/* allocate scratch arrays */
89+
S1 = create_sqmatrix(n_bands);
90+
S2 = create_sqmatrix(n_bands);
91+
Un = create_sqmatrix(n_bands);
92+
Wn = create_sqmatrix(n_bands);
93+
CHK_MALLOC(eigvals, scalar_complex, n_bands);
94+
95+
bott.num_items = n_bands;
96+
CHK_MALLOC(bott.items, number, n_bands);
97+
for (n = 1; n <= n_bands; ++n) { /* compute n-th bott index */
98+
sqmatrix_copy(Un, U);
99+
sqmatrix_copy(Wn, W);
100+
sqmatrix_resize(&Un, n, 1);
101+
sqmatrix_resize(&Wn, n, 1);
102+
sqmatrix_resize(&S1, n, 0);
103+
sqmatrix_resize(&S2, n, 0);
104+
sqmatrix_AeBC(S1, Wn, 0, Un, 0);
105+
sqmatrix_AeBC(S2, Wn, 1, Un, 1);
106+
sqmatrix_AeBC(Un, S1, 0, S2, 0);
107+
sqmatrix_eigenvalues(Un, eigvals);
108+
for (i = 0; i < n; ++i)
109+
bott.items[n-1] += scalar_carg(eigvals[i]);
110+
bott.items[i] /= 6.28318530717958647692528676655900; /* twopi */
111+
}
112+
destroy_sqmatrix(Wn);
113+
destroy_sqmatrix(Un);
114+
destroy_sqmatrix(S2);
115+
destroy_sqmatrix(S1);
116+
destroy_sqmatrix(W);
117+
destroy_sqmatrix(U);
118+
free(eigvals);
119+
return bott;
120+
}

mpb/mpb.scm.in

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
; this case, we assume that the procedure returns 1 argument,
2323
; as this is the most useful default for our purposes. Sigh.
2424

25-
(define (procedure-num-args p)
25+
(define (procedure-num-args p)
2626
(let ((arity (procedure-property p 'arity)))
2727
(if arity (car arity) 1)))
2828

@@ -76,9 +76,9 @@
7676
(lambda (object)
7777
(let ((sz (object-property-value object 'size))
7878
(i (object-property-value object 'matgrid-init)))
79-
(let ((g (apply make-uniform-array
79+
(let ((g (apply make-uniform-array
8080
(cons 0.333 (map inexact->exact (vector->list sz))))))
81-
(array-index-map! g (lambda (x y z)
81+
(array-index-map! g (lambda (x y z)
8282
(i (- (/ x (vector3-x sz)) 0.5)
8383
(- (/ y (vector3-y sz)) 0.5)
8484
(- (/ z (vector3-z sz)) 0.5))))
@@ -165,7 +165,7 @@
165165
(define TE EVEN-Z)
166166
(define TM ODD-Z)
167167
(define PREV-PARITY -1)
168-
(define-external-function set-parity false false
168+
(define-external-function set-parity false false
169169
no-return-value 'integer)
170170
(define set-polarization set-parity) ; backwards compatibility
171171

@@ -186,12 +186,12 @@
186186
(define-external-function get-epsilon false false no-return-value)
187187
(define-external-function get-mu false false no-return-value)
188188
(define-external-function fix-field-phase false false no-return-value)
189-
(define-external-function compute-field-energy false false
189+
(define-external-function compute-field-energy false false
190190
(make-list-type 'number))
191191
(define-external-function compute-field-divergence false false no-return-value)
192192

193193
(define-external-function get-epsilon-point false false 'number 'vector3)
194-
(define-external-function get-epsilon-inverse-tensor-point false false
194+
(define-external-function get-epsilon-inverse-tensor-point false false
195195
'cmatrix3x3 'vector3)
196196
(define-external-function get-energy-point false false 'number 'vector3)
197197
(define get-scalar-field-point get-energy-point)
@@ -210,7 +210,7 @@
210210
'number (make-list-type 'geometric-object))
211211

212212
(define-external-function output-field-to-file false false
213-
no-return-value 'integer 'string)
213+
no-return-value 'integer 'string)
214214

215215
(define-external-function mpi-is-master? false false 'boolean)
216216
(define-external-function using-mpi? false false 'boolean)
@@ -226,7 +226,7 @@
226226
no-return-value 'integer)
227227

228228
(define-external-function sqmatrix-size false false 'integer 'SCM)
229-
(define-external-function sqmatrix-ref false false 'cnumber
229+
(define-external-function sqmatrix-ref false false 'cnumber
230230
'SCM 'integer 'integer)
231231
(define-external-function sqmatrix-mult false false 'SCM
232232
'SCM 'SCM)
@@ -249,6 +249,8 @@
249249
'string)
250250
(define-external-function load-eigenvectors false false no-return-value
251251
'string)
252+
(define-external-function bott-indices false false (make-list-type 'number)
253+
'integer 'integer)
252254

253255
(define cur-field 'cur-field)
254256
(define-external-function cur-field? false false 'boolean 'SCM)
@@ -261,19 +263,19 @@
261263
(define-external-function field-set! false false no-return-value 'SCM 'SCM)
262264
(define (field-copy f) (let ((f' (field-make f))) (field-set! f' f) f'))
263265
(define-external-function field-load false false no-return-value 'SCM)
264-
(define-external-function field-mapL! false false no-return-value 'SCM
266+
(define-external-function field-mapL! false false no-return-value 'SCM
265267
'function (make-list-type 'SCM))
266268
(define (field-map! dest f . src) (apply field-mapL! (list dest f src)))
267269
(define-external-function integrate-fieldL false false 'cnumber
268270
'function (make-list-type 'SCM))
269271
(define (integrate-fields f . src) (apply integrate-fieldL (list f src)))
270-
(define-external-function rscalar-field-get-point false false 'number
272+
(define-external-function rscalar-field-get-point false false 'number
271273
'SCM 'vector3)
272-
(define-external-function cscalar-field-get-point false false 'cnumber
274+
(define-external-function cscalar-field-get-point false false 'cnumber
273275
'SCM 'vector3)
274-
(define-external-function cvector-field-get-point false false 'cvector3
276+
(define-external-function cvector-field-get-point false false 'cvector3
275277
'SCM 'vector3)
276-
(define-external-function cvector-field-get-point-bloch false false 'cvector3
278+
(define-external-function cvector-field-get-point-bloch false false 'cvector3
277279
'SCM 'vector3)
278280

279281
(define-external-function randomize-material-grid! false false
@@ -398,7 +400,7 @@
398400
(define (try+ k v)
399401
(if (< (n (vector3+ k v)) (n k)) (try+ (vector3+ k v) v) k))
400402
(define (try k v) (try+ (try+ k v) (vector3- (vector3 0) v)))
401-
(define trylist (list
403+
(define trylist (list
402404
#(1 0 0) #(0 1 0) #(0 0 1)
403405
#(0 1 1) #(1 0 1) #(1 1 0)
404406
#(0 1 -1) #(1 0 -1) #(1 -1 0)
@@ -483,7 +485,7 @@
483485
(cons (car freqs) k-point) (car br)))
484486
(newmax (if (> (car freqs) (cadr br))
485487
(cons (car freqs) k-point) (cdr br))))
486-
(ubrd br-rest (cdr freqs)
488+
(ubrd br-rest (cdr freqs)
487489
(cons (cons newmin newmax) br-start))))))
488490
(ubrd band-range-data freqs '()))
489491

@@ -552,7 +554,7 @@
552554
(let ((median-iters (* 0.5 (+ (list-ref sorted-iters
553555
(quotient num-runs 2))
554556
(list-ref sorted-iters
555-
(- (quotient
557+
(- (quotient
556558
(+ num-runs 1) 2)
557559
1))))))
558560
(print ", median = " median-iters))))
@@ -611,7 +613,7 @@
611613
(let ((k-split (list-split k-points k-split-num k-split-index)))
612614
(set-kpoint-index (car k-split))
613615
(if (zero? (car k-split))
614-
(begin
616+
(begin
615617
(output-epsilon) ; output epsilon immediately for 1st k block
616618
(if (using-mu?) (output-mu)))) ; and mu too, if we have it
617619
(if (> num-bands 0)
@@ -620,7 +622,7 @@
620622
(set! current-k k)
621623
(begin-time "elapsed time for k point: " (solve-kpoint k))
622624
(set! all-freqs (cons freqs all-freqs))
623-
(set! band-range-data
625+
(set! band-range-data
624626
(update-band-range-data band-range-data freqs k))
625627
(set! eigensolver-iters
626628
(append eigensolver-iters
@@ -841,7 +843,7 @@
841843
(define korig (if (pair? korig-and-kdir) (car korig-and-kdir) (vector3 0)))
842844
(define kdir (if (pair? korig-and-kdir) (cdr korig-and-kdir) korig-and-kdir))
843845
(let ((num-bands-save num-bands) (k-points-save k-points)
844-
(nb (- band-max band-min -1))
846+
(nb (- band-max band-min -1))
845847
(kdir1 (cartesian->reciprocal (unit-vector3 (reciprocal->cartesian kdir))))
846848
; k0s is an array caching the best k value found for each band:
847849
(k0s (if (list? kmag-guess) (list->vector kmag-guess)
@@ -850,7 +852,7 @@
850852
(bktab '()))
851853
(define (rootfun b) (lambda (k)
852854
(let ((tab-val (assoc (cons b k) bktab))) ; first, look in cached table
853-
(if tab-val
855+
(if tab-val
854856
(begin ; use cached result if available
855857
(print "find-k " b " at " k ": " (cadr tab-val) " (cached)\n")
856858
(cdr tab-val))
@@ -861,15 +863,15 @@
861863
(let ((v (compute-group-velocity-component kdir1)))
862864
; cache computed values:
863865
(map (lambda (b f v)
864-
(let ((tabval (assoc
866+
(let ((tabval (assoc
865867
(cons b (vector-ref k0s (- b band-min)))
866868
bktab)))
867869
(if (or (not tabval)
868870
(< (abs (- f omega)) (abs (cadr tabval))))
869871
(vector-set! k0s (- b band-min) k))) ; cache k0
870872
(set! bktab (cons (cons (cons b k) (cons (- f omega) v))
871873
bktab)))
872-
(arith-sequence band-min 1 (- b band-min -1))
874+
(arith-sequence band-min 1 (- b band-min -1))
873875
(ncdr (- band-min 1) freqs)
874876
(ncdr (- band-min 1) v))
875877
; finally return (frequency - omega . derivative):
@@ -889,7 +891,7 @@
889891
(run-parity p false
890892
(lambda (b')
891893
(if (= b' b)
892-
(map (lambda (f)
894+
(map (lambda (f)
893895
(apply-band-func-thunk f b true))
894896
band-funcs)))))
895897
(arith-sequence band-max -1 nb) (reverse ks)))
@@ -898,7 +900,7 @@
898900
(print parity "kvals:, " omega ", " band-min ", " band-max)
899901
(vector-map (lambda (k) (print ", " k)) korig)
900902
(vector-map (lambda (k) (print ", " k)) kdir1)
901-
(map (lambda (k) (print ", " k)) ks)
903+
(map (lambda (k) (print ", " k)) ks)
902904
(print "\n")
903905
ks)))
904906

@@ -912,7 +914,7 @@
912914
(let ((dots (dot-eigenvectors old-eigs first-band)))
913915
(let ((phases (map (lambda (d) (conj (make-polar 1 (angle d))))
914916
(sqmatrix-diag dots))))
915-
(map (lambda (i phase)
917+
(map (lambda (i phase)
916918
(scale-eigenvector i phase)
917919
(conj phase))
918920
(arith-sequence first-band 1 (length phases)) phases))))

0 commit comments

Comments
 (0)