MPI-SCATCI  2.0
An MPI version of SCATCI
MOLPROCorePotential_module.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 
31 
32  use precisn, only: wp
33  use const, only: stdout
35  use input
36  use mpi_mod, only: myrank
37 
38  implicit none
39 
40  integer, parameter :: max_molpro_energies = 3
41  character(len=*), parameter :: molpro_energy_line = 'TOTAL ENERGIES'
42  character(len=*), parameter :: molpro_nuclear = 'NUCLEAR REPULSION ENERGY'
43  character(len=*), parameter :: molpro_rhf_energy_line ='HF-SCF'
44 
46  integer, allocatable :: molpro_symmetry_map(:)
47  real(wp) :: nuclear_energy
48  contains
49  procedure, public :: parse_ecp => parse_molpro_casscf_energies
50  procedure, public :: parse_input => parse_molpro_input
51  procedure, public :: modify_target_energies => molpro_energies
52  procedure, private :: search_state_energy
53  procedure, private :: search_rhf_state_energy
54  procedure, private :: read_state_energy
55  procedure, private :: search_core_energy
56  procedure, private :: detect_symmetry_ordering
57  end type
58 
59 contains
60 
70  subroutine parse_molpro_casscf_energies (this, filename)
71  class(molprocorepotential) :: this
72  character(len=*) :: filename
73 
74  integer :: targ_sym_do,current_target_sym
75  integer :: targ_stat_do,err
76  integer :: io
77  real(wp) :: energy_val
78  logical :: eof
79  logical :: success
80  integer :: actual_targ_sym
81 
82  io = find_io(1) + myrank
83 
84  open (io, action = 'read', status = 'old', file = filename, iostat = err)
85 
86  if (err /= 0) then
87  write (stdout, "('Error opening input file ',a)") filename
88  stop "Could not open input file"
89  end if
90 
91  success = this % search_core_energy(io)
92 
93  if (success == .false.) then
94  stop "Could not find core energy in molpro"
95  end if
96 
97  !success = this%detect_symmetry_ordering(io)
98  !if(success ==.false.) then
99  ! stop "Could not assign MOLPRO symmetries to SCATCI targets"
100  !endif
101 
102  eof = this % search_rhf_state_energy(io, 1, 1, this % target_energies(:,1))
103  if (.not. eof) stop "Could not find HF energy"
104  !do targ_sym_do=1,this%num_target_sym
105  ! ! current_target_sym = current_target_sym + 1
106  ! !do targ_stat_do=1,this%num_target_per_symmetries(targ_sym_do)
107  ! actual_targ_sym = this%molpro_symmetry_map(targ_sym_do)
108  ! !energy_line = '!MCSCF STATE 1.1 Energy'
109  !eof = this%search_state_energy(io,targ_sym_do,this%num_target_per_symmetries(targ_sym_do),this%target_energies(:,actual_targ_sym))
110  ! !length = len(trim(energy_line))
111  !
112  ! if(eof == .false.) then
113  ! ! write(stdout,"(a,2x,f)") energy_line
114  ! ! enddo
115  !enddo
116 
117  close (io)
118 
119  this % target_energies(:,:) = this % target_energies(:,:) - this % nuclear_energy
120 
121  end subroutine parse_molpro_casscf_energies
122 
123 
130  subroutine parse_molpro_input(this)
131  class(molprocorepotential) :: this
132  end subroutine parse_molpro_input
133 
134 
135  subroutine molpro_energies (this, target_sym, target_energy)
136  class(molprocorepotential) :: this
137  integer, intent(in) :: target_sym
138  real(wp) :: target_energy(:)
139  integer :: num_states
140 
141  num_states = this % num_target_per_symmetries(target_sym)
142 
143  if (target_sym == 1) then
144  this % ground_energy = target_energy(1)
145  !this%L2_ECP_deficit = (this%target_energies(1,1) - target_energy(1))
146  this % L2_ECP_deficit = 0.1
147  print *, 'ground_energy ',this % ground_energy
148  print *, 'target_ECP_energy ',this % target_energies(1,1)
149  print *, 'L2 diff ', this % L2_ECP_deficit
150  end if
151  !target_energy(1:num_states) =target_energy(1:num_states) + 0.455207
152  !find deficieny
153  !target_energy(1:num_states) =target_energy(1:num_states) + this%target_energies(1,1)
154  end subroutine molpro_energies
155 
156 
157  logical function search_state_energy (this, io, target_sym, number_of_energies, target_energy)
158  class(molprocorepotential) :: this
159  integer, intent(in) :: io, target_sym,number_of_energies
160  real(wp), intent(out) :: target_energy(:)
161  integer :: reason
162  character(len=line_len) :: buffer
163  character(len=line_len) :: header_line
164  character(len=4) :: sym_char, stat_char
165 
166  search_state_energy = .true.
167 
168  write (sym_char, '(i4)') target_sym
169 
170  !CI vector for state symmetry 1
171  !header_line = '!MCSCF STATE '//trim(adjustl(stat_char))//'.'//trim(adjustl(sym_char))//' Energy'
172 
173  header_line = 'CI vector for state symmetry ' // trim(adjustl(sym_char))
174 
175  do while (.true.)
176  read (io, '(a)', iostat = reason) buffer
177  !write(stdout,"(a)") trim(buffer(2:line_len))
178  !write(stdout,"(a)") trim(header_line)
179  if (reason == 0) then
180  if (trim(buffer(2:line_len)) == trim(header_line)) then
181  search_state_energy = this % read_state_energy(io, number_of_energies, target_energy)
182  !write(stdout,*) buffer
183  return
184  end if
185  else
186  search_state_energy = .false.
187  exit
188  end if
189  end do
190  end function search_state_energy
191 
192 
193  logical function search_rhf_state_energy (this, io, target_sym, number_of_energies, target_energy)
194  class(molprocorepotential) :: this
195  integer, intent(in) :: io, target_sym,number_of_energies
196  real(wp), intent(out) :: target_energy(:)
197  integer :: reason
198  character(len=line_len) :: buffer
199  character(len=line_len) :: header_line
200  character(len=4) :: sym_char, stat_char
201 
202  search_rhf_state_energy = .true.
203 
204  !write( sym_char, '(i4)') target_sym
205  !CI vector for state symmetry 1
206  !header_line = '!MCSCF STATE '//trim(adjustl(stat_char))//'.'//trim(adjustl(sym_char))//' Energy'
207  !header_line = 'CI vector for state symmetry '//trim(adjustl(sym_char))
208 
209  do while (.true.)
210  read (io, '(a)', iostat = reason) buffer
211  write (stdout, '(a)') trim(buffer(1:line_len))
212  !write(stdout,"(a)") trim(header_line)
213  if (reason == 0) then
214  if (trim(buffer(9:14)) == trim(molpro_rhf_energy_line)) then
215  read (io, '(a)', iostat = reason) buffer
216  call parse(buffer)
217  call readf(target_energy(1))
218  write (stdout, *) buffer
219  return
220  end if
221  else
222  search_rhf_state_energy = .false.
223  exit
224  end if
225  end do
226  end function search_rhf_state_energy
227 
228 
229  logical function read_state_energy (this, io, number_of_energies, target_energy)
230  class(molprocorepotential) :: this
231  integer, intent(in) :: io, number_of_energies
232  real(wp), intent(out) :: target_energy(:)
233  character(len=line_len) :: header_line
234  integer :: num_found_energies, total_energies_line, curr_en, reason
235  character(len=line_len) :: buffer
236  character(len=line_len) :: fields
237 
238  num_found_energies = 0
239 
240  do while (.true.)
241  read (io, '(a)', iostat = reason) buffer
242  if (reason == 0) then
243  if (trim(buffer(2:len(molpro_energy_line)+1)) == trim(molpro_energy_line)) then
244  call parse(buffer)
245  total_energies_line = nitems - 2
246  !write(stdout,*) total_energies_line
247  call readu(fields)
248  call readu(fields)
249  num_found_energies = 0
250  do while (total_energies_line > 0)
251  num_found_energies = num_found_energies + 1
252 
253  if (num_found_energies > number_of_energies) exit
254 
255  call readf(target_energy(num_found_energies))
256  !write(stdout,"(f12.6)") target_energy(num_found_energies)
257  total_energies_line = total_energies_line - 1
258 
259  if (total_energies_line == 0) then
260  read (io, '(a)', iostat = reason) buffer
261  call parse(buffer)
262  if (nitems == 0) exit
263  total_energies_line = nitems - 2
264  end if
265  end do
266  read_state_energy = .true.
267  return
268  end if
269  else
270  read_state_energy = .false.
271  return
272  end if
273  end do
274 
275  end function read_state_energy
276 
277 
278  logical function search_core_energy (this, io)
279  class(molprocorepotential) :: this
280  integer, intent(in) :: io
281  integer :: reason
282  character(len=line_len) :: buffer
283  character(len=line_len) :: fields
284 
285  do while(.true.)
286  read (io, '(a)', iostat = reason) buffer
287  !write(stdout,"(a)") trim(buffer(2:line_len))
288  !write(stdout,"(a)") trim(header_line)
289  if (reason == 0) then
290  if (trim(buffer(2:len(molpro_nuclear) + 1)) == trim(molpro_nuclear)) then
291  call parse(buffer)
292  call readu(fields)
293  call readu(fields)
294  call readu(fields)
295  call readf(this % nuclear_energy)
296  !write(stdout,"(f12.6)") this%nuclear_energy
297 
298  search_core_energy = .true.
299 
300  return
301  end if
302  else
303  search_core_energy = .false.
304  exit
305  end if
306  end do
307 
308  end function search_core_energy
309 
310 
311  logical function detect_symmetry_ordering (this, io)
312  class(molprocorepotential) :: this
313  integer, intent(in) :: io
314  integer :: reason
315  character(len=line_len) :: buffer
316  character(len=line_len) :: fields
317  character(len=line_len) :: header_line
318  character(len=4) :: sym_char
319  integer :: target_sym, ido
320  integer :: detected_space, detected_spin
321 
322  allocate(this % molpro_symmetry_map(this % num_target_sym))
323 
324  do target_sym = 1, this % num_target_sym
325 
326  write (sym_char, '(i4)') target_sym
327  header_line = 'State symmetry ' // trim(adjustl(sym_char))
328 
329  do while (.true.)
330 
331  read (io, '(a)', iostat = reason) buffer
332 
333  if (reason == 0) then
334  if (trim(buffer(2:line_len)) == trim(header_line)) then
335  !Empty_line
336  read(io,'(a)',iostat=reason) buffer
337  !Info
338  read(io,'(a)',iostat=reason) buffer
339 
340  do ido = 1, len(buffer)
341  if (buffer(ido:ido) == "=") buffer(ido:ido) = " "
342  end do
343 
344  call parse(buffer)
345  !write(stdout,*) buffer
346  !Number
347  call readu(fields)
348  !of
349  call readu(fields)
350  !electrons
351  call readu(fields)
352  !#
353  call readu(fields)
354 
355  call readu(fields)
356 
357  if (trim(fields) == 'SPIN') then
358  call readu(fields)
359  call readu(fields)
360  select case(trim(fields))
361  case('SINGLET')
362  detected_spin = 1
363  case('DOUBLET')
364  detected_spin = 2
365  case('TRIPLET')
366  detected_spin = 3
367  case default
368  write (stdout, *) fields
369  stop "Invalid MOLPRO input on spin symmetry"
370  end select
371  else
372  write (stdout, *) fields
373  stop "Invalid MOLPRO input on spin expected first"
374  end if
375  call readu(fields)
376  if (trim(fields) == 'SPACE') then
377  call readu(fields)
378  call readi(detected_space)
379  else
380  write (stdout, *) fields
381  stop "Invalid MOLPRO input on space expected second"
382  end if
383 
384  do ido = 1, this % num_target_sym
385  if (this % spatial_symmetry(ido) + 1 == detected_space .and. &
386  this % spin_symmetry(ido) == detected_spin) then
387  this % molpro_symmetry_map(target_sym) = ido
388  exit
389  else if (ido == this % num_target_sym) then
390  write (stdout, *) 'Could not find molpro symmetry mapping of Spatial=', &
391  detected_space, ' and Spin=', detected_spin
392  stop "Invalid molpro space spin assignment"
393  end if
394  end do
395 
396  exit
397  end if
398  else
399  detect_symmetry_ordering = .false.
400  return
401  end if
402  end do
403  end do
404 
405  detect_symmetry_ordering = .true.
406 
407  write (stdout, *) ' '
408  write (stdout, *) '---------------------------------'
409  write (stdout, *) 'MOLPRO -> SCATCI symmetry mapping'
410  write (stdout, *) '---------------------------------'
411  write (stdout, *) ' '
412 
413  do ido = 1, this % num_target_sym
414  write (stdout, *) ido, '----->', this % molpro_symmetry_map(ido)
415  end do
416 
417  end function detect_symmetry_ordering
418 
molprocorepotential_module::search_core_energy
logical function search_core_energy(this, io)
Definition: MOLPROCorePotential_module.f90:279
molprocorepotential_module::molpro_energy_line
character(len= *), parameter molpro_energy_line
Definition: MOLPROCorePotential_module.f90:41
molprocorepotential_module::molpro_energies
subroutine molpro_energies(this, target_sym, target_energy)
Definition: MOLPROCorePotential_module.f90:136
basecorepotential_module::basecorepotential
Definition: BaseCorePotential_module.f90:36
molprocorepotential_module::max_molpro_energies
integer, parameter max_molpro_energies
Definition: MOLPROCorePotential_module.f90:40
molprocorepotential_module::molpro_nuclear
character(len= *), parameter molpro_nuclear
Definition: MOLPROCorePotential_module.f90:42
molprocorepotential_module::search_rhf_state_energy
logical function search_rhf_state_energy(this, io, target_sym, number_of_energies, target_energy)
Definition: MOLPROCorePotential_module.f90:194
molprocorepotential_module::molprocorepotential
Definition: MOLPROCorePotential_module.f90:45
molprocorepotential_module::molpro_rhf_energy_line
character(len= *), parameter molpro_rhf_energy_line
Definition: MOLPROCorePotential_module.f90:43
molprocorepotential_module::read_state_energy
logical function read_state_energy(this, io, number_of_energies, target_energy)
Definition: MOLPROCorePotential_module.f90:230
basecorepotential_module
Base type for core potentials.
Definition: BaseCorePotential_module.f90:30
molprocorepotential_module::parse_molpro_casscf_energies
subroutine parse_molpro_casscf_energies(this, filename)
Main build routine of the hamiltonian.
Definition: MOLPROCorePotential_module.f90:71
molprocorepotential_module::detect_symmetry_ordering
logical function detect_symmetry_ordering(this, io)
Definition: MOLPROCorePotential_module.f90:312
molprocorepotential_module
MOLPRO core potentials.
Definition: MOLPROCorePotential_module.f90:30
molprocorepotential_module::search_state_energy
logical function search_state_energy(this, io, target_sym, number_of_energies, target_energy)
Definition: MOLPROCorePotential_module.f90:158
molprocorepotential_module::parse_molpro_input
subroutine parse_molpro_input(this)
Main build routine of the hamiltonian.
Definition: MOLPROCorePotential_module.f90:131