CONGEN 5.0
Configuration generation for SCATCI
Loading...
Searching...
No Matches
congen_driver.f90
Go to the documentation of this file.
1! Copyright 2019
2!
3! For a comprehensive list of the developers that contributed to these codes
4! see the UK-AMOR website.
5!
6! This file is part of UKRmol-in (UKRmol+ suite).
7!
8! UKRmol-in is free software: you can redistribute it and/or modify
9! it under the terms of the GNU General Public License as published by
10! the Free Software Foundation, either version 3 of the License, or
11! (at your option) any later version.
12!
13! UKRmol-in is distributed in the hope that it will be useful,
14! but WITHOUT ANY WARRANTY; without even the implied warranty of
15! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16! GNU General Public License for more details.
17!
18! You should have received a copy of the GNU General Public License
19! along with UKRmol-in (in source/COPYING). Alternatively, you can also visit
20! <https://www.gnu.org/licenses/>.
21!> \brief Main CONGEN subroutines.
22!>
24
25 implicit none
26
27 ! module entry point
28 public csfgen
29
30 ! internal support routines
31 private csfout
32 private getcon
33 private getcup
34 private getref
35 private icgcf
36 private stwrit
37 private subdel
38 private wfnin
39 private wfnin0
40 private wrnmlt
41 private wvwrit
42
43contains
44
45 !> \brief Central CONGEN subroutine
46 !>
47 !> Main driver routine: this is a transportable (Cray/IBM) version of CONGEN with the D2h symmetry for MOLECULE re-instated.
48 !>
49 subroutine csfgen
50
51 use precisn, only : wp
52 use consts, only : zero => xzero, two => xtwo
53 use congen_data, only : mxtarg, nx => nu, ny, nz, jx, jy, jz, ky, kz, ntcon, test, nrcon, nobt, &
54 nsym, nobi, ift, next, navail => nx, icdi, iexcon, indi, inodi, iqnstr, &
56 ncall, ncsf, confpf, occst => occshl, pqnst, mshlst => mshl, gushst => gushl, &
57 cupst => cup, sshlst, shlmx1, nqntot => qntot, nqntar => qntar, ngutot => gutot, &
58 nnndel => nndel, nnlecg, nisz, nsmtyp => symtyp, nftw, nftr, exdet, exref
59
60 use iso_c_binding, only : c_loc, c_f_pointer
61 use congen_distribution, only : distrb
63 use congen_projection, only : projec
64
65 real(wp), allocatable, dimension(:), target :: bmx
66 real(wp), pointer :: bmx_ptr
67 integer, dimension(:), pointer :: int_ptr, ndel_ptr, ndel1_ptr, ndel2_ptr, irfcon_ptr
68 integer :: byproj, cdimn, conmes, d, defltc, guold, gutot, i, idiag, iposit, is, iscat, iso, isz, itu, j, lc, lcdi, &
69 lcdo, lcdt, ln, lndi, lndo, lndt, lpp, lsquare, ltri, maxtgsym, megu, mflag, mold, mt, n, nadel, nbmx, &
70 nconmx, ncsf0, ncupp, ndimn, ndpmax, ndpp, ndprod, negmax, negr, nelecg, nelect, nelp, nelr, nemax, nerfg, &
71 nerfs, nextk, nfto, nndel, nobep, nodimn, npcupf, npmult, nrefo, nrefog, nrefop, nrerun, nrfgmx, nrfgoe, &
72 nrfoe, nrfomx, ns, nshgmx, nshlp0, nshlpt, nspf, nspi, nsymmx, nsymp, ntconp, err, gflag, noex
73 integer, dimension(3,jx) :: cup, pqn
74 logical :: ene, ener, enob, enrefo, epsno, eqnt, erefd, error, errorg, espace, esymt, qmoln
75 logical, dimension(11) :: erfg
76 logical, dimension(9) :: erfs
77 character(len=80) :: gname, sname
78 character(len=256) :: errmsg
79 integer, dimension(mxtarg) :: gucont, mcont, mdegen, mrkorb, nctgt, notgt
80 integer, dimension(jx) :: gushl, ksss, loopf, mshl, occshl, shlmx, sshl
81 integer, dimension(jy) :: kdssv, nelecp, nshlp, nslsv
82 integer, dimension(nx) :: nob, nob0, nob0l, nobl
83 integer, dimension(nx) :: nobe, nobp, nobv
84 integer, dimension(6) :: npflg
85 integer, dimension(jz) :: nshcon
86 integer :: ntgsmx, ntgsym, nwfngp, pqn2, symtyp
87 real(kind=wp) :: pin, r, s, sz, thres
88 integer, dimension(3) :: qntar, qntar1, qntot
89 integer, dimension(nz) :: refdet ! Reference determinant (assignment of electrons to spin-orbitals).
90 integer, dimension(kz) :: refdtg ! Wfngrp reference determinant (assignment of electrons to spin-orbitals).
91 integer, dimension(ny) :: refgu ! Gerade/ungerade quantum numbers for the reference determinant (per quintet).
92 integer, dimension(ky) :: refgug ! Gerade/ungerade quantum numbers for the wfngrp reference determinant (per quintet).
93 integer, dimension(5,ny) :: reforb ! Reference determinant setup (quintets from &state).
94 integer, dimension(5,ky) :: reforg ! Movable electrons setup (quintets from &wfngrp).
95 integer, dimension(3,jx,jz) :: tcon ! Constraints. ???
96
97 equivalence(reforg(1,1), reforb(1,1))
98 equivalence(refgu(1), refgug(1))
99
100 ! named error flags
101 equivalence(erfs(1), esymt)
102 equivalence(erfs(2), enob)
103 equivalence(erfs(3), epsno)
104 equivalence(erfs(4), ene)
105 equivalence(erfs(5), enrefo)
106 equivalence(erfs(6), ener)
107 equivalence(erfs(7), erefd)
108 equivalence(erfs(8), eqnt)
109 equivalence(erfs(9), espace)
110
111 ! input namelists
112 namelist /state / megul, nrerun, lcdt, lndt, nfto, ltri, idiag, thres, megu, npflg, nodimx, ndimx, cdimx, &
113 byproj, lcdo, lndo, nftw, iscat, ntgsym, sname, lpp, confpf, symtyp, qntot, gutot, isz, &
114 npmult, nob, reforb, refgu, nrefo, nelect, nndel, qmoln, gflag, &
115 iposit, nob0, nbmx, nobe, nobp, nobv, noex ! this last row: positron control data
116
117 namelist /wfngrp/ nelecg, ndprod, nelecp, nshlp, gname, reforg, refgug, nrefog, mshl, gushl, pqn, cup, defltc, &
118 npcupf, test, nrcon, nshcon, tcon, ntcon, qntar, lsquare
119
120 !
121 ! Hardcoded limits
122 !
123
124 conmes = 400 ! Quantenmol-specific output file unit with time estimate.
125 nrfoe = 30 ! initial value for "nrefop" (see below).
126 nrfgoe = 10 ! ... ?? ... Used in GETCON.
127 nerfs = 9 ! Number of error condition flags in erfs.
128 nerfg = 11 ! Number of error condition flags in erfg.
129 nsymmx = nx ! Maximal number of symmetries.
130 nrfomx = ny ! Maximal number of reference orbital quintets.
131 nemax = nz ! Maximal number of electrons.
132 nrfgmx = ky ! Maximal number of quintets used in single wave function group.
133 negmax = kz ! Maximal number of movable electrons.
134 nshgmx = jx ! Maximal number of pqn triplets per wave function group.
135 ndpmax = jy ! Maximal number of sets of orbitals per wave function group.
136 nconmx = jz ! Maximal number of constraints.
137
138 nobl(:) = 0
139 nob0l(:) = 0
140 mdegen(:) = 0
141
142 !
143 ! Default input data
144 !
145
146 qmoln = .false. ! Indicates CONGEN running from Quantenmol.
147 gflag = 1 ! Flag to disable CSF grouping based on symmetry 0=OFF 1=ON (default)
148 iscat = 0 ! Output format: 0 = SPEEDY, 1 = SCATCI, 2 = SCATCI + information for phase correcting target CI wavefunctions.
149 ntgsym = mxtarg ! Number of target state symmetries
150 nndel = 0 ! Whether to read CSFs from input stream.
151 megul = 13 ! Congen output file with generated configurations.
152 nrerun = 0 ! Restart flag for SPEEDY (not used in SCATCI).
153 lcdt = 500 ! Not used.
154 lndt = 5000 ! Not used.
155 lcdo = 500 ! Limit on number of determinants.
156 lndo = 5000 ! Limit on number of integers used in determinant description.
157 nfto = 15 ! Fortran data set number for output unit of SPEEDY.
158 ltri = 300 ! Not used.
159 idiag = -1 ! Matrix element evaluation flag passed to SPEEDY or SCATCI.
160 nbmx = 2000000 ! Workspace: Number of real numbers.
161 byproj = 1 ! Project wave functions in 1 = CONGEN, 0 = SPEEDY, -1 = nowhere (should be avoided).
162 megu = 14 ! Output data set with the namelist input to be passed to SPEEDY.
163 thres = 1.e-10_wp ! Threshold for storing coefficients of matrix elements that contribute to Hij.
164
165 nobe(:) = 0 ! Number of electronic orbitals.
166 nobp(:) = 0 ! Number of positronic orbitals.
167 nobv(:) = 0 ! Not used, set to number of target (non-continuum) orbitals.
168
169 npflg(1:6) = 0 ! Print flags for SPEEDY / SCATCI.
170
171 cdimx = 400 ! Workspace size for determinant (real) multiplication factors.
172 ndimx = 4000 ! Workspace size for packed determinant (integer) descriptions.
173 nodimx = 100 ! Workspace size for number of packed determinants per CSF.
174 cdimn = 100 ! Default value for user namelist override of cdimx.
175 ndimn = 1000 ! Default value for user namelist override of ndimx.
176 nodimn = 25 ! Default value for user namelist override of nodimx.
177
178 isz = 0 ! 2*Sz + 1
179 lpp = 0 ! Length of line printer page. Used to determine where to put page banner.
180 confpf = 1 ! Print flag for the amount of print given of configurations and prototypes.
181 symtyp = -1 ! Symmetry type, 0 = C_infv, 1 = D_infh, 2 = {D_2h, C_2v, C_s, E}.
182 gutot = 0 ! Inversion symmetry, used for D_infh only (+1 = gerade, -1 = ungerade).
183 npmult = 0 ! Print flag for the D2h multiplication table (0 = no, 1 = yes).
184 nelect = 0 ! Number of electrons.
185 iposit = 0 ! Exotic particle flag: 0 = electrons only, +/-1 = positive non-electron, +/-2 = negative non-electron.
186 noex = 0 ! Flag to switch off exchange between projectile electron and target electrons: 0 = no exchange
187
188 qntot(1:3) = -2 ! Total quantum numbers (spin multiplicity, irreducible representation, inversion symmetry).
189
190 nob(1:nsymmx) = 0 ! Number of orbitals for configuration generation per symmetry, including continuum orbitals.
191 nob0(1:nsymmx) = 0 ! As above, excluding continuum orbitals.
192 nsoi(1:nsymmx) = 0 ! For each symmetry, index of the first spin-orbital (index runs across all symmetries).
193 nobi(1:nsymmx) = 0 ! For each symmetry, index of the first orbital (index runs across all symmetries).
194
195 nrefo = 0 ! How many quintets are needed to define the reference determinant.
196
197 refdet(1:nemax) = 0 ! Reference determinant (assignment of electrons to spin-orbitals).
198 refgu(1:nrfomx) = -2 ! Gerade (= +1) or underage (= -1) symmetry for the M value of each reference quintet.
199 reforb(1:5,1:nrfomx) = -2 ! Reference determinant setup (quintets).
200 erfs(1:nerfs) = .false. ! Error condition indicators.
201
202 nsym = nsymmx ! Number of symmetries: initialized to maximal number of symmetries.
203 nsymp = nsymmx ! Number of symmetries, whose info to print in stwrit.
204 nrefop = nrfoe !
205 nelp = 0 ! Auxiliary variable typically holding the (calculated) number of electrons.
206
207 ! read the input namelist
208 read(nftr, state, iostat = i, iomsg = errmsg)
209
210 ! abort if namelist read failed
211 if (i /= 0) then
212 write(nftw,'("1***** FAILED TO READ NAMELIST &STATE:",/,9X,A)') trim(errmsg)
213 return
214 end if
215
216 ! choose default value for idiag if not set by input
217 if (idiag < 0) then
218 if (iscat <= 0) idiag = 0 ! SPEEDY format
219 if (iscat > 0) idiag = 1 ! SCATCI format
220 end if
221
222 ! Check the NOB-values
223 !
224 ! NOBE(i) number of electronic orbitals, default nobe(i)=nob(i)
225 ! NOBP(i) number of positronic orbitals, default nobp(i)=0
226 ! NOBV(i) at the moment not used, but printed on output, default nobv(i)=nob0(i)
227
228 do i = 1, nsym
229 if (nobp(i) == 0) then
230 nobe(i) = nob(i)
231 end if
232 nobep = nobe(i) + nobp(i)
233 if (nobep /= nob(i)) then
234 write(nftw,*) 'ERROR on input:'
235 write(nftw,*) 'not: NOB(i)=NOBE(i)+NOBP(i)'
236 write(nftw,*) 'i=', i
237 write(nftw,*) 'NOB(i)=', nob(i)
238 write(nftw,*) 'NOBE(i)=', nobe(i)
239 write(nftw,*) 'NOBP(i)=', nobp(i)
240 end if
241 if (nobv(i) == 0) then
242 nobv(i) = nob0(i)
243 end if
244 if (nob0(i) > nob(i)) then
245 write(nftw,*) 'ERROR on input:'
246 write(nftw,*) 'NOB0(i) > NOB(i)'
247 write(nftw,*) 'i=', i
248 write(nftw,*) 'NOB(i)=', nob(i)
249 write(nftw,*) 'NOB0(i)=', nob0(i)
250 end if
251 end do
252
253 ! get index (-> nsym) of last symmetry with at least one orbital
254 nsym = 0
255 do i = 1, nsymmx
256 if (nob(i) /= 0) nsym = i
257 end do
258 nsymp = nsym
259
260 ! set limit on shell occupancy
261 ! symtyp = 0 (C_infv) : 2,4,4,4,...
262 ! symtyp = 1 (D_infh) : 2,2,4,4,...
263 ! symtyp other : 2,2,2,2,...
264 shlmx1(1:nsymmx) = 2
265 if (symtyp == 0) shlmx1(2:nsymmx) = 4
266 if (symtyp == 1) shlmx1(3:nsymmx) = 4
267
268 ! prepare global indices of orbitals and spin-orbitals across symmetries
269 nobt = 0
270 ntso = 0
271 do i = 1, nsym
272 nsoi(i) = ntso + 1 ! 1-based index of spin-orbital across symmetries
273 nobi(i) = nobt ! 0-based index of orbital across symmetries
274 nob(i) = abs(nob(i))
275 nobt = nobt + nob(i)
276 ntso = ntso + shlmx1(i) * nob(i)
277 end do
278
279 allocate(exdet(ntso), exref(ntso), stat = err)
280
281 ! set up error flags
282 enob = (nsym == 0)
283 epsno = (err /= 0)
284 ene = (nelect <= 0 .or. nelect > nemax)
285 esymt = (symtyp < 0)
286
287 ! continue only if no error condition is raised
288 if (.not. any(erfs)) then
289
290 ! assemble reference list of spin-orbitals (target "reference determinant")
291 call getref (reforb, refgu, nrefo, nelect, refdet, nelr, nsoi, nob, shlmx1, nsym, symtyp, nrfomx, enrefo, ener, erefd)
292
293 ! more initializations
294 nelp = nelect
295 if (.not. enrefo) nrefop = nrefo
296 confpf = max(confpf, 1)
297 if (isz == 0) isz = qntot(1)
298
299 ! check validity of total quantum numbers
300 eqnt = (qntot(1) <= 0 .or. qntot(2) < 0) &
301 .or. (qntot(2) == 0 .and. symtyp <= 1 .and. abs(qntot(3)) /= 1) &
302 .or. (abs(isz - 1) > qntot(1) - 1) &
303 .or. (symtyp == 1 .and. abs(gutot) /= 1)
304
305 ! update array bounds based on namelist input
306 cdimx = max(cdimn, cdimx)
307 ndimx = max(ndimn, ndimx)
308 nodimx = max(nodimn, nodimx)
309
310 ! allocate the wp-real (!) workspace
311 allocate(bmx(nbmx))
312
313 ! calculate positions of data in the workspace
314 icdi = 1
315 indi = icdi + cdimx
316 inodi = indi + ndimx
317 ndel = inodi + nodimx
318 ndel1 = ndel + nndel
319 ndel2 = ndel1 + nndel
320 next = ndel2 + nndel
321 navail = nbmx - next + 1
322 nextk = next / 1024
323
324 ! Workspace is composed of the following consecutive chunks of real numbers
325 ! icdi : icdi + cdimx ... determinant coefficients (real number per determinant)
326 ! indi : indi + ndimx ... packed determinants (size + replacements per determinant)
327 ! inodi : inodi + nodimx ... states ()
328 ! ndel : ndel + nndel ... space for configurations read from input (unit nftr)
329 ! ndel1 : ndel1 + nndel ... workspace for reading configurations from input (unit nftr)
330 ! ndel2 : ndel2 + nndel ... workspace for reading configurations from input (unit nftr)
331 !
332 ! + further chunks per every wave function group:
333 ! irfcon : irfcon + nobt * ntcon ... orbital constraints
334 ! iexcon : iexcon + nobt ... more orbital contrains?
335 ! iqnstr : ? ... only temporarily, overwritten by next wave function group
336
337 write(nftw,'(" NBMX =",I9," WORDS")') nbmx
338 write(nftw,'(" ***** REGION USED FOR INPUT DATA ",I7," WORDS ",I5," K")') next, nextk
339 write(nftw,'(" ***** LEFT ",I9," WORDS")') navail
340
341 ! are we out of space already?
342 espace = (navail <= 0)
343
344 end if
345
346 ! print current setup information
347 call stwrit (nelect, confpf, qntot, cdimx, icdi, ntso, symtyp, ndimx, indi, nrefo, nodimx, inodi, nsym, gutot, nbmx, &
348 isz, navail, idiag, megu, thres, lcdt, megul, lndt, nfto, nrerun, ltri, npflg, nndel, nob, nsoi, nsymp, &
349 refdet, nerfs, erfs, nrefop, reforb, refgu, nelp, lpp, sname, error, byproj, lndo, lcdo, iposit, nob0, &
350 npmult, ntgsym, mxtarg, nobe, nobp, nobv)
351
352 ! if requested, read CSFs directly from input stream
353 if (nndel /= 0) then
354 bmx_ptr => bmx(ndel) ; call c_f_pointer (c_loc(bmx_ptr), ndel_ptr, (/1/))
355 bmx_ptr => bmx(ndel1) ; call c_f_pointer (c_loc(bmx_ptr), ndel1_ptr, (/1/))
356 bmx_ptr => bmx(ndel2) ; call c_f_pointer (c_loc(bmx_ptr), ndel2_ptr, (/1/))
357 call subdel (ndel_ptr, ndel1_ptr, ndel2_ptr, nndel)
358 end if
359
360 ! general default for wfngrp arrays
361 call wfnin (nwfngp, nadel, nncsf, ncsf, lcdi, lndi, nelecg, ndprod, nrefog, npcupf, negmax, refdtg, nrfgmx, refgug, &
362 ntcon, reforg, nshgmx, nsymmx, mshl, gushl, pqn, cup, ndpmax, nshlp, nconmx, test, nrcon, nshcon, tcon, errorg)
363
364 ncsf0 = 0 ! number of CSFs generated up to the previous wfn group
365 ntgsmx = ntgsym !
366 ntgsym = 0 ! number of target symmetries (assuming that all wfn groups are "target × continuum")
367 maxtgsym = 0 ! number of target symmetries (actually taking into account the value of lsquare)
368 mold = -1 ! symmetry (M-value) of the last shell (pqn triplet) in the previous wfn group
369 guold = 0 ! g/u symmetry of the last shell in the previous wfn group
370 qntar1(1) = -1 ! target quantum numbers in the previous wfn group
371 pqn2 = 0 ! orbital sequence start of the last shell in the previous wfn group
372 lsquare = 0 ! do not assume L2 configuration by default
373
374 ! loop over wfngrp input sets
375 wfngrp_loop: do while (nndel == 0 .or. nadel < nndel)
376
377 ! set default values to some parameters (others are carried over from the previous namelist, if any)
378 call wfnin0 (nelecp, defltc, nerfg, erfg, gname, qntar, errorg, ndpmax)
379
380 ! read the user settings from the next &wfngrp namelist
381 read(nftr, wfngrp, iostat = i)
382
383 ! check success
384 if (i /= 0) then
385 call space (2)
386 call addl (1)
387 if (nwfngp == 0) then
388 write(nftw,'(" ***** NO WFNGRP INPUT FOUND")')
389 return
390 end if
391 write(nftw,'(" ***** END OF FILE ON INPUT")')
392 exit wfngrp_loop
393 end if
394
395 call wfngrp_sanity_check(nftw, nob, ndprod, nelecp, nshlp, pqn, mshl)
396
397 ! total number of pqn triplets for this &wfngrp
398 nshlpt = sum(abs(nshlp(1:ndprod)))
399
400 ! assemble information for phase correction data
401 if (iscat < 2 .or. mold < -1) then
402
403 ! no phase correction data required (or all that was needed is already done, do nothing)
404
405 else if (mold == mshl(nshlpt) .and. (symtyp /= 1 .or. guold == gushl(nshlpt)) .and. &
406 all(qntar(1:3) == qntar1(1:3)) .and. pqn2 == pqn(2,nshlpt) .and. lsquare /= 1 .and. gflag /= 0) then
407
408 ! the same target state? - check continuum orbitals consistent!
409 if (notgt(ntgsym) /= pqn(3,nshlpt) - pqn(2,nshlpt) + 1) then
410 write(nftw,'(//," Attempt to perform CI target calculation with different length continua for same target:")')
411 write(nftw,'( " Number of continua, last WFNGRP",I4)') notgt(ntgsym)
412 write(nftw,'( " Number of continua, this WFNGRP",I4)') pqn(3,nshlpt) - pqn(2,nshlpt) + 1
413 write(nftw,'( " STOP")')
414 stop
415 end if
416
417 else
418
419 ! new target state detected: first save data about old one
420 if (ntgsym >= 1) then
421 nctgt(ntgsym) = (ncsf - ncsf0) / notgt(ntgsym)
422 mrkorb(ntgsym) = nspi
423 end if
424
425 if (qntar(1) <= 0 ) then
426
427 ! all target states are finished
428 mold = -2
429
430 else
431
432 ncsf0 = ncsf
433 ntgsym = ntgsym + 1
434 if (ntgsym > ntgsmx) then
435 write(nftw,'(" Number of target states [",I5,"] has exceeded mxtarg [",I5,"].")') ntgsym, ntgsmx
436 write(nftw,'(" Increase mxtarg and recompile.")')
437 stop 1
438 end if
439 if (lsquare == 0) maxtgsym = maxtgsym + 1
440 write(nftw,'(/," Target state number",I3) ') ntgsym
441 write(nftw,'(" TARGET MULTIPLICITY =",I5,5X,"TARGET SYMMETRY =",I5,5X,"TARGET INVERSION SYMMETRY =",I5)') qntar
442 write(nftw,'(" Coupling to continuum with M =",I3)') mshl(nshlpt)
443 if (symtyp == 1) write(nftw,'(27x,"GU =",I3)') gushl(nshlpt)
444
445 ! save continuum electron data for future use
446 notgt(ntgsym) = pqn(3,nshlpt) - pqn(2,nshlpt) + 1
447 mcont(ntgsym) = mshl(nshlpt)
448 if (symtyp == 1) gucont(ntgsym) = gushl(nshlpt)
449 pqn2 = pqn(2,nshlpt)
450
451 ! for degenerate symmetries/degenerate target states, need extra
452 ! information to sort out coupling of possible second continuum
453 if (symtyp <= 1 .and. qntot(2) > 0 .and. qntar(2) > 0) then
454 mdegen(ntgsym) = max(qntot(2), qntar(2)) - mcont(ntgsym)
455 end if
456
457 qntar1(1:3) = qntar(1:3)
458 mold = mshl(nshlpt)
459 if (symtyp == 1) guold = gushl(nshlpt)
460
461 end if
462
463 end if
464
465 ndpp = ndpmax
466 nelp = 0
467 ncupp = 0
468 ntconp = 0
469 nwfngp = nwfngp + 1
470 erfg(1) = .true.
471 if (nelecg <= 0 .or. nelecg > negmax) go to 150
472 erfg(1) = .false.
473 ndprod = max(1, ndprod)
474 erfg(2) = .true.
475 if (ndprod > ndpmax) go to 150
476 erfg(2) = .false.
477 ndpp = ndprod
478 nshlpt = 0
479
480 nelecp(1:ndprod) = abs(nelecp(1:ndprod))
481 nshlp(1:ndprod) = abs(nshlp(1:ndprod))
482 negr = sum(nelecp(1:ndprod))
483 nshlpt = sum(nshlp(1:ndprod))
484
485 erfg(3) = (any(nshlp(1:ndprod) == 0))
486
487 nshlp0 = nshlpt - nshlp(ndprod)
488 if (nshlpt > nshgmx) erfg(3) = .true.
489 if (negr /= nelecg) erfg(4) = .true.
490 if (erfg(3) .or. erfg(4)) go to 150
491
492 ! reference determinant (refdtg) for the wave function group
493 call getref (reforg, refgug, nrefog, nelecg, refdtg, nelr, nsoi, nob, shlmx1, &
494 nsym, symtyp, nshgmx, erfg(5), erfg(6), erfg(7))
495
496 if (.not. erfg(5)) nrefop = nrefog
497 if (.not. erfg(6)) nelp = nelecg
498 if (erfg(5) .or. erfg(6) .or. erfg(7)) go to 150
499
500 ! Set "exref" to contain only the non-movable subset of the global reference determinant.
501 exref(1:ntso) = 0 ! start with unpopulated spin-orbitals
502 exref(refdet(1:nelect)) = 1 ! populate spin-orbitals according to the reference determinant
503 if (any(exref(refdtg(1:nelecg)) == 0)) erfg(7) = .true. ! non-movable spin-orbitals must be a subset of all reference spin-orbitals
504 exref(refdtg(1:nelecg)) = 0 ! un-populate spin-orbitals with movable electrons
505 if (erfg(7)) go to 150
506
507 ! check shell data...
508 erfg(8) = .true.
509 if (noex .eq. 0) then
510 if (iposit /= 0 .and. nelecp(ndprod) /= 1) go to 150 ! ... but skip the check if for non-electrons ...?
511 endif
512
513 do i = 1, nshlpt ! scan all sets of orbitals
514 mshl(i) = abs(mshl(i)) ! use absolute value of the M-value (symmetry)
515 mt = mshl(i) + 1 ! change M-value from 0-based index to 1-based index
516 if (symtyp == 1) then ! special section for degenerate point groups
517 if (abs(gushl(i)) /= 1) go to 150 ! gerage (+1) or ungerade (-1) only possible
518 itu = 1 ! let's call this a kind of parity,...
519 if (mod(mt,2) == 0) itu = -1 ! ...as it changes its sign across the symmetry eigenspaces
520 mt = mt + mt - abs((gushl(i) + itu) / 2) ! expanded symmetry index combining the orig symmetry and g/u
521 end if
522 sshl(i) = mt ! 1-based index of symmetry (expanded, in case of degenerate groups)
523 if (mt > nsym) go to 150 ! out of bounds symmetry index!
524 if (pqn(1,i) /= 0) then ! transform pqn=x00 to xxx for unified processing later
525 pqn(2,i) = pqn(1,i)
526 pqn(3,i) = pqn(2,i)
527 end if
528 d = pqn(3,i) - pqn(2,i) ! distance between orbitals (= orbital count - 1)
529 if (d < 0) go to 150 ! wrong order of orbitals in triplet!
530 shlmx(i) = shlmx1(mt) * (d + 1) ! maximal occupation of i-th set of orbitals
531 nspi = nsoi(mt) + (pqn(2,i) - 1) * shlmx1(mt) ! index of the first spin-orbital in the current set orbitals
532 nspf = nspi + shlmx(i) - 1 ! index of the last spin-orbital in the current set of orbitals
533 if (iposit /= 0 .and. i >= nshlp0) cycle ! ... some extra for non-electrons ...?
534 if (any(exref(nspi:nspf) /= 0)) go to 150 ! the set of orbitals mustn't contain non-movable ones
535 if (pqn(3,i) > nob(mt)) then ! out of bounds orbital index!
536 write(nftw,'(//," Error: PQN number",i3," accesses orbital number",i3)') i, pqn(3,i)
537 write(nftw,'( " symmetry",i2," only contains",i3," orbitals")') mt, nob(mt)
538 go to 150
539 end if
540 end do
541 erfg(8) = .false.
542
543 ! ???
544 ncupp = nshlpt - 1
545 call getcup (nshlpt, defltc, ndprod, nshlp, cup(1,1), erfg(9))
546 if (erfg(9)) npcupf = 1
547 ntcon = min(abs(ntcon), nconmx)
548
549 ! calculate positions of new data in the workspace
550 irfcon = next
551 if (ntcon == 0) go to 150
552 iexcon = irfcon + nobt * ntcon
553 next = iexcon + nobt
554 navail = nbmx - next + 1
555 nextk = next / 1024
556 write(nftw,'(" ***** REGION USED FOR DETERMINANTS ",I7," WORDS ",I5," K")') next, nextk
557 write(nftw,'(" **** LEFT ",I7," WORDS")') navail
558 if (navail <= 0) erfg(11) = .true.
559
560 ! set up constraints
561 bmx_ptr => bmx(irfcon) ; call c_f_pointer (c_loc(bmx_ptr), irfcon_ptr, (/1/))
562 call getcon (ntcon, nshcon, nrcon, nshgmx, nrfgoe, ntconp, nelecg, nsym, &
563 nobt, nob, nobi, nsoi, shlmx1, exref, tcon, irfcon_ptr, &
564 erfg(10))
565
566 ! position of "qnstr"(?) data in the workspace
567 150 iqnstr = next
568
569 ! write information about wave function group to output...
570 bmx_ptr => bmx(irfcon) ; call c_f_pointer (c_loc(bmx_ptr), irfcon_ptr, (/1/))
571 call wvwrit (nwfngp, gname, nelecg, defltc, irfcon, ndprod, symtyp, ntcon, &
572 navail, nrefog, nelecp, nshlp, qntar, nshlpt, nshgmx, mshl, &
573 gushl, pqn, cup, ncupp, npcupf, refdtg, nelp, ntconp, nshcon, &
574 nobt, reforb, refgu, test, nrcon, tcon, irfcon_ptr, nerfg, &
575 erfg, ndpp, nrefop, lsquare, errorg)
576
577 ! ... and do nothing more if there are errors
578 if (errorg) return
579
580 ! push data to global arrays
581 nqntot(1:3) = qntot(1:3)
582 nqntar(1:3) = qntar(1:3)
583 nisz = isz
584 ngutot = gutot
585 nnlecg = nelecg
586 nsmtyp = symtyp
587 nnndel = nndel
588
589 exref(1:ntso) = 0 ! start with un-populated spin-orbitals
590 exref(refdtg(1:nelecg)) = 1 ! populate spin-orbitals with movable electrons only
591
592 ncall = 1 ! this will make "wfn" routine initialize some arrays
593 ift = 1 ! this will make "assign" routine initialize some arrays
594
595 call icgcf ! precompute needed binomial coefficients
596
597 call distrb (nelecp, nshlp, shlmx, occshl, nslsv, kdssv, loopf, ksss, pqn, &
598 occst, shlmx1, pqnst, mshl, mshlst, gushl, gushst, cup, cupst, &
599 ndprod, symtyp, confpf, sshl, sshlst, ncsf, nncsf, nadel, &
600 nndel, bmx, nftw, noex)
601
602 ! write constructed (non-yet-projected) CSFs to output file
603 bmx_ptr => bmx(1) ; call c_f_pointer (c_loc(bmx_ptr), int_ptr, (/1/))
604 call csfout (lc, ln, megul, nndel, bmx, int_ptr)
605
606 ! update total number of stored coefficients and integers forming packed determinants
607 lcdi = lcdi + lc
608 lndi = lndi + ln
609
610 end do wfngrp_loop
611
612 ! check that data for final target state has been saved
613 mflag = 0
614 if (ntgsym >= 1) then
615 if (mold > -2) then
616 nctgt(ntgsym) = (ncsf - ncsf0) / notgt(ntgsym)
617 mrkorb(ntgsym) = nspi
618 end if
619
620 ! for degenerate symmetries/degenerate target states, need extra
621 ! information to sort out coupling of possible second continuum
622 ! check this for errors and missed couplings
623 if (symtyp <= 1 .and. qntot(2) > 0) then
624 if (mdegen(ntgsym) > 0) mdegen(ntgsym) = 0
625 do n = 2, ntgsym
626 if (mdegen(n) > 0) then
627 if (mdegen(n-1) <= 0) then
628 write(nftw,'(/," WARNING: for target state number",I3)') ntgsym
629 write(nftw,'( " Coupling to upper continuum only detected")')
630 write(nftw,'( " Calculation may give target phase problems")')
631 mdegen(n) = 0
632 else if (nctgt(n) /= nctgt(n-1)) then
633 write(nftw,'(/," Target states",I3," and",I3)') n - 1, n
634 write(nftw,'( " analysed for degenerate coupling to the continuum")')
635 write(nftw,'( " But number of CSFs differ:",I6," and",I6," respectively: STOP")') nctgt(n-1), nctgt(n)
636 stop
637 end if
638 else if (mdegen(n) > 0) then
639 if (mdegen(n-1) > 0) mdegen(n-1) = 0
640 end if
641 if (mdegen(n) /= 0) mflag = max(mflag, nctgt(n))
642 end do
643 end if
644 end if
645
646 call space (2)
647 call addl (1)
648
649 write(nftw,'(" ********** TOTAL NUMBER OF CSF''S GENERATED IS ",I9)') ncsf
650
651 !
652 ! Quantenmol: open a file fort.400 to inform the user about estimated time of the run
653 !
654
655 if (qmoln .and. iscat < 2 .and. megul == 70) then
656
657 open(unit = conmes, status = 'unknown')
658 write(conmes,'(/," *** TOTAL NUMBER OF GENERATED CSF''S FOR THE GROUND STATE IS ",I6)') ncsf
659
660 if (ncsf <= 600) then
661 write(conmes,'("*** This target calculation should not take long !",/)')
662 else if (ncsf > 600 .and. ncsf < 12000) then
663 write(conmes,'("*** This target calculation will take a few hours !")')
664 write(conmes,'("*** You can have a cup of tea and come back later.",/)')
665 else if (ncsf > 12000 .and. ncsf <= 22000) then
666 write(conmes,'("*** Oops, This target calculation is very big !")')
667 write(conmes,'("*** You can come back tomorrow.",/)')
668 else if (ncsf > 22000 .and. ncsf <= 80000) then
669 write(conmes,'("*** Oops, This target calculation is very big ")')
670 write(conmes,'("*** and can take several days to run !",/)')
671 else if (ncsf > 80000) then
672 write(conmes,'("*** Oops, This target calculation is too big ")')
673 write(conmes,'("*** to be computationally possible !")')
674 write(conmes,'("*** Rerun with a smaller basis or contact ")')
675 write(conmes,'("*** technical support: support@quantemol.com")')
676 end if
677
678 close(conmes)
679
680 end if
681
682 s = real(qntot(1) - 1,kind = wp) / two
683 sz = real(isz - 1, kind = wp) / two
684 r = zero
685 if (qntot(2) == 0 .and. symtyp <= 1) r = real(qntot(3), kind = wp)
686 pin = zero
687
688 ! save contents of nob and nob0 prior to any symmetry conversion
689 nobl(1:nsym) = nob(1:nsym)
690 nob0l(1:nsym) = nob0(1:nsym)
691 if (symtyp == 1) then
692 pin = real(gutot, kind = wp)
693 j = 0
694 do i = 1, nsym, 2
695 j = j + 1
696 nob(j) = nob(i) + nob(i+1)
697 nob0(j) = nob0(i) + nob0(i+1)
698 end do
699 nsym = j
700 end if
701
702 if (allocated(bmx)) deallocate(bmx)
703
704 call newpg
705
706 ! stage 2: read CSFs back and project
707 rewind megul
708
709 ! SCATCI data output
710 if (byproj > 0 .or. iscat > 0) then
711 call projec (sname, megul, symtyp, qntot(2), s, sz, r, pin, ncsf, byproj, idiag, npflg, thres, nelect, nsym, &
712 nob, refdet, nftw, iposit, nob0, nobl, nob0l, iscat, ntgsym, notgt, nctgt, mcont, gucont, mrkorb, &
713 mdegen, mflag, nobe, nobp, nobv, maxtgsym)
714 end if
715
716 ! SPEEDY data output
717 if (iscat <= 0) then
718 call wrnmlt (megu, sname, nrerun, megul, symtyp, qntot(2), s, sz, r, pin, ncsf, byproj, lcdi, lndi, lcdo, lndo, &
719 lcdt, lndt, nfto, ltri, idiag, npflg, thres, nelect, nsym, nob, refdet, nftw, iposit, nob0, nobl, &
720 nob0l, nx, nobe, nobp, nobv)
721 rewind megu
722 end if
723
724 ! final text information output
725 if (confpf >= 1) then
726 call wrnmlt (nftw, sname, nrerun, megul, symtyp, qntot(2), s, sz, r, pin, ncsf, byproj, lcdi, lndi, lcdo, lndo, &
727 lcdt, lndt, nfto, ltri, idiag, npflg, thres, nelect, nsym, nob, refdet, nftw, iposit, nob0, nobl, &
728 nob0l, nx, nobe, nobp, nobv)
729 end if
730
731 end subroutine csfgen
732
733
734 !> \brief Check electron distribution
735 !> \authors J Benda
736 !> \date 2024 - 2025
737 !>
738 !> Perform some basic checks on the electron distribution parameters to filter out trivial errors.
739 !>
740 !> \param nftw Output unit.
741 !> \param ndprod Number of sets of shells.
742 !> \param nelecp Number of electrons in each set.
743 !> \param nshlp Number of shells (triplets) in each set.
744 !> \param pqn Orbitals in each shell.
745 !> \param mshl Symmetry of shells above.
746 !>
747 subroutine wfngrp_sanity_check (nftw, nob, ndprod, nelecp, nshlp, pqn, mshl)
748
749 use congen_data, only: nu, shlmx1
750
751 integer, intent(in) :: nftw, nob(:), ndprod, nelecp(:), nshlp(:), pqn(:, :), mshl(:)
752
753 integer :: iset, jset, ishl, jshl, ipqn, jpqn, iorb, jorb, irr, npqn, nso
754
755 character(len=*), parameter :: err_few_shells = &
756 '(/,"ERROR: Set of shells ",i0," has to accommodate ",i0," particles but has only ",i0," spinorbitals!")'
757 character(len=*), parameter :: err_missing_pqn = &
758 '(/,"ERROR: PQN triplet ",i0," unspecified, but used by shell ",i0," in set ",i0,"!")'
759 character(len=*), parameter :: err_invalid_mshl = &
760 '(/,"ERROR: Invalid MSHL value ",i0," for PQN triplet ",i0,"!")'
761 character(len=*), parameter :: err_overlapping_pqns = &
762 '(/,"ERROR: Orbital ",i0," with MSHL ",i0," is used in two PQN triplets ",i0," and ",i0,"!")'
763 character(len=*), parameter :: err_out_of_orbitals = &
764 '(/,"ERROR: PQN triplet ",i0," references orbitals beyond NOB (",i0,")!")'
765
766 ! check that there are enough PQN triplets for the given NDPROP and NSHLP
767 ipqn = 0
768 do iset = 1, ndprod
769 nso = 0
770 do ishl = 1, nshlp(iset)
771 ipqn = ipqn + 1
772 if (pqn(1, ipqn) == -1) then
773 write (nftw, err_missing_pqn) ipqn, ishl, iset
774 stop 1
775 end if
776 irr = mshl(ipqn)
777 if (irr < 0 .or. irr >= nu) then
778 write (nftw, err_invalid_mshl) irr, ipqn
779 stop 1
780 end if
781 if (any(pqn(:, ipqn) > nob(irr + 1))) then
782 write (nftw, err_out_of_orbitals) ipqn, nob(irr + 1)
783 stop 1
784 end if
785 if (pqn(1, ipqn) /= 0) then
786 nso = nso + shlmx1(irr + 1) ! direct orbital reference mode (pqn = K,0,0)
787 else
788 nso = nso + (pqn(3, ipqn) - pqn(2, ipqn) + 1)*shlmx1(irr + 1) ! sequence mode (pqn = 0,I,J)
789 end if
790 end do
791 if (nelecp(iset) > nso) then
792 write (nftw, err_few_shells) iset, nelecp(iset), nso
793 stop 1
794 end if
795 end do
796
797 ! check non-overlapping orbital ranges (provided that all non-empty PQNs use the sequence mode, i.e. 0,I,J)
798 ipqn = 0
799 npqn = sum(nshlp(1:ndprod))
800 if (all(pqn(1, 1:npqn) == 0)) then
801 ! scan all PQN triplets
802 do iset = 1, ndprod
803 do ishl = 1, nshlp(iset)
804 ipqn = ipqn + 1
805 ! check only non-empty ones
806 if (nelecp(iset) > 0) then
807 do iorb = pqn(2, ipqn), pqn(3, ipqn)
808 ! scan all previous PQN triplets
809 jpqn = 0
810 do jset = 1, ndprod
811 do jshl = 1, nshlp(jset)
812 jpqn = jpqn + 1
813 ! check only non-empty ones with the same symmetry
814 if (jpqn < ipqn .and. nelecp(jset) > 0 .and. mshl(jpqn) == mshl(ipqn)) then
815 do jorb = pqn(2, jpqn), pqn(3, jpqn)
816 if (iorb == jorb) then
817 write (nftw, err_overlapping_pqns) iorb, mshl(jpqn), ipqn, jpqn
818 stop 1
819 end if
820 end do
821 end if
822 end do
823 end do
824 end do
825 end if
826 end do
827 end do
828 end if
829
830 end subroutine wfngrp_sanity_check
831
832
833 !> \brief Store the wave function to file and reset arrays
834 !>
835 !> Writes all determinants present in the CONGEN global arrays (i.e. for the current CSFs) to the output file.
836 !> The data written are as follows:
837 !> \verbatim
838 !> 1. NOI ... number of states
839 !> 2. NODI(1:NOI) ... number of determinants per state
840 !> 3. NID ... number of all determinants
841 !> 4. CR(1:NID) ... determinant multiplicative factors
842 !> 5. NI ... length of integer array defining all determinants
843 !> 6. NR(1:NI) ... integer array defining all determinants as differences w.r.t. reference determinant
844 !> \endverbatim
845 !>
846 !> Note that this is not the only moment when these data are written. The subroutine \ref congen_distribution::wfn
847 !> does writing, too, whenever it detects that any further addition of determinants would exceed the storage.
848 !>
849 !> Once the writing is done, this subroutine erases all determinant data.
850 !>
851 !> \param ia On output, accumulated number of written determinants (value of \ref congen_data::lcdi).
852 !> \param ib On output, accumulated number of written integers describing the determinants (value of \ref congen_data::lndi).
853 !> \param megul Output file unit number.
854 !> \param nndel How many CSFs were read from standard input. If non-zero, nothing will be written to the file and the
855 !> variables \c ia and \c ib will be assigned just the current values of \c lcdi and \c lcdt.
856 !> \param cr Real workspace array; determinant coefficients are expected to be located at index \c icdi and onwards.
857 !> \param nr Real workspace array; determinant array pointers are expected to be located at position \c inodi and onwards,
858 !> while packed determinant descriptions are expected at position \c indi and onwards. More specifically, this is
859 !> true if integer has the same byte size as the real data type. Otherwise the offsets are adjusted so that
860 !> they allow for \c inodi - 1 or \c indi - 1 real numbers before start of the determinant integer data.
861 !>
862 subroutine csfout (ia, ib, megul, nndel, cr, nr)
863
864 use precisn, only : wp
865 use congen_data, only : lratio, iidis2, lcdi, lndi, ni, nid, noi, icdi, indi, inodi
866
867 integer :: ia, ib, megul, nndel
868 real(kind=wp), dimension(*) :: cr
869 integer, dimension(*) :: nr
870 intent (in) cr, megul, nndel, nr
871 intent (out) ia, ib
872
873 integer :: i
874
875 if (noi /= 0 .or. ni /= 0 .or. nid /= 0) then
876
877 if (nndel == 0 .or. iidis2 /= 0) then
878 write(megul) noi, (nr(i+(inodi-1)*lratio), i=1,noi)
879 write(megul) nid, (cr(i+icdi-1), i=1,nid)
880 write(megul) ni, (nr(i+(indi-1)*lratio), i=1,ni)
881 lcdi = lcdi + nid
882 lndi = lndi + ni
883 end if
884
885 noi = 0
886 nid = 0
887 ni = 0
888
889 end if
890
891 ia = lcdi
892 ib = lndi
893
894 end subroutine csfout
895
896
897 !> \brief Check tcon data and form refcon array
898 !>
899 subroutine getcon (ntcon, nshcon, nrcon, nshgmx, npmax, nc, nelecg, nsym, nobt, nob, nobi, nsoi, shlmx1, exref, tcon, &
900 refcon, error)
901
902 logical :: error
903 integer :: nc, nelecg, nobt, npmax, nshgmx, nsym, ntcon
904 integer, dimension(*) :: exref, nob, nobi, nrcon, nshcon, nsoi, shlmx1
905 integer, dimension(nobt,*) :: refcon
906 integer, dimension(3,nshgmx,*) :: tcon ! JMC the dimensions could be changed to (3,JX,JZ) if desired.
907 intent (in) exref, nelecg, nob, nobi, nobt, npmax, nrcon, nshgmx, nsoi, nsym, ntcon, shlmx1, tcon
908 intent (out) error
909 intent (inout) nc, nshcon, refcon
910
911 integer :: ic, j, k, nel, nesym, net, netc, noc, ns, nshcr, nspf, nspi, pqnt, pqntm, symt
912
913 error = .false.
914 nc = 0
915 if (ntcon == 0) return
916 error = .true.
917 do ic = 1, ntcon
918 nc = nc + 1
919 do j = 1, nobt
920 refcon(j,ic) = 0
921 end do
922 nshcr = nshcon(ic)
923 if (nshcr <= nshgmx) then
924 else
925 nshcon(ic) = npmax
926 return
927 end if
928 if (nrcon(ic) < 0 .or. nrcon(ic) > nelecg) return
929 netc = 0
930 do j = 1, nshcr
931 symt = tcon(1,j,ic) + 1
932 pqnt = tcon(2,j,ic)
933 net = tcon(3,j,ic)
934 if (symt <= 0 .or. symt > nsym) return
935 if (net <= 0) return
936 netc = netc + net
937 nesym = shlmx1(symt)
938 pqntm = pqnt + (net - 1) / nesym
939 if (pqnt <= 0 .or. pqntm > nob(symt)) return
940 nspi = nsoi(symt) + (pqnt - 1) * nesym
941 nspf = nspi + ((net + 1) / nesym) * nesym - 1
942 do ns = nspi, nspf
943 if (exref(ns) /= 0) return
944 end do
945 noc = nobi(symt) + pqnt - 1
946 nel = net
947 do k = 1, nel, nesym
948 noc = noc + 1
949 if (refcon(noc,ic) /= 0) return
950 refcon(noc,ic) = min(nesym, net)
951 net = net - nesym
952 end do
953 end do
954 if (netc /= nelecg) return
955 end do
956 error = .false.
957
958 end subroutine getcon
959
960
961 !> \brief Set up coupling scheme
962 !>
963 subroutine getcup (nshlt, def, nd, nshlp, cup, error)
964
965 integer :: def, nd, nshlt
966 logical :: error
967 integer, dimension(3,nshlt) :: cup
968 integer, dimension(nd) :: nshlp
969 intent (in) def, nd, nshlp, nshlt
970 intent (out) error
971 intent (inout) cup
972
973 integer :: i, i1cup, i2cup, ifc, ifcup, ii, iicup, itest, j, nc, ncup, ncup2, ndm1, ns1, ns2, nsc1, nsc2
974
975 error = .false.
976 if (nshlt == 1) return
977
978 if (def == 0) then
979
980 ifcup = nshlt
981 ifc = 0
982 i1cup = 1
983 do i = 1, nd
984 iicup = nshlp(i) - 1
985 if (iicup /= 0) then
986 i2cup = i1cup
987 do ii = 1, iicup
988 ifc = ifc + 1
989 ifcup = ifcup + 1
990 i2cup = i2cup + 1
991 cup(1,ifc) = i1cup
992 cup(2,ifc) = i2cup
993 cup(3,ifc) = ifcup
994 i1cup = ifcup
995 end do
996 i1cup = i2cup
997 end if
998 i1cup = i1cup + 1
999 end do
1000 ndm1 = nd - 1
1001
1002 ! complete shell to shell couplings
1003 ns1 = 1
1004 nsc1 = nshlp(1) - 1
1005 do i = 1, ndm1
1006 ns2 = ns1 + nshlp(i)
1007 nsc2 = nsc1 + (nshlp(i + 1) - 1)
1008 ifc = ifc + 1
1009 ifcup = ifcup + 1
1010 i1cup = ns1
1011 i2cup = ns2
1012 if (nshlp(i) /= 1) i1cup = cup(3,nsc1)
1013 if (nshlp(i+1) /= 1) i2cup = cup(3,nsc2)
1014 if (i > 1) i1cup = cup(3,ifc-1)
1015 cup(1,ifc) = i1cup
1016 cup(2,ifc) = i2cup
1017 cup(3,ifc) = ifcup
1018 ns1 = ns2
1019 nsc1 = nsc2
1020 end do
1021
1022 end if
1023
1024 ! check cup array for allowed values
1025 error = .true.
1026 ncup = nshlt - 1
1027 itest = nshlt
1028 do i = 1, ncup
1029 itest = itest + 1
1030 if (cup(3,i) /= itest) return
1031 if (cup(1,i) >= itest .or. cup(2,i) >= itest) return
1032 end do
1033
1034 ncup2 = ncup + ncup
1035 do i = 1, ncup2
1036 nc = 0
1037 do j = 1, ncup
1038 if (cup(1,j) == i) nc = nc + 1
1039 if (cup(2,j) == i) nc = nc + 1
1040 end do
1041 if (nc /= 1) return
1042 end do
1043 error = .false.
1044
1045 end subroutine getcup
1046
1047
1048 !> \brief Form reference list of spin-orbital numbers
1049 !>
1050 !> This subroutine construct the "reference determinant", which is nothing else than a list of unique numbers, one for each
1051 !> electron, where each number corresponds to one of molecular spin-orbitals defined by the \c &state namelist of CONGEN.
1052 !> The spin-orbitals are labeled sequentially across all symmetries, where all spin-orbitals sharing an orbital (but differing
1053 !> by spin) are kept together with consecutive indices. The order of spins within groups corresponding to a single orbital
1054 !> is "alpha spin, then beta spin". On successful return, the array \c refdet contains the reference list with indices sorted
1055 !> from smallest to largest.
1056 !>
1057 !> This subroutine can run into several error conditions that are indicated by logical flags \c e1, \c e2, \c e3 (.true.
1058 !> means that the error occured). They are all related to inconsistencies in the input file.
1059 !>
1060 !> \param reforb Reference determinant quintets specification (1 = M-value of shell, 2 = \c pqn, 3 = number of electrons in shell,
1061 !> 4 = spin orb 1, 5 = spin orb 2)
1062 !> \param refgu Inversion symmetry numbers for orbitals (+1 = gerade, -1 = ungerade). Only used for \c symtyp = 1 (D_infh).
1063 !> \param nrefo Number of quintets in \c reforb.
1064 !> \param nelec Input value of number of electrons.
1065 !> \param refdet List of spin-orbital numbers (one for each electron, in increasing order) in reference determinant.
1066 !> \param nelr Computed number of electrons from \c reforb(3,i).
1067 !> \param nsoi Initial value of spin orb 1 for all symmetries (index runs through all symmetries).
1068 !> \param nob ?
1069 !> \param symtyp Point group (0 = C_infv, 1 = D_infh, 2 = D_2h,C_2v,C_s,E).
1070 !> \param shlmx Shell occupancy limit for each symmetry.
1071 !> \param nsym Number of available irreducible representations.
1072 !> \param nrfomx Max number of orbitals for ref state in arrays \c reforb and \c refgu.
1073 !> \param e1 Output error flag: \c nrefo out of range.
1074 !> \param e2 Output error flag: \c nelr does not match \c nelec.
1075 !> \param e3 Output error flag: Errors in \c reforb and \c refgu arrays.
1076 !>
1077 subroutine getref (reforb, refgu, nrefo, nelec, refdet, nelr, nsoi, nob, shlmx, nsym, symtyp, nrfomx, e1, e2, e3)
1078
1079 logical :: e1, e2, e3
1080 integer :: nelec, nelr, nrefo, nrfomx, nsym, symtyp
1081 integer, dimension(*) :: nob, nsoi, refdet, shlmx
1082 integer, dimension(*) :: refgu
1083 integer, dimension(5,*) :: reforb
1084 intent (in) nelec, nob, nrefo, nrfomx, nsoi, nsym, refgu, reforb, shlmx, symtyp
1085 intent (out) e1, e2, e3
1086 intent (inout) nelr, refdet
1087
1088 integer :: i, isot, j, jj, ne, neb, nelrm1, neo, ner, nesr, pqnr, pqnrm, symr, t1, tgu
1089
1090 ! so far no errors
1091 e1 = .false.
1092 e2 = .false.
1093 e3 = .false.
1094
1095 ! make sure that 'nrefo' is in interval 1 .. 'nrfomx'
1096 if (nrefo <= 0 .or. nrefo > nrfomx) then
1097 e1 = .true.
1098 return
1099 end if
1100
1101 ! make sure that there are really 'nelec' electrons used in quintets
1102 nelr = sum(abs(reforb(3,1:nrefo)))
1103 if (nelr /= nelec) then
1104 e2 = .true.
1105 return
1106 end if
1107
1108 ! loop over all quintets
1109 nelr = 0
1110 do i = 1, nrefo
1111
1112 ! unpack quintet data
1113 symr = reforb(1,i) + 1
1114 pqnr = reforb(2,i)
1115 ne = reforb(3,i)
1116
1117 ! D_infh-specific code
1118 if (symtyp == 1) then
1119 ! check if the mirror symmetry q-number is valid
1120 tgu = refgu(i)
1121 if (abs(tgu) /= 1) then
1122 e3 = .true.
1123 return
1124 end if
1125
1126 ! remap symr according to this table:
1127 !
1128 ! | original symr
1129 ! tgu | 1 2 3 4 5 ...
1130 ! ----|-----------------------
1131 ! +1 | 1 4 5 8 9 ...
1132 ! -1 | 2 3 6 7 10 ...
1133 !
1134 if (mod(symr,2) /= 0) tgu = -tgu
1135 symr = 2 * symr - (1 - tgu) / 2
1136 end if
1137
1138 ! abort on reference to non-existent symmetry
1139 if (symr <= 0 .or. symr > nsym .or. ne <= 0) then
1140 e3 = .true.
1141 return
1142 end if
1143
1144 ! make sure that electrons in this quintet actually fit in provided orbitals
1145 nesr = shlmx(symr)
1146 pqnrm = pqnr + (ne - 1) / nesr
1147 if (pqnr <= 0 .or. pqnrm > nob(symr)) then
1148 e3 = .true.
1149 return
1150 end if
1151
1152 ! spin-orbital indices
1153 isot = nsoi(symr) + (pqnr - 1) * nesr - 1 ! global index of the spin-orbital just before the starting one for this quintet
1154 neo = mod(ne, nesr) ! number of electrons in this quintet that are in open shell
1155 ner = nelr + ne - neo ! number of all electrons in closed shells so far
1156 neb = min(neo, nesr - neo) ! number of electrons or holes in the shell, whichever is smaller
1157
1158 ! label electrons in this quintet by the next free spin-orbitals
1159 do j = 1, ne
1160 nelr = nelr + 1
1161 isot = isot + 1
1162 refdet(nelr) = isot
1163 end do
1164
1165 ! And that's all for closed shell!
1166 ! ... also cycle if there are no data for treatment of open shells
1167 if (neo == 0) cycle
1168 if (all(reforb(3+1:3+neb,i) == -1)) cycle
1169
1170 ! revisit the first electron that is not in closed shell
1171 isot = isot - neo + 1
1172
1173 ! if the shell is not filled over half...
1174 if (neo == neb) then
1175 do j = 1, neb
1176 if (reforb(3+j,i) < 0 .or. reforb(3+j,i) > nesr) then
1177 e3 = .true.
1178 return
1179 end if
1180 ner = ner + 1
1181 ! ... just correct the electron spin-orbital indices by offset ("spin") value given by the user from reforb(4:,i)
1182 refdet(ner) = isot + reforb(3+j,i)
1183 end do
1184 cycle
1185 end if
1186
1187 ! when the shell is filled over half ...
1188 nesr_loop: do j = 1, nesr
1189 do jj = 1, neb
1190 if (reforb(3+jj,i) < 0 .or. reforb(3+jj,i) > nesr) then
1191 e3 = .true.
1192 return
1193 end if
1194 if (reforb(3+jj,i) < j - 1) cycle nesr_loop
1195 end do
1196 ner = ner + 1
1197 ! ... do some other magic ???
1198 refdet(ner) = isot + j - 1
1199 end do nesr_loop
1200
1201 end do
1202
1203 ! order spin-orbital numbers in refdet (if more than one electron)
1204 nelrm1 = nelr - 1
1205 if (nelrm1 > 0) then
1206 do i = 1, nelrm1
1207 t1 = refdet(i)
1208 j = i + 1
1209 do jj = 1, ner
1210 if (t1 == refdet(jj)) return
1211 if (t1 <= refdet(jj)) cycle
1212 t1 = refdet(jj)
1213 refdet(jj) = refdet(i)
1214 refdet(i) = t1
1215 end do
1216 end do
1217 end if
1218
1219 end subroutine getref
1220
1221
1222 !> \brief Precomputes needed binomial coefficients
1223 !>
1224 !> Calculates the Pascal triangle of a given order. The binomial coefficients are stored
1225 !> in the array \c binom as concatenated lines of the Pascal triangle, where the consecutive
1226 !> lines share the common value of 1. The array \c ind contains pointers to line beginnings.
1227 !> The leading elements of the two arrays are:
1228 !> \verbatim
1229 !> ind = 1, 1, 2, 4, 7, ...
1230 !> binom = 1, 1, 2, 1, 3, 3, 1, 4, 6, 4, 1, ...
1231 !> \endverbatim
1232 !>
1233 subroutine icgcf
1234
1235 use precisn, only : wp
1236 use consts, only : one => xone
1237 use congen_data, only : binom, ind, jsmax
1238
1239 integer :: i, jj, js, lb, lb1
1240
1241 ind(1) = 1
1242 ind(2) = 1
1243 binom(1) = one
1244 binom(2) = one
1245 lb = 3
1246 lb1 = 1
1247 js = jsmax + 1
1248 do i = 2, js
1249 do jj = 2, i
1250 binom(lb) = binom(lb1) + binom(lb1 + 1)
1251 lb = lb + 1
1252 lb1 = lb1 + 1
1253 end do
1254 ind(i + 1) = lb1
1255 binom(lb) = one
1256 lb = lb + 1
1257 end do
1258
1259 end subroutine icgcf
1260
1261
1262 !> \brief Write information obtained from &state
1263 !>
1264 !> This subroutine is called by \ref csfgen after the \c &state namelist is read, workspace allocated and reference
1265 !> determinant formed. Its purpose is to summarize the so far read input data on standard output (or other unit specified
1266 !> by \c nftw) and also to print information about the reference determinant.
1267 !>
1268 !> This subroutine does not alter any of its arguments except for \c error, which is set to .true. if an error condition
1269 !> occured and to .false. otherwise.
1270 !>
1271 subroutine stwrit (nelect, confpf, qntot, cdimx, icdi, ntso, symtyp, ndimx, indi, nrefo, nodimx, inodi, nsym, gutot, nbmx, &
1272 isz, navail, idiag, megu, thres, lcdt, megul, lndt, nfto, nrerun, ltri, npflg, nndel, nob, nsoi, nsymp, &
1273 refdet, nerfs, erfs, nrefop, reforb, refgu, nelp, lpp, sname, error, byproj, lndo, lcdo, iposit, nob0, &
1274 npmult, ntgsym, mxtarg, nobe, nobp, nobv)
1275
1276 use precisn, only : wp
1277 use global_utils, only : mprod
1278 use congen_data, only : nftw, nu, rhead
1280
1281 integer :: byproj, cdimx, confpf, gutot, icdi, idiag, indi, inodi, &
1282 iposit, isz, lcdo, lcdt, lndo, lndt, lpp, ltri, megu, &
1283 megul, mxtarg, navail, nbmx, ndimx, nelect, nelp, &
1284 nerfs, nfto, nndel, nodimx, npmult, nrefo, nrefop, &
1285 nrerun, nsym, nsymp, ntgsym, ntso, symtyp
1286 logical :: error
1287 character(len=80) :: sname
1288 real(kind=wp) :: thres
1289 logical, dimension(9) :: erfs
1290 integer, dimension(nu) :: nob, nob0, nobe, nobp, nobv, nsoi ! JMC changing the dimension from 10
1291 integer, dimension(6) :: npflg
1292 integer, dimension(3) :: qntot
1293 integer, dimension(*) :: refdet, refgu
1294 integer, dimension(5,*) :: reforb
1295 intent (in) byproj, cdimx, confpf, erfs, gutot, icdi, idiag, indi, &
1296 inodi, iposit, isz, lcdo, lcdt, lndo, lndt, ltri, &
1297 megu, megul, mxtarg, navail, nbmx, ndimx, nelect, &
1298 nelp, nerfs, nfto, nndel, nob, nob0, nobe, nobp, nobv, &
1299 nodimx, npflg, nrefo, nrefop, nrerun, nsoi, nsym, &
1300 nsymp, ntgsym, ntso, qntot, refdet, refgu, reforb, &
1301 symtyp, thres
1302 intent (inout) error
1303
1304 character(len=32), dimension(9) :: ersnts
1305 character(len=30) :: head = 'CONGEN 1.0 IBM SAN JOSE '
1306 integer :: i, ii, imax, ip, it, junk, lsn = 64, nitem = 30
1307
1308 data ersnts/'SYMMETRY TYPE OUT OF RANGE ', &
1309 'NO ORBITALS GIVEN ', &
1310 'EXDET, EXREF ALLOCATION FAILED ', &
1311 'NELECT OUT OF RANGE ', &
1312 'NREFO OUT OF RANGE ', &
1313 'SUM NELEC IN REF ORBS NE NELECT ', &
1314 'ERROR IN REFORB DATA ', &
1315 'ERROR IN TOTAL QN DATA ', &
1316 'NO CORE FOR CDI, NDI, AND NODI '/
1317
1318 call ctlpg1 (lpp, head, len(head), sname, lsn)
1319 call newpg
1320 call addl (15)
1321
1322 write(nftw,'(T2,"NELECT",T8,I4,T15,"CONFPF",I3,T27,"MULT ",I2,T38,"CDIMX ",I5,T52,"ICDI ",I6)') &
1323 nelect, confpf, qntot(1), cdimx, icdi
1324 write(nftw,'(" NTSO ",I4,T15,"SYMTYP",I3,T27,"MVAL ",I2,T38,"NIDMX ",I5,T52,"INDI ",I6)') &
1325 ntso, symtyp, qntot(2), ndimx, indi
1326 write(nftw,'(" NREFO ",I4,T27,"REFLC",I3,T38,"NODIMX",I5,T52,"INODI",I6)') nrefo, qntot(3), nodimx, inodi
1327 write(nftw,'(" NSYM ",I4,T27,"GUTOT",I3,T38,"NCORE",I10)') nsym, gutot, nbmx
1328 write(nftw,'(T27,"ISZ ",I3,T38,"NAV ",I10)') isz, navail
1329
1330 write(nftw,'(//,T14," DATA FOR SPEEDY INPUT")')
1331 write(nftw,'(/, T14,"IDIAG ",I4,T27,"MEGU ",I3,T38,"THRES ",1PE12.4)') idiag, megu, thres
1332 write(nftw,'(T14,"LCDT ",I4,T27,"MEGUL",I3)') lcdt, megul
1333 write(nftw,'(T14,"LNDT ",I4,T27,"NFTO ",I3)') lndt, nfto
1334 write(nftw,'(T14,"NRERUN",I4,T27,"LTRI ",I3)') nrerun, ltri
1335 write(nftw,'(/,T14,"NPFLG =",6I3,2X,"NNDEL = ",I5)') npflg, nndel
1336
1337 call addl (1)
1338
1339 write(nftw,'(T14,"BYPROJ",I2,3x,"LNDO",I10,3x,"LCDO",I10)') byproj, lndo, lcdo
1340
1341 if (ntgsym < mxtarg) then
1342 call addl (1)
1343 write(nftw,'(" ntgsym",I4)') ntgsym
1344 end if
1345
1346 call space (2)
1347 call addl (3)
1348
1349 write(nftw,'(" NSYM",30I5)') (ip, ip=1,nsymp)
1350 write(nftw,'(" NOB ",30I5)') (nob(ip), ip=1,nsymp)
1351 if (iposit /= 0) then
1352 call addl (4) ! JMC adding this line
1353 write(nftw,'(" NOB0",30I5)') (nob0(ip), ip=1,nsymp)
1354 write(nftw,'(" NOBE",30I5)') (nobe(ip), ip=1,nsymp)
1355 write(nftw,'(" NOBP",30I5)') (nobp(ip), ip=1,nsymp)
1356 write(nftw,'(" NOBV",30I5)') (nobv(ip), ip=1,nsymp)
1357 end if
1358 write(nftw, '(" NSOI",30I5)') (nsoi(ip), ip=1,nsymp)
1359 call space (1)
1360 if (iposit /= 0) then
1361 call addl (1) ! JMC adding this line
1362 write(nftw,'(5X,"POSITRON SCATTERING CASE: IPOSIT =",I3)') iposit
1363 call space (1)
1364 end if
1365
1366 it = 1
1367 if (symtyp == 1) it = 2
1368 do i = 1, nrefop, nitem
1369 imax = min(i + nitem - 1, nrefop)
1370 call addl (6) ! JMC the argument will be too small in some cases (i=1 and symtyp=1)???
1371 if (i == 1) then
1372 write(nftw,'(" REFERENCE DETERMINANT INPUT DATA")')
1373 it = it - 1
1374 end if
1375 write(nftw,'(1X,A4,I5,29I4)') rhead(1), (ip,ip=i,imax)
1376 do ii = 1, 5
1377 write(nftw, '(1X,A4,I5,29I4)') rhead(ii+1), (reforb(ii,ip), ip=i,imax)
1378 end do
1379 if (symtyp == 1) write(nftw, '(1X,A4,I5,29I4)') rhead(7), (refgu(ip), ip=i,imax)
1380 call space (1)
1381 end do
1382 call space (1)
1383 it = (nelp + nitem - 1) / nitem
1384 if (mod(nelp,nitem) == 0) it = it + 1
1385
1386 if (nelp /= 0) then
1387 call addl (it)
1388 write(nftw,'(" REFDET =",30(I3,",")/(9X,30(I3,",")))') (refdet(ip), ip=1,nelp)
1389 end if
1390
1391 ! print D_2h multiplication table
1392 if (symtyp >= 2 .and. npmult /= 0) then
1393 call addl (25)
1394 junk = mprod(1, 1, npmult, nftw)
1395 end if
1396
1397 ! process &state errors
1398 error = .false.
1399 do i = 1, nerfs
1400 if (erfs(i)) then
1401 if (.not. error) then
1402 call space (2)
1403 call addl (2)
1404 write(nftw,'(" **** ERROR DATA FOR &STATE FOLLOWS (&WFNGRP NOT PROCESSED)"/12X,A32)') ersnts(i)
1405 error = .true.
1406 else
1407 call addl (1)
1408 write(nftw,'(12X,A32)') ersnts(i)
1409 end if
1410 end if
1411 end do
1412
1413 end subroutine stwrit
1414
1415
1416 !> \brief Read CSFs from input stream.
1417 !>
1418 subroutine subdel (ndel, ndel1, ndel2, nndel)
1419
1420 use congen_data, only : nftw, nftr
1421
1422 integer :: nndel
1423 integer, dimension(*) :: ndel, ndel1, ndel2 ! JMC changing dimension from 2.
1424 intent (inout) ndel, ndel1, ndel2, nndel
1425
1426 integer :: i, j, k, m, nndel1
1427
1428 read(nftr,'(16I5)') nndel
1429 read(nftr,'(16I5)') (ndel(i), i=1,nndel)
1430
1431 read(nftr,'(16I5)') nndel1
1432
1433 do while (nndel1 /= 0)
1434
1435 read(nftr,'(16I5)') (ndel1(j), j=1,nndel1)
1436
1437 i = 1
1438 j = 1
1439 k = 0
1440
1441 read_loop: do
1442
1443 if (ndel(i) <= ndel1(j)) then
1444 k = k + 1
1445 if (ndel(i) == ndel1(j)) j = j + 1
1446 ndel2(k) = ndel(i)
1447 i = i + 1
1448 if (i > nndel) then
1449 ndel(1:k) = ndel2(1:k)
1450 do m = j, nndel1
1451 k = k + 1
1452 ndel(k) = ndel1(m)
1453 end do
1454 exit read_loop
1455 end if
1456 else
1457 k = k + 1
1458 ndel2(k) = ndel1(j)
1459 j = j + 1
1460 end if
1461
1462 if (j > nndel1) then
1463 do m = i, nndel
1464 k = k + 1
1465 ndel2(k) = ndel(m)
1466 end do
1467 ndel(1:k) = ndel2(1:k)
1468 exit read_loop
1469 end if
1470
1471 end do read_loop
1472
1473 nndel = k
1474 read(nftr,'(16I5)') nndel1
1475
1476 end do
1477
1478 write(nftw,'(" ***** NUMBER OF CHOSEN CONFIGURATIONS ***",I10)') nndel
1479 write(nftw,'(/,24I5)')(ndel(i),i=1,nndel)
1480 write(7,'(16I5)') (ndel(i), i=1,nndel) ! JMC writing to unit 7 (hardwired)???
1481
1482 end subroutine subdel
1483
1484
1485 !> \brief Set defaults for wave function group parameters
1486 !>
1487 subroutine wfnin (nwfngp, nadel, nncsf, ncsf, lcdi, lndi, nelecg, ndprod, nrefog, npcupf, negmax, refdtg, nrfgmx, refgug, &
1488 ntcon, reforg, nshgmx, nsymmx, mshl, gushl, pqn, cup, ndpmax, nshlp, nconmx, test, nrcon, nshcon, tcon, &
1489 errorg)
1490
1491 logical :: errorg
1492 integer :: lcdi, lndi, nadel, nconmx, ncsf, ndpmax, ndprod, negmax, nelecg, nncsf, npcupf, nrefog, nrfgmx, nshgmx, &
1493 nsymmx, ntcon, nwfngp
1494 integer, dimension(3,*) :: cup, pqn
1495 integer, dimension(*) :: gushl, mshl, nrcon, nshcon, nshlp, refdtg, refgug, test
1496 integer, dimension(5,*) :: reforg
1497 integer, dimension(3,nshgmx,*) :: tcon ! JMC the dimensions could be changed to (3,JX,JZ) if desired.
1498 intent (in) nconmx, ndpmax, negmax, nrfgmx, nshgmx, nsymmx
1499 intent (out) cup, errorg, gushl, lcdi, lndi, mshl, nadel, ncsf, ndprod, nelecg, nncsf, npcupf, nrcon, nrefog, nshcon, &
1500 nshlp, ntcon, nwfngp, pqn, refdtg, refgug, reforg, tcon, test
1501
1502 integer :: i, j, k
1503
1504 ! general default for wfngrp arrays
1505
1506 nwfngp = 0
1507 nadel = 1
1508 nncsf = 0
1509 ncsf = 0
1510 lcdi = 0
1511 lndi = 0
1512 ntcon = 0
1513
1514 nelecg = 0
1515 ndprod = 0
1516 nrefog = 0
1517 npcupf = 0
1518
1519 refdtg(1:negmax) = 0
1520 refgug(1:nrfgmx) = -2
1521 reforg(1:5,1:nrfgmx) = -2
1522
1523 mshl(1:nshgmx) = nsymmx + 1
1524 gushl(1:nshgmx) = -2
1525
1526 pqn(1:3,1:nshgmx) = -1
1527 cup(1:3,1:nshgmx) = -1
1528
1529 errorg = .false.
1530
1531 nshlp(1:ndpmax) = 0
1532 test(1:nconmx) = 1
1533 nrcon(1:nconmx) = -1
1534 nshcon(1:nconmx) = 0
1535
1536 tcon(1,1:nshgmx,1:nconmx) = -1
1537 tcon(2,1:nshgmx,1:nconmx) = 0
1538 tcon(3,1:nshgmx,1:nconmx) = 0
1539
1540 end subroutine wfnin
1541
1542
1543 !> \brief Defaults to be reset before every wfngrp
1544 !>
1545 !> This subroutine is called from \ref csfgen before every attempt to read next \c &wfngrp namelist.
1546 !> It erases all previous values to avait new input.
1547 !>
1548 !> \param nelecp Number of electrons per electron set within the wave function group.
1549 !> \param defltc Use of user-specified intermediate coupling.
1550 !> \param nerfg Size of the array \c erfg.
1551 !> \param erfg Array of error condition flags.
1552 !> \param gname Arbitrary namelist text description (max 80 characters).
1553 !> \param qntar Triplet of total quantum numbers for the wave function.
1554 !> \param errorg Error flag (not used).
1555 !> \param ndpmax Size of the array \c nelecp.
1556 !>
1557 subroutine wfnin0 (nelecp, defltc, nerfg, erfg, gname, qntar, errorg, ndpmax)
1558
1559 integer :: defltc, ndpmax, nerfg
1560 logical :: errorg
1561 character(len=80) :: gname
1562 logical, dimension(*) :: erfg
1563 integer, dimension(*) :: nelecp
1564 integer, dimension(3) :: qntar
1565 intent (in) ndpmax, nerfg
1566 intent (out) defltc, erfg, gname, nelecp, qntar
1567
1568 nelecp(1:ndpmax) = -1
1569 erfg(1:nerfg) = .false.
1570
1571 gname = ' '
1572 defltc = 0
1573
1574 qntar(1) = -1
1575 qntar(2) = 0
1576 qntar(3) = 0
1577
1578 end subroutine wfnin0
1579
1580
1581 !> \brief Final text information output.
1582 !>
1583 subroutine wrnmlt (k, sname, nrerun, megul, symtyp, mgvn, s, sz, r, pin, ncsf, byproj, lcdi, lndi, lcdo, lndo, lcdt, lndt, &
1584 nfto, ltri, idiag, npflg, thres, nelect, nsym, nob, refdet, nftw, iposit, nob0, nobl, nob0l, nx, nobe, &
1585 nobp, nobv)
1586
1587 use precisn, only : wp
1588
1589 integer :: byproj, idiag, iposit, k, lcdi, lcdo, lcdt, lndi, lndo, lndt, ltri, megul, mgvn, ncsf, nelect, nfto, nftw, &
1590 nrerun, nsym, nx, symtyp
1591 real(kind=wp) :: pin, r, s, sz, thres
1592 character(len=80) :: sname
1593 integer, dimension(*) :: nob, nob0, refdet
1594 integer, dimension(nx) :: nob0l, nobl
1595 integer, dimension(nx) :: nobe, nobp, nobv
1596 integer, dimension(6) :: npflg
1597 intent (in) byproj, idiag, iposit, k, lcdi, lcdo, lcdt, lndi, lndo, lndt, ltri, megul, mgvn, ncsf, nelect, nfto, &
1598 nob, nob0, nob0l, nobe, nobl, nobp, nobv, npflg, nrerun, nsym, nx, pin, r, refdet, s, sname, symtyp, &
1599 sz, thres
1600
1601 character(len=4) :: blank1 = ' '
1602 integer :: j
1603
1604 write(k,'(" &INPUT")')
1605 write(k,'(" NAME=''",A80,"'',")') sname
1606 write(k,'(" NRERUN=",I3,", MEGUL=",I3,", SYMTYP=",I3,",")') nrerun, megul, symtyp
1607 write(k,'(" MGVN=",I3,", S=",F6.1,",SZ=",F6.1,", R=",F6.1,", PIN=",F6.1,", NOCSF=",I6,",")') mgvn, s, sz, r, pin, ncsf
1608 write(k,'(" BYPROJ=",I2,",")') byproj
1609 write(k,'(" LCDI=",I15,", LNDI=",I15,", LCDO=",I7,", LNDO=",I15,","," LCDT=",I7,", LNDT=",I7,",")') &
1610 lcdi, lndi, lcdo, lndo, lcdt, lndt
1611 write(k,'(" NFTO=",I3,", LTRI=",I5,", IDIAG=",I3,", NPFLG=",5(I2,",")," NPMSPD =",I2,",")') nfto, ltri, idiag, npflg
1612 write(k,'(" THRES=",1PD9.2,",")') thres
1613 write(k,'(" NELT=",I4,", NSYM=",I3,", NOB=",10(1x,I0,","))') nelect, nsym, (nob(j), j=1,nsym)
1614 write(k,'(" NDTRF=",12(1x,I0,",")/(8X,12(1x,I0,",")))') (refdet(j), j=1,nelect)
1615 write(k,'(" NOBL=",10(1x,I0,","))') nobl
1616 write(k,'(" NOB0L=",10(1x,I0,","))') nob0l
1617
1618 if (iposit /= 0) then
1619 write(k,'(" IPOSIT=",I3)') iposit
1620 write(k,'(" NOB0=",10(1x,I0,","))') (nob0(j), j=1,nsym)
1621 write(k,'(" NOBE=",10(1x,I0,","))') (nobe(j), j=1,nsym)
1622 write(k,'(" NOBP=",10(1x,I0,","))') (nobp(j), j=1,nsym)
1623 write(k,'(" NOBV=",10(1x,I0,","))') (nobv(j), j=1,nsym)
1624 end if
1625 write(k,'(" /")')
1626
1627 end subroutine wrnmlt
1628
1629
1630 !> \brief Display information about the wave function group
1631 !>
1632 subroutine wvwrit (nwfngp, gname, nelecg, defltc, irfcon, ndprod, symtyp, ntcon, navail, nrefog, nelecp, nshlp, qntar, &
1633 nshlpt, nshgmx, mshl, gushl, pqn, cup, ncupp, npcupf, refdtg, nelp, ntconp, nshcon, nobt, reforb, &
1634 refgu, test, nrcon, tcon, refcon, nerfg, erfg, ndpp, nrefop, lsquare, errorg)
1635
1636 use congen_data, only : nftw, rhead
1637 use congen_pagecontrol, only : addl, newpg, space
1638
1639 integer :: defltc, irfcon, navail, ncupp, ndpp, ndprod, nelecg, nelp, nerfg, nobt, npcupf, nrefog, nrefop, &
1640 nshgmx, nshlpt, ntcon, ntconp, nwfngp, symtyp, lsquare
1641 logical :: errorg
1642 character(len=80) :: gname
1643 integer, dimension(3,*) :: cup, pqn
1644 logical, dimension(11) :: erfg
1645 integer, dimension(*) :: gushl, mshl, nelecp, nrcon, nshcon, nshlp, refcon, refdtg, refgu, test
1646 ! change refcon from integer to couble for consistency
1647 ! double precision refcon(*) ! jmc the correponding actual arg is d.p. ???
1648 integer, dimension(3) :: qntar
1649 integer, dimension(5,*) :: reforb
1650 integer, dimension(3,nshgmx,*) :: tcon ! jmc changing the 2nd dimension from LG to NSHGMX for consistency with elsewhere.
1651 ! The dimensions could also be changed to (3,JX,JZ) if desired.
1652 intent (in) cup, defltc, erfg, gname, gushl, irfcon, mshl, navail, ncupp, ndpp, ndprod, nelecg, nelecp, nelp, &
1653 nerfg, nobt, npcupf, nrcon, nrefog, nrefop, nshcon, nshgmx, nshlp, nshlpt, ntcon, ntconp, nwfngp, pqn, &
1654 qntar, refcon, refdtg, refgu, reforb, symtyp, tcon, lsquare
1655 intent (inout) errorg, test
1656
1657 character(len=32), dimension(11) :: ersntg
1658 character(len=4) :: hcup = 'CUP ', htcon = 'TCON', lpc = ' ( '
1659 integer :: i, i1, i2, ic, ii, iimax, imax, ip, ishp, it, jj, jnshl, nshcr, nit1 = 10, nit2 = 30
1660
1661 data ersntg/'NELECG OUT OF RANGE ', &
1662 'NDPROD TOO LARGE ', &
1663 'NSHLP OUT OF RANGE ', &
1664 'NELECG NE SUM OF NELEP ', &
1665 'NREF OUT OF RANGE ', &
1666 'NELECG NE SUM OVER NELEC IN REFO', &
1667 'ERROR IN REF ORB DATA ', &
1668 'ERROR IN SHELL DATA ', &
1669 'ERROR IN COUPLING DATA ', &
1670 'ERROR IN CONFIG CONSTRAINT DATA ', &
1671 'NO SPACE FOR REFCON ARRAY '/
1672
1673 ! print wfngrp input data
1674 call newpg
1675 call addl (9)
1676 write(nftw,'(" WFN GROUP",I4,4X,A80)') nwfngp, gname
1677 write(nftw,'(" NELECG",I4,T15,"DEFLTC",I3,T27,"IRFCON",I6)') nelecg, defltc, irfcon
1678 write(nftw,'(" NDPROD",I4,T15,"NTCON ",I3,T27,"NAV ",I10)') ndprod, ntcon, navail
1679 write(nftw,'(" LSQUARE",I3)') lsquare
1680 write(nftw,'(" NREFOG",I4,/)') nrefog
1681 write(nftw,'(9X,9I3)') (i, i=1,ndpp)
1682 write(nftw,'(" NELECP =",9I3)') (nelecp(i), i=1,ndpp)
1683 write(nftw,'(" NSHLP =",9I3)') (nshlp(i), i=1,ndpp)
1684
1685 if (qntar(1) /= -1) then
1686 call addl (1)
1687 write(nftw,'(5X,"TARGET MULTIPLICITY =",I5,5X,"TARGET SYMMETRY =",I5,5X,"TARGET INVERSION SYMMETRY =",I5)') &
1688 (qntar(i), i=1,3)
1689 end if
1690
1691 call space (1)
1692
1693 if (ndprod /= 0 .and. nshlpt <= nshgmx) then
1694
1695 it = merge(1, 0, symtyp == 1)
1696 ishp = 0
1697
1698 do ip = 1, ndprod
1699 jnshl = nshlp(ip)
1700 if (jnshl == 0) then
1701 call addl (1)
1702 write(nftw,'(I4," ORBITALS IN GROUP",I2)') jnshl, ip
1703 call space (2)
1704 end if
1705 do i = 1, jnshl, nit1
1706 imax = min(i + nit1 - 1, jnshl)
1707 if (i == 1) then
1708 call addl (4 + it)
1709 write(nftw,'(I4," ORBITALS IN GROUP",I2)') jnshl, ip
1710 else
1711 call addl (3 + it)
1712 end if
1713 write(nftw,'(1X,A4,I8,9I12)') rhead(1), (ii, ii=i,imax)
1714 write(nftw, '(1X,A4,I8,9I12)') rhead(2), (mshl(ishp+ii), ii=i,imax)
1715 if (symtyp == 1) write(nftw,'(1X,A4,I8,9I12)') rhead(7), (gushl(ishp+ii), ii=i,imax)
1716 write(nftw,'(1X,A4,10(A3,I2,",",I2,",",I2,")"))') rhead(3), (lpc,(pqn(jj,ishp+ii), jj=1,3), ii=i,imax)
1717 call space (1)
1718 end do
1719 ishp = ishp + jnshl
1720 end do
1721
1722 call space (1)
1723
1724 if (ncupp * npcupf /= 0) then
1725 do i = 1, ncupp, nit1
1726 imax = min(i + nit1 - 1, ncupp)
1727 i1 = i + nshlpt
1728 i2 = imax + nshlpt
1729 if (i == 1) then
1730 call addl (3)
1731 write(nftw,'(" COUPLING DATA")')
1732 else
1733 call addl (2)
1734 end if
1735 write(nftw,'(1X,A4,I8,9I12)') rhead(1), (ii, ii=i1,i2)
1736 write(nftw, '(1X,A4,10(A3,I2,",",I2,",",I2,")"))') hcup, (lpc,(cup(jj,ii), jj=1,3), ii=i,imax)
1737 call space (1)
1738 end do
1739 end if
1740
1741 it = merge(2, 1, symtyp == 1)
1742
1743 do i = 1, nrefop, nit2
1744 imax = min(i + nit2 - 1, nrefop)
1745 call addl (6 + it)
1746 if (i == 1) then
1747 write(nftw,'(" REFERENCE DETERMINANT INPUT DATA")')
1748 it = it - 1
1749 end if
1750 write(nftw, '(1X,A4,I5,29I4)') rhead(1), (ip, ip=i,imax)
1751 do ii = 1, 5
1752 write(nftw, '(1X,A4,I5,29I4)') rhead(ii+1), (reforb(ii,ip), ip=i,imax)
1753 end do
1754 if (symtyp == 1) write(nftw, '(1X,A4,I5,29I4)') rhead(7), (refgu(ip), ip=i,imax)
1755 call space (1)
1756 end do
1757
1758 call space (1)
1759
1760 it = (nelp + nit2 - 1) / nit2
1761 if (mod(nelp, nit2) == 0) it = it + 1
1762 if (nelp /= 0) then
1763 call addl (it)
1764 write(nftw,'(" REFDET =",30(I3,","),/,(9X,30(I3,",")))') (refdtg(ip), ip=1,nelp)
1765 end if
1766
1767 call space (1)
1768
1769 do ic = 1, ntconp
1770 nshcr = nshcon(ic)
1771 it = 1 + 2 * ((nshcr + nit1 - 1) / nit1) + 1 + (nobt + nit2 - 1) / nit2 ! jmc one too many here???
1772 if (mod(nobt, nit2) == 0) it = it + 1
1773 if (ic == 1) then
1774 call addl (2 + it)
1775 write(nftw,'(" EXITATION CONSTRAINTS / TCON(SYM,PQN,NE",/)')
1776 else
1777 call addl(it)
1778 end if
1779 if (test(ic) /= 1) then
1780 write(nftw,'(I3,10X,"GT",I3," REPLACEMENTS ALLOWED(INTERSECTION)")') ic, nrcon(ic)
1781 test(ic) = 0
1782 else
1783 write(nftw,'(I3,10X,"LE",I3," REPLACEMENTS ALLOWED(UNION)")') ic, nrcon(ic)
1784 end if
1785 if (nshcr /= 0) then
1786 do ii = 1, nshcr, nit1
1787 iimax = min(ii + nit1 - 1, nshcr)
1788 write(nftw,'(1X,A4,I8,9I12)') rhead(1), (ip, ip=ii,iimax)
1789 write(nftw,'(1X,A4,10(A3,I2,",",I2,",",I2,")"))') htcon, (lpc,(tcon(jj,ip,ic), jj=1,3), ip=ii,iimax)
1790 end do
1791 call space (1)
1792 write(nftw,'(" REFCON =",30(I3,",")/(9X,30(I3,",")))') (refcon(ip), ip=1,nobt)
1793 end if
1794 call space (1)
1795 end do
1796
1797 end if
1798
1799 ! print wfngrp error messages
1800
1801 do i = 1, nerfg
1802 if (.not. erfg(i)) cycle
1803 if (.not. errorg) then
1804 call space (2)
1805 call addl (2)
1806 write(nftw,'(" **** ERROR DATA FOR &WFNGRP FOLLOWS",/,12X,A32)') ersntg(i)
1807 errorg = .true.
1808 cycle
1809 end if
1810 call addl (1)
1811 write(nftw,'(12X,A32)') ersntg(i)
1812 end do
1813
1814 end subroutine wvwrit
1815
1816end module congen_driver
Module containing parameters / data required throughout the CONGEN program.
integer ndel
Workspace position used for the CSFs read from input.
integer nobt
Total number of all orbitals considered in the calculation, essentially equal to sum(nob).
integer, dimension(nu) shlmx1
Maximal occupancy of orbitals per symmetry.
integer lndi
Total number of integers forming packed determinants.
integer, dimension(jz) test
Determines which of the two types of constraints will be used.
integer, parameter jsmax
Maximal order of precomputed binomial coefficients.
integer, parameter nz
Used to dimension REFDET in congen_driver::csfgen; maximum number of electrons.
integer icdi
Position in workspace where the determinant coefficients start (one coeff per one determinant).
integer, dimension(lg) gushl
Gerade/ungerade per shell.
integer, parameter nftr
Unit number for reading standard input.
integer, parameter kz
Used to dimension REFDTG in csfgen; limit on input variable NELECG?
integer gutot
Total gerade (= +1) / ungerade (= -1) quantum number.
integer iqnstr
Starting position in workspace for per-shell quantum numbers (e.g. congen_distribution::cplem).
integer indi
Position in workspace where packed determinants start (each as size + replacements).
real(kind=wp), dimension((jsmax *jsmax+3 *jsmax+4)/2) binom
Table of precomputed Pascal triangle.
integer, parameter ny
Used to dimension REFGU and REFORB in csfgen. Limit on input variable NREFO.
integer nisz
Total S_z, set by CSFGEN, defaults to first element of qntot.
character(len=1), dimension(132) head
String with output page number and user-specific header text.
integer ndel1
Workspace position used for reading CSFs from the input.
integer megul
File unit for binary output of generated configurations.
integer ntso
Total number of spin-orbitals, given the orbitals and their maximal occupacy (from group properties).
integer, parameter nitem
Number of interesting things printed per line in the PRINT* routines.
integer, dimension(:), allocatable exref
Population of spin-orbitals (0 = not populated, 1 = populated).
integer, parameter jz
Maximum number of constraints upon CSFs accepted (limit on input variable NTCON).
integer, dimension(3) qntot
Total quantum numbers.
integer, dimension(jz) nrcon
integer nndel
Number of workspace elements used for reservation of space needed when reading CSFs from input.
integer, dimension(jsmax+2) ind
Pascal triangle row pointers into congen_data::binom.
integer, dimension(:), allocatable exdet
integer confpf
Print flag for the amount of print given of configurations and prototypes.
integer nnlecg
The total number of electrons which are movable within the current wfn group.
integer, dimension(nu) nsoi
Running index of the first spin-orbital within given total symmetry.
integer, parameter jy
Used to dimension various arrays in csfgen including NELECP and NSHLP. Limit on input variable NDPROD...
integer ift
Used to signal to congen_distribution::assign to initialize some variables.
integer nncsf
Number of CSFs generated by congen_distribution::wfn (total).
integer ndel2
Workspace position used for reading CSFs from the input.
integer, parameter nu
Maximal number of irreducible representation (= max dimension of NOB etc.).
integer, dimension(3, lg) pqnst
integer, dimension(nu) nobi
Running index of the first orbital in each symmetry.
integer, parameter mxtarg
Maximum number of target state symmetries.
integer lratio
Ratio of real size to integer size. Used to manage workspace data.
integer cdimx
Maximal number of determinants.
integer nid
Length of the integer array containing all packed determinants.
integer ndimx
Maximal number of workspace elements usable for packed determinant data.
integer nsym
Number of symmetries given in input file (right-trimmed of those with zero orbitals).
integer ncall
Used to signal to "wfn" to initialize some variables.
integer iexcon
Position in workspace where EX constraints start.
integer lcdi
Total number of determinants (including those already flushed to disk).
integer irfcon
integer, dimension(3, lg) cup
Coupling scheme data. ???
integer, parameter ky
Used to dimension REFGUG and REFORG in congen_driver::csfgen. Limit on input variable NREFOG?
integer ncsf
Total number of CSFs generated.
integer nftw
Unit number for printing; may be changed via the STATE namelist so not a parameter.
integer next
Position in the workspace indicating the first unused element.
integer, parameter jx
Used to dimension many arrays in congen_driver::csfgen; limit on the sum of elements in the NSHLP arr...
integer noi
Number of determinants per CSF.
character(len=4), dimension(7), parameter rhead
integer nx
Full or remaining workspace size (depending on context).
integer, dimension(lg) mshl
Symmetry number from zero to n-1 (mvalue).
integer, dimension(3) qntar
Coupling control for current wfn group. ???
integer nodimx
Maximal number of workspace elements usable for CSF information.
integer ni
Number of determinants currently in memory.
integer, dimension(lg) sshlst
integer inodi
Position in workspace where CSFs start (as number of determinants per CSF).
integer symtyp
Symmetry type, 0 = C_infv, 1 = D_infh, 2 = {D_2h, C_2v, C_s, E}.
integer, dimension(lg) occshl
Compressed shell occupations, all zeros deleted and pseudo shells expanded.
Distribute electrons to available orbitals.
subroutine, public distrb(nelecp, nshlp, shlmx, occshl, nslsv, kdssv, loopf, ksss, pqn, occst, shlmx1, pqnst, mshl, mshlst, gushl, gushst, cup, cupst, ndprod, symtyp, confpf, sshl, sshlst, ncsf, nncsf, nadel, nndel, x, nftw, noex)
Distribute electrons to spin-orbitals.
subroutine, private state(ns, x, last, nd, confpf)
?
Main CONGEN subroutines.
subroutine, private getref(reforb, refgu, nrefo, nelec, refdet, nelr, nsoi, nob, shlmx, nsym, symtyp, nrfomx, e1, e2, e3)
Form reference list of spin-orbital numbers.
subroutine, private icgcf
Precomputes needed binomial coefficients.
subroutine, private csfout(ia, ib, megul, nndel, cr, nr)
Store the wave function to file and reset arrays.
subroutine, public csfgen
Central CONGEN subroutine.
subroutine, private wrnmlt(k, sname, nrerun, megul, symtyp, mgvn, s, sz, r, pin, ncsf, byproj, lcdi, lndi, lcdo, lndo, lcdt, lndt, nfto, ltri, idiag, npflg, thres, nelect, nsym, nob, refdet, nftw, iposit, nob0, nobl, nob0l, nx, nobe, nobp, nobv)
Final text information output.
subroutine, private wfnin0(nelecp, defltc, nerfg, erfg, gname, qntar, errorg, ndpmax)
Defaults to be reset before every wfngrp.
subroutine, private getcon(ntcon, nshcon, nrcon, nshgmx, npmax, nc, nelecg, nsym, nobt, nob, nobi, nsoi, shlmx1, exref, tcon, refcon, error)
Check tcon data and form refcon array.
subroutine wfngrp_sanity_check(nftw, nob, ndprod, nelecp, nshlp, pqn, mshl)
Check electron distribution.
subroutine, private stwrit(nelect, confpf, qntot, cdimx, icdi, ntso, symtyp, ndimx, indi, nrefo, nodimx, inodi, nsym, gutot, nbmx, isz, navail, idiag, megu, thres, lcdt, megul, lndt, nfto, nrerun, ltri, npflg, nndel, nob, nsoi, nsymp, refdet, nerfs, erfs, nrefop, reforb, refgu, nelp, lpp, sname, error, byproj, lndo, lcdo, iposit, nob0, npmult, ntgsym, mxtarg, nobe, nobp, nobv)
Write information obtained from &state.
subroutine, private getcup(nshlt, def, nd, nshlp, cup, error)
Set up coupling scheme.
subroutine, private subdel(ndel, ndel1, ndel2, nndel)
Read CSFs from input stream.
subroutine, private wvwrit(nwfngp, gname, nelecg, defltc, irfcon, ndprod, symtyp, ntcon, navail, nrefog, nelecp, nshlp, qntar, nshlpt, nshgmx, mshl, gushl, pqn, cup, ncupp, npcupf, refdtg, nelp, ntconp, nshcon, nobt, reforb, refgu, test, nrcon, tcon, refcon, nerfg, erfg, ndpp, nrefop, lsquare, errorg)
Display information about the wave function group.
subroutine, private wfnin(nwfngp, nadel, nncsf, ncsf, lcdi, lndi, nelecg, ndprod, nrefog, npcupf, negmax, refdtg, nrfgmx, refgug, ntcon, reforg, nshgmx, nsymmx, mshl, gushl, pqn, cup, ndpmax, nshlp, nconmx, test, nrcon, nshcon, tcon, errorg)
Set defaults for wave function group parameters.
subroutine, public ctlpg1(lpp, h1, nh1, h2, nh2)
Controls page layout and counting.
subroutine, public newpg
Start new page of output.
subroutine, public space(lines)
Add blank lines to output.
subroutine, public addl(lines)
Add blank lines to output.
Projection on spin states.
subroutine, public projec(sname, megul, symtyp, mgvn, s, sz, r, pin, nocsf, byproj, idiag, npflg, thres, nelt, nsym, nob, ndtrf, nftw, iposit, nob0, nob1, nob01, iscat, ntgsym, notgt, nctgt, mcont, gucont, mrkorb, mdegen, mflag, nobe, nobp, nobv, maxtgsym)
Project the wave function.