2
subroutine aor_r1_tensor (rtdb, basis, geom, omega, lstatic, ncomp
3
& , g_smat0, g_dipmag, g_dipel, g_quadel, g_vectors,
4
& froct,nbf, nmo, nocct, nvirt, lgiao, lquad, lvelocity,lifetime,
5
& lmagpert, g_vecE1, g_vecE1_im, alfare, alfaim, betare, betaim)
7
c $Id: aor_r1_tensor.F 21176 2011-10-10 06:35:49Z d3y133 $
9
c =================================================================
1
subroutine aor_r1_tensor(
2
& rtdb,basis,geom, ! in : handles
7
& g_dipmag, ! in : magn -dipole mom AO
8
& g_dipel, ! in : elect-dipole mom AO
9
& g_quadel, ! in : quadrupole AO
10
& g_vectors, ! in : MOs
11
& froct, ! in : set of occupations
12
& nbf, nmo, ! in : nr basis, nr MOs
13
& npol, ! in : nr. polarizations
14
& nocct, nvirt, ! in : nocc,nvirt
15
& lgiao, lquad, ! in : logical vars
16
& lvelocity, ! in : logical vars
17
& lifetime, ! in : logical vars
18
& lmagpert, ! in : logical vars
19
& g_vecE1,g_vecE1_im, ! in :
20
& alfare,alfaim, ! out: electric-electric response matrices
21
& betare,betaim) ! out: electric-magnetic response matrices
22
c $Id: aor_r1_tensor.F 23263 2012-12-09 18:38:17Z niri $
23
c =================================================================
11
24
c purpose: calculate linear response tensors
13
25
c We assume that perturbed MO coefficients have already
14
26
c been computed elsewhere.
16
27
c called from: aoresponse_driver_new
18
28
c output: alfare, alfaim - field-electric response matrices
19
29
c betare, betaim - field-magnetic response matrices
21
30
c =================================================================
32
c Written by J. Autschbach, SUNY Buffalo
33
c Extension to spin-unrestricted case
34
c by F. Aquino, Northwestern University
36
c --> Experimental (not published yet)
25
39
#include "errquit.fh"
26
40
#include "global.fh"
27
41
#include "mafdecls.fh"
37
50
c ---------------------
38
51
c subroutine arguments:
39
52
c ---------------------
41
53
integer rtdb ! [input] run-time database handle
42
54
integer basis ! [input] basis handle
43
55
integer geom ! [input] geometry handle
56
integer npol,nocct(npol), nvirt(npol)
57
double precision froct(nbf,npol)
45
58
c These are all input, too
46
integer g_smat0, g_vectors(2), g_dipel,
47
& g_quadel, g_dipmag, g_vecE1(2), g_vecE1_im(2)
59
integer g_smat0, g_vectors(npol), g_dipel,
61
& g_vecE1(2,2),g_vecE1_im(2,2)
48
62
integer nbf, nmo, ncomp
49
integer nocct(2), nvirt(2)
50
double precision froct(nbf,2)
51
63
double precision gamwidth, omega
52
64
logical lgiao, lquad, lvelocity, lifetime, lmagpert, lstatic
65
double precision sum_my ! Added by FA
55
67
double precision alfare(3,3), alfaim(3,3)
56
68
double precision betare(3,3), betaim(3,3)
63
c global array handles:
72
c global array handles:
69
74
c other local variables:
71
75
integer nmot(2), nocvir(2)
73
76
integer dims(3), chunk(3)
74
77
integer alo(3), ahi(3), blo(3), bhi(3), clo(3), chi(3)
76
78
character*(256) cstemp
78
79
character*(1) direction(3)
79
80
data direction/'x','y','z'/
82
integer ipm, nocc, nvir, nocv, imo, jmo, nmo1, iresp, idir
82
integer ipm, nocc, nvir, nocv, imo, jmo, nmo1,
83
84
logical debug, dbgmat,
85
86
double precision sum, scaling
86
87
double precision tenm8, one, two, zero, half
87
88
parameter (tenm8=1d-8, one=1d0, two=2d0, zero=0d0, half=one/two)
89
89
c external functions:
91
double precision ga_trace_diag
92
external ga_trace_diag
90
double precision ga_trace_diag,coeffre,coeffim
91
external ga_trace_diag
92
c ------- Added for unrestricted calc ----- START
94
external get_alfaorbeta_reim
95
c ------- Added for unrestricted calc ----- END
96
ndir=3 ! nr directions (x,y,z)
94
97
c ====================================================================
96
debug = .false. .and. ga_nodeid().eq.0 ! .true. during development
98
debug = .false. .and. ga_nodeid().eq.0 ! .true. during development
97
99
dbgmat = .false. .and. ga_nodeid().eq.0 ! debug large matrices
99
103
if (debug) write (luout,*) 'hello from aor_r1_beta'
101
104
c the main results are collected in alfare/in, betare/im.
102
105
c initialize with zeros:
108
alfare(idir,iresp) = 0.0d0
109
alfaim(idir,iresp) = 0.0d0
110
betare(idir,iresp) = 0.0d0
111
betaim(idir,iresp) = 0.0d0
112
enddo ! end-loop-iresp
113
enddo ! end-loop-idir
110
114
c set parameters that control the various computational options
111
115
c (later we will set most of this by input)
112
nspin = 1 ! assume closed shell
113
lzora = .false. ! not yet available here
116
lzora = .false. ! not yet available here
116
117
if (debug) write (luout,*) 'giao, velocity, magpert',
117
118
& lgiao, lvelocity, lmagpert
119
119
lantisym = (lvelocity .or. lmagpert) ! antisymm. perturbation
122
120
c -----------------------------------------
123
121
c determine number of occ * virt orbitals
124
122
c and nmot(1:2) and fix froct, if necessary
125
123
c -----------------------------------------
128
125
nocvir(ispin) = nocct(ispin) * nvirt(ispin)
129
126
nmot(ispin) = nmo
130
127
if (nmo .lt.nbf) then
185
176
c perturbing field has an antisymmetric AO matrix and
186
177
c we have to ADD the vectors instead.
187
178
c ---------------------------------------------------------
180
if (ga_nodeid().eq.0) then
181
write(*,100) ncomp,lantisym,lifetime
182
100 format('(comp,lantisym,lifetime)=(',i3,',',L1,',',L1,')')
184
if (ga_nodeid().eq.0)
185
& write(*,*) '--g_vecE1-BEF-IF ------ START'
186
call ga_print(g_vecE1(ispin,1))
187
if (ga_nodeid().eq.0)
188
& write(*,*) '--g_vecE1-BEF-IF ------ END'
190
if (ga_nodeid().eq.0)
191
& write(*,*) '--g_vecE1-im-BEF-IF ------ START'
192
call ga_print(g_vecE1_im(ispin,1))
193
if (ga_nodeid().eq.0)
194
& write(*,*) '--g_vecE1-im-BEF-IF ------ END'
195
endif ! end-if-lifetime
189
197
if (ncomp.gt.1) then
190
198
if (lantisym) then
191
call ga_add(1d0, g_vecE1(1), 1d0, g_vecE1(2),
199
call ga_add(1d0, g_vecE1(ispin,1),
200
& 1d0, g_vecE1(ispin,2),
193
202
if (lifetime) then
194
call ga_add(1d0, g_vecE1_im(1), 1d0, g_vecE1_im(2),
203
call ga_add(1d0, g_vecE1_im(ispin,1),
204
& 1d0, g_vecE1_im(ispin,2),
205
& g_vecE1_im(ispin,1))
196
206
end if ! lifetime
197
207
else ! lantisym ?
198
call ga_add(1d0, g_vecE1(1), -1d0, g_vecE1(2),
208
call ga_add(1d0, g_vecE1(ispin,1),
209
& -1d0, g_vecE1(ispin,2),
200
211
if (lifetime) then
201
call ga_add(1d0, g_vecE1_im(1), -1d0, g_vecE1_im(2),
212
call ga_add(1d0, g_vecE1_im(ispin,1),
213
& -1d0, g_vecE1_im(ispin,2),
214
& g_vecE1_im(ispin,1))
203
215
end if ! lifetime
204
216
end if ! lantisym
205
217
endif ! ncomp.gt.1
207
do idir = 1,3 ! direction of the perturbing field
215
alo(3) = iresp ! pick the correct B-field direction
227
call nga_matmul_patch('n','n',1d0,0d0,
229
& g_vectors(ispin),blo,bhi,
232
if (debug) write (luout,*)
233
& 'beta: H(B) C(0) intermediate complete'
251
call nga_matmul_patch('t','n',1d0,0d0,
257
c the factor of two is for the orbital occupations,
258
c assuming that ispin is never equal to two
260
sum = 2d0 * ga_trace_diag(g_work)
262
c the minus sign is consistent with the original aoresponse
263
c routine. We have to use - to get consistent results
264
c with the output from aor_r1_beta.F
265
betare(idir,iresp) = betare(idir,iresp) - sum
270
call nga_matmul_patch('t','n',1d0,0d0,
271
& g_vecE1_im,alo,ahi,
276
sum = 2d0 * ga_trace_diag(g_work)
277
betaim(idir,iresp) = betaim(idir,iresp) + sum
281
if (debug) write (luout,*)
282
& 'beta: C(E) H(B) C(0) complete'
219
if (ga_nodeid().eq.0)
220
& write(*,*) '--g_vecE1-AFT-IF ------ START'
221
call ga_print(g_vecE1(ispin,1))
222
if (ga_nodeid().eq.0)
223
& write(*,*) '--g_vecE1-AFT-IF ------ END'
225
if (ga_nodeid().eq.0)
226
& write(*,*) '--g_vecE1-im-AFT-IF ------ START'
227
call ga_print(g_vecE1_im(ispin,1))
228
if (ga_nodeid().eq.0)
229
& write(*,*) '--g_vecE1-im-AFT-IF ------ END'
230
endif ! end-if-lifetime
232
c if (ga_nodeid().eq.0)
233
c & write(*,*) '==== compute beta ====== START'
234
ndir=3 ! nr. directions (x,y,z)
235
do idir = 1,ndir ! direction of the perturbing field
238
call get_alfaorbeta_reim(
239
& betare(idir,iresp), ! in/out: alpha or beta real part
240
& betaim(idir,iresp), ! in/out: alpha or beta im part
241
& g_vecE1(ispin,1), ! in : 1st-order pert vec RE
242
& g_vecE1_im(ispin,1),! in : 1st-order pert vec IM
243
& g_dipmag, ! in : dipole electric or magnetic
244
& g_vectors(ispin), ! in : MO vectors
245
& idir, ! in : = 1,2,3=x,y,z directions
246
& iresp, ! in : = 1,2,3
247
& coeffre,coeffim,1, ! in : (coeffre,coeffim,caseAO)
248
& nbf, ! in : nr. basis functions
249
& nocc, ! in : nr. occupied alpha or beta
250
& lifetime, ! in : logical var for damping
251
& debug, ! in : logical var for debugging
252
& g_temp) ! in : scratch GA array
255
if (ga_nodeid().eq.0) then
256
write(*,1) ispin,idir,iresp,
257
& betare(idir,iresp),betaim(idir,iresp)
258
1 format('beta(',i3,',',i3,',',i3,
259
& ')=(',f15.8,',',f15.8,')')
262
enddo ! end-loop-iresp (responding field components)
263
enddo ! end-loop-idir (perturbing E-field components)
264
c if (ga_nodeid().eq.0)
265
c & write(*,*) '==== compute beta ====== END'
288
266
c --------------------------------------
289
267
c (B) calculate alfa from C(E) h(E) C(0)
290
268
c --------------------------------------
292
269
c ---------------------------------------------------------
293
270
c For alfa we need the sum of the +/- components no matter
295
272
c length or velocity gauge so we add twice the icomp=2 component
296
273
c back into g_vecE1(1)
297
274
c ---------------------------------------------------------
299
275
if (ncomp.gt.1) then
300
276
if (lantisym) then
303
call ga_add(1d0, g_vecE1(1), 2d0, g_vecE1(2),
279
call ga_add(1d0, g_vecE1(ispin,1),
280
& 2d0, g_vecE1(ispin,2),
305
282
if (lifetime) then
306
call ga_add(1d0, g_vecE1_im(1), 2d0, g_vecE1_im(2),
283
call ga_add(1d0, g_vecE1_im(ispin,1),
284
& 2d0, g_vecE1_im(ispin,2),
285
& g_vecE1_im(ispin,1))
308
286
end if ! lifetime
309
287
end if ! lantisym
310
288
endif ! ncomp.gt.1
319
alo(3) = iresp ! pick direction iresp for g_dipel
332
call nga_matmul_patch('n','n',1d0,0d0,
334
& g_vectors(ispin),blo,bhi,
337
if (debug) write (luout,*)
338
& 'alfa: h(E) C(0) intermediate complete'
358
call nga_matmul_patch('t','n',1d0,0d0,
364
c the factor of two is for the orbital occupations,
365
c assuming that ispin is never equal to two
367
sum = 2d0 * ga_trace_diag(g_work)
369
alfare(idir,iresp) = alfare(idir,iresp) - sum
375
call nga_matmul_patch('t','n',1d0,0d0,
376
& g_vecE1_im,alo,ahi,
381
sum = 2d0 * ga_trace_diag(g_work)
383
alfaim(idir,iresp) = alfaim(idir,iresp) + sum
386
if (debug) write (luout,*) 'alfa C(E) h(E) C(0) complete'
390
c -----------------------------------------
391
c end loop over responding field components
392
c -----------------------------------------
397
c -------------------------------------------
398
c end loop over perturbing E-field components
399
c -------------------------------------------
289
c if (ga_nodeid().eq.0)
290
c & write(*,*) '==== compute alfa ====== START'
291
ndir=3 ! nr. directions (x,y,z)
292
do idir = 1,ndir ! direction of the perturbing field
295
call get_alfaorbeta_reim(
296
& alfare(idir,iresp), ! out: alpha or beta real part
297
& alfaim(idir,iresp), ! out: alpha or beta im part
298
& g_vecE1(ispin,1), ! in : 1st-order pert vec RE
299
& g_vecE1_im(ispin,1),! in : 1st-order pert vec IM
300
& g_dipel, ! in : dipole electric or magnetic
301
& g_vectors(ispin), ! in : MO vectors
302
& idir, ! in : = 1,2,3=x,y,z directions
303
& iresp, ! in : = 1,2,3
304
& coeffre,coeffim,1, ! in : (coeffre,coeffim,caseAO)
305
& nbf, ! in : nr. basis functions
306
& nocc, ! in : nr. occupied alpha or beta
307
& lifetime, ! in : logical var for damping
308
& debug, ! in : logical var for debugging
309
& g_temp) ! in : scratch GA array
312
if (ga_nodeid().eq.0) then
313
write(*,2) ispin,idir,iresp,
314
& alfare(idir,iresp),alfaim(idir,iresp)
315
2 format('alfa(',i3,',',i3,',',i3,
316
& ')=(',f15.8,',',f15.8,')')
319
enddo ! end-loop-iresp (responding field components)
320
enddo ! end-loop-idir (perturbing E-field components)
321
c if (ga_nodeid().eq.0)
322
c & write(*,*) '==== compute alfa ====== END'
323
c ============ visualize-1 (alfa,beta) ========== START
324
c if (ga_nodeid().eq.0) then
327
c write(*,10) ispin,idir,iresp,
328
c & alfare(idir,iresp),alfaim(idir,iresp),
329
c & betare(idir,iresp),betaim(idir,iresp)
330
c 10 format('FA-tensor:(ispin,idir,iresp)=(',
331
c & i3,',',i3',',i3,')',
332
c & ' alfa(re,im)=(',f15.8,',',f15.8,')',
333
c & ' beta(re,im)=(',f15.8,',',f15.8,')')
334
c enddo ! end-loop-iresp
335
c enddo ! end-loop-idir
337
c ============ visualize-1 (alfa,beta) ========== END
405
338
if (.not.ga_destroy(g_temp))
407
340
& ('aor_beta: ga_destroy failed g_temp',
342
enddo ! end-loop-ispin
411
347
if (.not.ga_destroy(g_work))
413
349
& errquit('aoresponse: ga_destroy failed g_work',
417
enddo ! ispin = 1,2 from way above
419
c ---------------------------------------------------------------
420
c end loop over spin components (which we don't use right now
421
c since nspin is forced to be 1 at the beginning of this routine)
422
c ---------------------------------------------------------------
425
351
c it seems that if we use GIAOs everything is off by a factor of
426
352
c two, so we need to scale betare, betaim. If we have static
427
353
c response then there is a factor of two missing everywhere
428
354
c because we don't add C(+) and C(-) for the electric field.
356
c if (ga_nodeid().eq.0)
357
c & write(*,*) 'FA-lgiao=',lgiao
361
do idir = 1,ndir ! direction of the perturbing field (x,y,z)
434
363
betare(idir, iresp) = betare(idir, iresp) * scaling
435
364
betaim(idir, iresp) = betaim(idir, iresp) * scaling
368
c ============ visualize-1 (alfa,beta) ========== START
369
c if (ga_nodeid().eq.0) then
372
c write(*,11) ispin,idir,iresp,
373
c & alfare(idir,iresp),alfaim(idir,iresp),
374
c & betare(idir,iresp),betaim(idir,iresp)
375
c 11 format('FA-AFT-lgiao:(ispin,idir,iresp)=(',
376
c & i3,',',i3',',i3,')',
377
c & ' alfa(re,im)=(',f15.8,',',f15.8,')',
378
c & ' beta(re,im)=(',f15.8,',',f15.8,')')
379
c enddo ! end-loop-iresp
380
c enddo ! end-loop-idir
382
c ============ visualize-1 (alfa,beta) ========== END
383
c if (ga_nodeid().eq.0)
384
c & write(*,*) 'FA-lstatic=',lstatic
440
386
if (lstatic) then
388
do idir = 1,ndir ! direction of the perturbing field (x,y,z)
444
390
alfare(idir, iresp) = alfare(idir, iresp) * scaling
445
391
alfaim(idir, iresp) = alfaim(idir, iresp) * scaling