1
C====================================================================
3
C Determine name of initial movecs file. If one was not specified
4
C in the input deck, it falls back to SCF output.
6
subroutine rt_tddft_movecs_fname (params, rt_movecs_fname)
11
#include "mafdecls.fh"
19
#include "rt_tddft.fh"
23
type(rt_params_t), intent(in) :: params
27
character(len=*), intent(out) :: rt_movecs_fname
31
character(*),parameter :: pname="rt_tddft_movecs_fname: "
36
C If we found a "vectors" directive while parsing the input we use
37
C that, otherwise fall back on the output vectors "movecs_in" from
38
C the DFT (via common block in cdft.fh header).
40
if (.not. rtdb_cget (params%rtdb, "rt_tddft:init_movecs",
41
$ 1, rt_movecs_fname)) then
43
if (movecs_in .eq. "atomic")
44
$ call errquit ('Cannot use atomic guess for rt_tddft'//
45
$ ' initial state--first run an SCF to generate'//
46
$ ' valid movecs', 0, 0)
48
call rt_tddft_print_warning ("Starting movecs not specified"//
49
$ "--trying SCF output: "//char(10)//" "//
52
rt_movecs_fname = movecs_in
55
call util_file_name_resolve (rt_movecs_fname, .false.)
61
C====================================================================
63
C Print imported movecs information to stdout.
65
subroutine rt_tddft_movecs_print_header (params, fname,
66
$ title, basis_name, scftype, nbf, mo_nsets, nmo)
74
#include "rt_tddft.fh"
78
type(rt_params_t), intent(in) :: params
79
character(len=*), intent(in) :: fname, title, basis_name, scftype
80
integer, intent(in) :: nbf, mo_nsets, nmo(mo_nsets)
84
character(*),parameter :: pname="rt_tddft_movecs_print_header: "
94
write (luout, "(5x,a,a)") "File name : ",
96
write (luout, "(5x,a,a)") "Job title : ",
98
write (luout, "(5x,a,a)") "Basis set name : ",
100
write (luout, "(5x,a,a)") "SCF type : ",
102
write (luout, "(5x,a,i0)") "Atomic orbitals : ",
105
if (mo_nsets .eq. 1) then
106
write (luout, "(5x,a,i0)") "Molecular orbitals : ",
108
elseif (mo_nsets .eq. 2) then
109
write (luout, "(5x,a,i0,a,i0)") "Molecular orbitals : ",
110
$ nmo(1), ", ", nmo(2)
113
call util_flush (luout)
120
C====================================================================
122
C Print imported movecs eigenvalues and occupations to stdout.
124
subroutine rt_tddft_movecs_print_evals (params, occ, evals)
128
#include "errquit.fh"
132
#include "rt_tddft.fh"
136
type(rt_params_t), intent(in) :: params
137
double precision, intent(in) :: occ(*), evals(*)
141
character(*),parameter :: pname="rt_tddft_movecs_print_evals: "
152
C Print eigenvalue list
158
call util_print_centered (luout, " Vector "//
159
$ "Occupation Eigenvalue [au]", 0, .true.)
161
do iv = 1, params%ns_ao
162
if (iv .le. params%ns_mo) then ! vals not removed by canorg
163
write (luout, "(2x,i8,7x,1f5.2,7x,es15.8)")
164
$ iv, occ(iv), evals(iv)
166
write (luout, "(2x,i8,4x,a)")
167
$ iv, " (linearly dependent; removed) "
172
call util_flush (luout)
179
C====================================================================
181
C Convert real-valued ns_ao x ns_ao into complex ns_ao x ns_ao dens
182
C mat in AO basis (used for importing from the ground state code).
184
C P_uv = \sum_i n_i C_ui C_vi^*
186
C where n_i is the ith orbital occupation, and C is the movecs
187
C coefficient matrix.
189
C We first build mask of orbital occupations (n3 = occupation of 3rd
197
C We apply this mask to the movecs matrix (g_movecs_pad) then take
198
C matrix multiplication with the unmasked transpose (note: full
199
C matrices are multiplied, since the mask has zeroed out the
200
C non-occupied orbitals anyways).
202
subroutine rt_tddft_movecs_zdens(params, nsets, g_zdens_ao)
206
#include "errquit.fh"
209
#include "mafdecls.fh"
211
#include "rt_tddft.fh"
215
type(rt_params_t), intent(in) :: params
216
C integer, intent(in) :: ispin !target movecs set : 1 for CS/SO; 1 or 2 for OS
217
integer, intent(in) :: nsets !total num movecs sets: 1 for CS/SO; 2 for OS
221
integer, intent(in) :: g_zdens_ao(nsets)
222
C integer, intent(in) :: g_movecs_ao_gs(nsets)
226
character(*),parameter :: pname="rt_tddft_movecs_zdens: "
230
logical, external :: movecs_read_header, movecs_read
234
character*256 rt_movecs_fname
235
integer g_movecs_pad !double, ns_ao x ns_ao w/ 0's for canorg removed lindeps
236
integer dtype, dim1, dim2
240
C (movecs header stuff)
241
character*256 mo_title, mo_basis_name, mo_scftype
242
integer mo_nbf, mo_nsets, mo_ns_mo(nsets)
244
integer locc, iocc, levals, ievals !MO occupations and eigenvalues (from movecs file)
257
C if ((ispin .lt. 1).or.(ispin .gt. nsets))
258
C $ call errquit (pname//"invalid ispin supplied", ispin, 0)
260
if ((nsets .ne. 1).and.(nsets .ne. 2))
261
$ call errquit (pname//"invalid nsets supplied", nsets, 0)
264
$ call errquit (pname//"nsets > 1 needs to be implemented",0,0)
267
call ga_check_handle (g_zdens_ao(is),
268
$ "third argument of "//pname//"not a valid GA")
269
call ga_inquire (g_zdens_ao(is), dtype, dim1, dim2)
271
if (dtype .ne. mt_dcpl) call errquit (pname//
272
$ "expecting complex-valued GA as third argument", 0, 0)
274
$ call errquit (pname//"dim1 must equal dim2", 0, 0)
275
if (dim1 .ne. params%ns_ao)
276
$ call errquit (pname//
277
$ "bad size P--expecting ns_ao x ns_ao", 0, 0)
285
if (.not. ga_create(mt_dbl,params%ns_ao,params%ns_ao,
286
$ "movecs", 0, 0, g_movecs_pad))
287
$ call errquit ("couldnt create movecs_pad", 0, GA_ERR)
290
C Just an alias to the ouput GA; note padded with 0's if have
293
CXXX [KAL]: ONLY FOR nsets = 1
294
C g_movecs_pad = g_movecs_ao_gs(1)
297
if (.not. ga_duplicate(g_movecs_pad, g_densre_ao, "real P"))
298
$ call errquit ("couldnt duplicate movecs", 0, GA_ERR)
300
if (.not. ga_duplicate(g_movecs_pad, g_tmp, "tmp"))
301
$ call errquit ("couldnt duplicate movecs", 0, GA_ERR)
305
C Read in header to get file name, check, then read in movecs. Note
306
C that the g_movecs_pad is ns_ao x ns_ao, with the last few columns
307
C possibly 0 (if lindep), which is how the SCF code does it, which
308
C is unlike my way, which has ns_mo x ns_mo.
311
call ga_zero (g_movecs_pad)
313
call rt_tddft_movecs_fname (params, rt_movecs_fname)
315
if (.not. movecs_read_header (rt_movecs_fname, mo_title,
316
$ mo_basis_name, mo_scftype, mo_nbf, mo_nsets,
318
$ call errquit (pname//"Failed to read movecs header", 0, 0)
322
C Check that movecs are legit.
324
if (mo_scftype .ne. "dft")
325
$ call errquit (pname//
326
$ 'Initial movecs should have scftype "dft"', 0, 0)
328
if (mo_nbf .ne. params%ns_ao)
329
$ call errquit (pname//
330
$ 'Initial movecs wrong size: mo_nbf /= ns_ao', mo_nbf, 0)
333
if (mo_ns_mo(is) .ne. params%ns_mo)
334
$ call errquit (pname//
335
$ 'Initial movecs wrong size: mo_ns_mo /= ns_mo',
339
if (mo_nsets .ne. nsets)
340
$ call errquit (pname//"Wrong number of initial movecs,",
344
call rt_tddft_movecs_print_header (params, rt_movecs_fname,
345
$ mo_title, mo_basis_name, mo_scftype, mo_nbf,
346
$ mo_nsets, mo_ns_mo)
351
C Allocate buffers and movecs (ns_ao x ns_ao padded with zero *not* ns_mo x ns_mo).
353
if (.not.ma_push_get(mt_dbl, params%ns_ao, 'occ', locc, iocc))
354
& call errquit(pname//'cannot allocate occ',0, MA_ERR)
356
if (.not.ma_push_get(mt_dbl, params%ns_ao, 'evals',
358
& call errquit(pname//'cannot allocate evals',0, MA_ERR)
362
C Read in movecs (note ispin).
364
if (.not. movecs_read (rt_movecs_fname, 1, dbl_mb(iocc), !note 1!!!
365
$ dbl_mb(ievals), g_movecs_pad))
366
$ call errquit (pname//"Failed to read movecs data", 0, 0)
368
call rt_tddft_movecs_print_evals (params,
369
$ dbl_mb(iocc), dbl_mb(ievals))
373
C Mask the movecs and multiply into the unmasked transposed movecs
374
C to make the real-valued dens mat in AO basis, then cast to
379
do iorb = 1, params%ns_ao
380
occ = dbl_mb(iocc + iorb - 1)
381
call ga_fill_patch (g_tmp, 1, params%ns_ao,
385
call ga_sync () !XXX needed?
387
call ga_elem_multiply (g_tmp, g_movecs_pad, g_tmp) ! g_tmp now holds masked movecs
388
call ga_zero (g_densre_ao)
389
call ga_dgemm ("N", "T", params%ns_ao, params%ns_ao, params%ns_ao,
390
$ 1d0, g_tmp, g_movecs_pad, 0d0, g_densre_ao)
392
call convert_d2z(1d0, g_densre_ao, 0d0, g_densre_ao, g_zdens_ao)
394
C call ga_print (g_movecs_pad)
399
if (.not. ga_destroy (g_movecs_pad))
400
$ call errquit (pname//"failed to destroy movecs",0,0)
402
if (.not. ga_destroy (g_densre_ao))
403
$ call errquit (pname//"failed to destroy densao_tmp",0,0)
405
if (.not. ma_pop_stack (levals))
406
$ call errquit (pname//"Failed to pop evals", 0, ma_err)
408
if (.not. ma_pop_stack (locc))
409
$ call errquit (pname//"Failed to pop occ", 0, ma_err)
411
if (.not. ga_destroy (g_tmp))
412
$ call errquit ("couldnt destroy tmp", 0, GA_ERR)
420
CXXX [KAL]: REMOVE ONCE UNIFIED WITH CLOSEDSHELL ROUTINE
421
C====================================================================
423
C rt_tddft_os_movecs_zdens.F
425
C Read in initial state movecs from file and convert to OPEN SHELL
426
C complex dens matrix in AO basis. Although the output dens mat is
427
C complex data type, it is pure real (as the movecs are from the SCF
428
C and thus pure real).
431
subroutine rt_tddft_os_movecs_zdens (params, g_zdens_ao)
434
#include "errquit.fh"
435
#include "mafdecls.fh"
443
#include "rt_tddft.fh"
444
#include "matutils.fh"
448
type (rt_params_t), intent(in) :: params
452
integer, intent(in) :: g_zdens_ao(2) !dble complex, ns_ao x ns_ao; alpha, beta
456
character(*),parameter :: pname="rt_tddft_os_movecs_zdens: "
460
logical, external :: movecs_read_header, movecs_read
464
character*256 rt_movecs_fname
465
integer dtype, dim1, dim2
471
C (movecs header stuff)
472
character*256 mo_title, mo_basis_name, mo_scftype
473
integer mo_nbf, mo_nsets, mo_ns_mo(2) !2 for alpha, beta spins
475
integer locc, iocc, levals, ievals !MO occupations and eigenvalues (from movecs file)
479
call rt_tddft_os_confirm (params)
486
call util_print_centered (luout,
487
$ "Initial state: Imported open shell MO eigenvectors",
495
call ga_check_handle (g_zdens_ao(1),
496
$ "third argument of "//pname//"not a valid GA")
497
call ga_inquire (g_zdens_ao(1), dtype, dim1, dim2)
498
if (dtype .ne. mt_dcpl) call errquit (pname//
499
$ "expecting complex-valued GA as third argument", 0, 0)
501
$ call errquit (pname//"dim1 must equal dim2", 0, 0)
502
if (dim1 .ne. params%ns_ao)
503
$ call errquit (pname//"bad size P--expecting ns_ao x ns_ao",
506
call ga_check_handle (g_zdens_ao(2),
507
$ "third argument of "//pname//"not a valid GA")
508
call ga_inquire (g_zdens_ao(2), dtype, dim1, dim2)
509
if (dtype .ne. mt_dcpl) call errquit (pname//
510
$ "expecting complex-valued GA as third argument", 0, 0)
512
$ call errquit (pname//"dim1 must equal dim2", 0, 0)
513
if (dim1 .ne. params%ns_ao)
514
$ call errquit (pname//"bad size P--expecting ns_ao x ns_ao",
521
if (.not. ga_create(mt_dbl,params%ns_ao,params%ns_ao,
522
$ "movecs", 0, 0, g_movecs_pad))
523
$ call errquit ("couldnt create movecs_pad", 0, GA_ERR)
525
if (.not. ga_duplicate(g_movecs_pad, g_densao_tmp, "real P"))
526
$ call errquit ("couldnt duplicate movecs", 0, GA_ERR)
531
C Read in header to get file name, check, then read in movecs. Note
532
C that the g_movecs_pad_pad is ns_ao x ns_ao, with the last few columns
533
C possibly 0 (if lindep), which is how the SCF code does it, which
534
C is unlike my way, which has ns_mo x ns_mo. The 2 is for open shell.
536
call rt_tddft_movecs_fname (params, rt_movecs_fname)
539
if (.not. movecs_read_header (rt_movecs_fname, mo_title,
540
$ mo_basis_name, mo_scftype, mo_nbf, mo_nsets,
542
$ call errquit (pname//"Failed to read movecs header", 0, 0)
544
C call rt_tddft_movecs_print_header (params, rt_movecs_fname,
545
C $ mo_title, mo_basis_name, mo_scftype, mo_nbf)
549
C Check that movecs are legit.
551
if (mo_scftype .ne. "dft")
552
$ call errquit (pname//
553
$ 'Initial movecs should have scftype "dft"', 0, 0)
555
if (mo_nbf .ne. params%ns_ao)
556
$ call errquit (pname//
557
$ 'Initial movecs wrong size: mo_nbf /= ns_ao', 0, 0)
559
if (mo_ns_mo(1) .ne. params%ns_mo)
560
$ call errquit (pname//
561
$ 'Initial movecs wrong size: mo_ns_mo(1) /= ns_mo', 0, 0)
563
if (mo_ns_mo(2) .ne. params%ns_mo)
564
$ call errquit (pname//
565
$ 'Initial movecs wrong size: mo_ns_mo(2) /= ns_mo', 0, 0)
567
C call rt_tddft_print_warning ("Didnt check mo_ns_mo(2) == ns_mo")
570
$ call errquit (pname//"Wrong number of initial movecs,"//
571
$ " mo_nsets should be 2 for open shell", 0, 0)
575
C Allocate tmp buffers for occupations and evals (ns_ao x ns_ao
576
C padded with zero *not* ns_mo x ns_mo).
578
if (.not.ma_push_get(mt_dbl, params%ns_ao, 'occ', locc, iocc))
579
& call errquit(pname//'cannot allocate occ 1',0, MA_ERR)
581
if (.not.ma_push_get(mt_dbl, params%ns_ao, 'evals',
583
& call errquit(pname//'cannot allocate evals',0, MA_ERR)
587
C Read in movecs. Note we loop over the two spins since closed
588
C shell, and we recycle all the MA and GA space, and finally store
589
C in g_zdens_ao which has two components (alpha, beta spins).
591
call ga_zero (g_zdens_ao(1))
592
call ga_zero (g_zdens_ao(2))
595
call ga_zero (g_movecs_pad)
597
if (.not. movecs_read (rt_movecs_fname, 1, dbl_mb(iocc),
598
$ dbl_mb(ievals), g_movecs_pad))
599
$ call errquit (pname//"Failed to read movecs data", 0, 0)
601
call rt_tddft_movecs_print_evals (params,
602
$ dbl_mb(iocc), dbl_mb(ievals))
604
call ga_zero (g_densao_tmp)
605
call ga_dgemm ("N", "T", params%ns_ao, params%ns_ao,
606
$ params%nalpha, 1d0, g_movecs_pad, g_movecs_pad,
609
call convert_d2z(1d0, g_densao_tmp, 0d0, g_densao_tmp,
614
call ga_zero (g_movecs_pad)
616
if (.not. movecs_read (rt_movecs_fname, 2, dbl_mb(iocc),
617
$ dbl_mb(ievals), g_movecs_pad))
618
$ call errquit (pname//"Failed to read movecs data", 0, 0)
620
call rt_tddft_movecs_print_evals (params,
621
$ dbl_mb(iocc), dbl_mb(ievals))
624
call ga_zero (g_densao_tmp)
625
call ga_dgemm ("N", "T", params%ns_ao, params%ns_ao,
626
$ params%nbeta, 1d0, g_movecs_pad, g_movecs_pad,
629
call convert_d2z(1d0, g_densao_tmp, 0d0, g_densao_tmp,
636
if (.not. ga_destroy (g_movecs_pad))
637
$ call errquit (pname//"failed to destroy movecs",0,0)
639
if (.not. ga_destroy (g_densao_tmp))
640
$ call errquit (pname//"failed to destroy densao_tmp",0,0)
642
if (.not. ma_pop_stack (levals))
643
$ call errquit (pname//"Failed to pop evals", 0, ma_err)
645
if (.not. ma_pop_stack (locc))
646
$ call errquit (pname//"Failed to pop occ", 0, ma_err)