2
C Get geometry info from rtdb and load into struct.
4
C Each geometry (fragment) has a "map" which is nbf_ao x nbf_ao, where nbf_ao
5
C is the number of basis functions in the "active" geometry (ie set
6
C geometry in input deck). You can then project the full nbf_ao x nbf_ao
7
C dipole integrals, etc onto each individual fragment via
10
C NOTE: params%geom_active_handle refers to the nwchem geom
11
C subsystem handle for "geometry", while params%active_geom refers
12
C to the params%geom(:) array of geom structs.
14
subroutine rt_tddft_init_geoms (params)
18
#include "mafdecls.fh"
30
#include "rt_tddft.fh"
33
C Note: geomP.fh supplies ngeom_rtdb, names_rtdb, max_geom_rtdb, ndipole
38
type(rt_params_t) params !geom params stored in here
42
character(*), parameter :: pname = "rt_tddft_init_geoms: "
43
character(*), parameter :: geom_tmp_name = "rt_tmp_geom"
44
double precision, parameter :: dist_thresh = 1d-8
52
character*16 geom_rtdb_name, geom_excite_name
53
character*16 active_geom_name
54
integer geom_tmp_ncent
56
integer ibf, icen, jcen
57
character*16 icen_tag, jcen_tag
58
double precision icen_loc(3), jcen_loc(3)
59
double precision icen_charge, jcen_charge
63
integer per_bf, per_cen
64
double precision geom_charge_nuc
68
C character*25 role_string
69
character*2 role_string
73
double precision ndip(3)
80
C Check that rt hardcoded max num geoms is less than = nwchem hardlimit
82
if (rt_max_geoms .lt. nw_max_geoms) !hardcoded in nwc_const.fh
83
$ call errquit (pname//"rt_max_geoms < nw_max_geoms",0,0)
87
C Get geom info from rtdb
89
if (.not.rtdb_get (params%rtdb, "geometry:ngeom",
90
$ mt_int, 1, ngeom_rtdb))
91
$ call errquit (pname//"failed to get ngeom from rtdb",0,0)
93
if (ngeom_rtdb .lt. 1)
94
$ call errquit (pname//"invalid ngeom_rtdb < 1",0,0)
96
c$$$ if (ngeom_rtdb .gt. nw_max_geoms)
97
c$$$ $ call errquit (pname//"invalid ngeom_rtdb > nw_max_geoms",0,0)
99
if (ngeom_rtdb .gt. max_geom_rtdb)
100
$ call errquit(pname//"invalid ngeom_rtdb > max_geom_rtdb",0,0)
102
if (.not. rtdb_cget (params%rtdb,'geometry:names',
103
$ ngeom_rtdb,names_rtdb))
104
$ call errquit (pname//"failed to read names from rtdb",0,0)
108
C Get internal index for active geometry from the rtdb name for the
112
if (.not. rtdb_cget (params%rtdb,'geometry',1,active_geom_name))
113
$ call errquit (pname//"failed to read active geom from rtdb",
116
found_active = .false.
118
do ig = 1, ngeom_rtdb
119
if ( trim(names_rtdb(ig)) .eq. trim(active_geom_name) ) then
120
if (found_active) then
121
call errquit (pname//"found multiple active geoms",0,0)
123
params%geom_active = ig
124
found_active = .true.
129
if (.not. found_active)
130
$ call errquit (pname//"failed to find active geom",0,0)
134
C Loop over all geoms found, create a temporary geometry object for
135
C each, calculate some properties, store in the rt struct, and
136
C delete the geom object (leaving geoms untouched).
138
do ig = 1, ngeom_rtdb
141
if (.not.geom_create (geom_tmp, geom_tmp_name))
142
$ call errquit (pname//"geom_create failed",0,0)
144
if (.not. geom_check_handle (geom_tmp,pname))
145
$ call errquit (pname//"not a valid geom",0,0)
147
if (.not. geom_rtdb_load (params%rtdb,
148
$ geom_tmp, names_rtdb(ig)))
149
$ call errquit (pname//"failed to load geom",0,0)
151
C (extract info from geom)
152
if (.not. geom_ncent (geom_tmp, geom_tmp_ncent))
153
$ call errquit (pname//"geom_ncent failed",0,0)
155
if (.not. geom_nuc_dipole (geom_tmp, ndip))
156
$ call errquit (pname//"geom_nucl_dipole failed",0,0)
158
geom_rtdb_name = names_rtdb(ig)
161
C Check that geometry fragment is not larger than active geometry.
163
if (geom_tmp_ncent .gt. params%natoms) call errquit (pname//
164
$ 'geom "'//trim(geom_rtdb_name)//
166
$ '" has more atoms than active geometry',
167
$ geom_tmp_ncent, GEOM_ERR)
170
C (alloc and compute mask GA)
171
if (.not.ga_create (mt_dbl, params%nbf_ao, params%nbf_ao,
172
$ trim(geom_rtdb_name)//"_mask", 0, 0,
173
$ params%geom(ig)%g_mask))
174
$ call errquit (pname//"alloc mask failed", 0, GA_ERR)
178
C Mask starts as all 1's, then we 0 any row/column which refers to a
179
C basis function not in this geom.
181
call ga_fill (params%geom(ig)%g_mask, 1d0)
185
C Loop over basis functions in overall/active basis set. For each
186
C basis function, find the "owning" atom, and then check if that
187
C atom is part of the "ig" geometry.
190
do ibf = 1, params%nbf_ao
191
if (.not. bas_bf2ce (params%ao_bas_han, ibf, icen))
192
$ call errquit (pname//"bas_bf2ce failed", 0, 0)
194
C (note this acts on full active geom, specified by the handle
196
if (.not. geom_cent_get (params%geom_active_handle, icen,
197
$ icen_tag, icen_loc, icen_charge))
198
$ call errquit (pname//"geom_cent_get active failed",0,0)
201
do jcen = 1, geom_tmp_ncent !increment over atoms in "ig" geom
203
if (.not. geom_cent_get (geom_tmp, jcen,
204
$ jcen_tag, jcen_loc, jcen_charge))
205
$ call errquit(pname//"geom_cent_get jcen failed",0,0)
207
C (icen_loc = location of ibf; jcen_loc = location of jcen'th atom/center in geom)
209
$ ( icen_loc(1) - jcen_loc(1) )**2 +
210
$ ( icen_loc(2) - jcen_loc(2) )**2 +
211
$ ( icen_loc(3) - jcen_loc(3) )**2 )
213
if (dist < dist_thresh) bf_in_geom = .true.
218
C (this basis func not in this geom, zero corresponding rows+columns)
219
if (.not. bf_in_geom) then
220
call ga_fill_patch (params%geom(ig)%g_mask,
221
$ 1, params%nbf_ao, ibf, ibf, 0d0)
222
call ga_fill_patch (params%geom(ig)%g_mask,
223
$ ibf, ibf, 1, params%nbf_ao, 0d0)
224
else ! this bf in this geom
225
nbf_geom = nbf_geom + 1
230
C (compute total nuclear charge on this geom)
231
geom_charge_nuc = 0d0
232
do jcen = 1, geom_tmp_ncent
234
if (.not. geom_cent_get (geom_tmp, jcen,
235
$ jcen_tag, jcen_loc, jcen_charge))
236
$ call errquit(pname//"geom_cent_get jcen failed",0,0)
238
geom_charge_nuc = geom_charge_nuc + jcen_charge
242
C (store misc params)
243
params%ngeoms = ngeom_rtdb
244
params%geom(ig)%name = trim (geom_rtdb_name)
245
params%geom(ig)%ncent = geom_tmp_ncent
246
params%geom(ig)%nbf = nbf_geom
247
params%geom(ig)%charge_nuc = geom_charge_nuc
248
params%geom(ig)%ndip%x = ndip(1)
249
params%geom(ig)%ndip%y = ndip(2)
250
params%geom(ig)%ndip%z = ndip(3)
251
params%geom(ig)%measure = .true. !XXX HARDCODED MEASURE ALL
254
C (remove tmp geom object, rtdb untouched)
255
if (.not. geom_destroy (geom_tmp))
256
$ call errquit (pname//"geom_destroy failed", 0, 0)
262
C Print geom info to stdout
268
write (luout, *) "Geometry "//
269
$ "Atoms Basis func. "//
270
$ "Nuc. charge Nuc. dip. mom."
272
write (luout, *) "-----------------"//
273
$ "------------------------------------"//
274
$ "------------------------------------"
278
do ig = 1, params%ngeoms
280
per_bf = 100 * params%geom(ig)%nbf / params%nbf_ao
281
per_cen = 100 * params%geom(ig)%ncent / params%natoms
285
C if ( trim(params%geom(ig)%name) .eq. trim(active_geom_name))
286
C $ role_string = trim(role_string) // "<= Active "
288
if (ig .eq. params%geom_active) then
297
C $ "(2x,a16,2x,i6,a,i3,a,5x,i6,a,i3,a,4x,1f8.2,4x,a)")
298
$ "(a,a16,i6,a,i3,a,i6,a,i3,a,2x,1f8.2,2x,3f10.2)")
300
$ params%geom(ig)%name,
301
$ params%geom(ig)%ncent, " (", per_cen , "% )",
302
$ params%geom(ig)%nbf, " (", per_bf, "% )",
303
$ params%geom(ig)%charge_nuc,
304
$ params%geom(ig)%ndip%x,
305
$ params%geom(ig)%ndip%y,
306
$ params%geom(ig)%ndip%z
309
call util_flush (luout)
314
C Now that we have determined the active geometry, update any
315
C excitations with -1 geom (ie if exciting orbitals directly) to
316
C excite the entire active geometry.
318
c$$$ do is = 1, params%nexcites
319
c$$$ if (params%excite(is)%geom_indx .lt. 1) then
320
c$$$ params%excite(is)%geom_indx = params%geom_active
327
C It appears that dipole integrals only work for Abelian symmetry,
328
C so we enforce that for each geom.
331
if (.not.sym_abelian_group(params%geom_active_handle))
332
$ call errquit (pname//
333
$ "active geom: non-Abelian symmetry; disable autosym",
337
C call util_flush (luout)
338
C if (.not. bas_print_all())
339
C $ call errquit (pname//"basis print failed")
340
C call util_flush (luout)