Skip to content

Commit 825f571

Browse files
Store dimensions of orbital matrix and CI vectors in Checkpoint.txt (#54)
Previously, the Checkpoint.txt would dump the vectors only, meaning that OpenFMS must know upon restart what the lengths of these vectors are. This is awkward since it requires "early" communication with the electronic structure backend upon restart that is not needed in a normal run, in particular, we must 1) ask backend for dimensions 2) read checkpoint 3) ask backend for electronic structure at restart geometry. Adding dimensions to Checkpoint.txt allows for a simpler sequence: 1) read checkpoint 2) ask backend for electronic structure at restart geometry. The code should be backwards compatible with pre-existing Checkpoint.txt files, and doesn't modify the TeraChem initialization sequence.
1 parent cd33087 commit 825f571

4 files changed

Lines changed: 188 additions & 23 deletions

File tree

src/modules/RestartModule.f90

Lines changed: 174 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -670,13 +670,30 @@ subroutine WriteElecStruc(ES, nf)
670670
! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
671671
type(T_ElecStruc), intent(in) :: ES
672672
integer(kind=DefInt), intent(in) :: nf
673+
integer(kind=DefInt) :: rows, cols
673674

674675
3 format(10(1x, es15.8))
675676

676-
write (nf, *) '# Orbitals'
677-
write (nf, 3) ES%OldOrbitals
678-
write (nf, *) '# CI vectors'
679-
write (nf, 3) ES%OldCIVecs
677+
if (allocated(ES%OldOrbitals)) then
678+
rows = size(ES%OldOrbitals, dim=1)
679+
cols = size(ES%OldOrbitals, dim=2)
680+
write (nf, *) '# Orbitals', rows, cols
681+
write (nf, 3) ES%OldOrbitals
682+
else
683+
write (nf, *) '# Orbitals', 0, 0
684+
write (nf, *)
685+
end if
686+
687+
if (allocated(ES%OldCIVecs)) then
688+
rows = size(ES%OldCIVecs, dim=1)
689+
cols = size(ES%OldCIVecs, dim=2)
690+
write (nf, *) '# CI vectors', rows, cols
691+
write (nf, 3) ES%OldCIVecs
692+
else
693+
write (nf, *) '# CI vectors', 0, 0
694+
write (nf, *)
695+
end if
696+
680697
write (nf, *) '# Overlap matrix'
681698
write (nf, 3) ES%OverlapMatrix
682699
write (nf, *) '# TC Blob'
@@ -685,28 +702,176 @@ subroutine WriteElecStruc(ES, nf)
685702
write (nf, 3) ES%OldMSPT2C
686703
write (nf, *) '# Electronic Phases'
687704
write (nf, *) ES%ElecPhase
705+
688706
end subroutine WriteElecStruc
689707

690708
subroutine ReadElecStruc(ES, nf)
709+
710+
use ElecStrucModule, only: esNBasis, esLCIVec
691711
type(T_ElecStruc), intent(inout) :: ES
692712
integer(kind=DefInt), intent(in) :: nf
713+
integer(kind=DefInt) :: ierr, rows, cols
714+
character(len=500) :: header
693715

694716
3 format(10(1x, es15.8))
695717

696-
read (nf, *)
697-
read (nf, 3) ES%OldOrbitals
698-
read (nf, *)
699-
read (nf, 3) ES%OldCIVecs
700-
read (nf, *)
718+
read (nf, '(A)') header
719+
720+
! Read orbitals
721+
call parse_matrix_header(header, '# Orbitals', rows, cols)
722+
call resolve_orbital_restart_dimensions(rows, cols)
723+
call read_matrix_from_unit(ES%OldOrbitals, nf, rows, cols, 'orbital matrix')
724+
call read_next_restart_header(nf, header)
725+
if (rows > 0) esNBasis = rows
726+
727+
! Read CI vectors
728+
call parse_matrix_header(header, '# CI vectors', rows, cols)
729+
call resolve_ci_restart_dimensions(rows, cols, size(ES%PotEn))
730+
call read_matrix_from_unit(ES%OldCIVecs, nf, rows, cols, 'CI vector matrix')
731+
call read_next_restart_header(nf, header)
732+
if (cols > 0) esLCIVec = cols
733+
734+
call require_header(header, '# Overlap matrix')
701735
read (nf, 3) ES%OverlapMatrix
702736
read (nf, *)
703737
read (nf, 3) ES%OldBlob
704738
read (nf, *)
705739
read (nf, 3) ES%OldMSPT2C
706740
read (nf, *)
707741
read (nf, *) ES%ElecPhase
742+
708743
end subroutine ReadElecStruc
709744

745+
subroutine read_next_restart_header(nf, header)
746+
!!
747+
!! Reads the next non-empty restart header
748+
!!
749+
integer(kind=DefInt), intent(in) :: nf
750+
character(len=500), intent(out) :: header
751+
integer(kind=DefInt) :: ierr
752+
753+
do
754+
read (nf, '(A)') header
755+
if (len_trim(header) > 0) exit
756+
end do
757+
758+
end subroutine read_next_restart_header
759+
760+
subroutine resolve_orbital_restart_dimensions(rows, cols)
761+
!!
762+
!! Resolve old-orbital matrix dimensions from the restart header or from
763+
!! an already-initialized backend, and check that both sources agree.
764+
!!
765+
use ElecStrucModule, only: esNBasis
766+
integer(kind=DefInt), intent(inout) :: rows, cols
767+
768+
if (rows >= 0 .and. cols >= 0) then
769+
if (rows == 0 .and. cols == 0) return
770+
if (esNBasis > 0 .and. (rows /= esNBasis .or. cols /= esNBasis)) then
771+
call FMS_DieError('Orbital matrix dimensions in restart file do not match initialized backend')
772+
end if
773+
else
774+
if (esNBasis <= 0) then
775+
call FMS_DieError('Restart orbital header must include dimensions when esNBasis is unknown')
776+
end if
777+
rows = esNBasis
778+
cols = esNBasis
779+
end if
780+
781+
end subroutine resolve_orbital_restart_dimensions
782+
783+
subroutine resolve_ci_restart_dimensions(rows, cols, num_states)
784+
!!
785+
!! Resolve CI vector dimensions from the restart header or from an
786+
!! already-initialized backend, and check that both sources agree.
787+
!!
788+
use ElecStrucModule, only: esLCIVec
789+
integer(kind=DefInt), intent(inout) :: rows, cols
790+
integer(kind=DefInt), intent(in) :: num_states
791+
792+
if (rows >= 0 .and. cols >= 0) then
793+
if (rows == 0 .and. cols == 0) return
794+
if (rows /= num_states) then
795+
call FMS_DieError('CI vector row count in restart file does not match number of states')
796+
end if
797+
if (esLCIVec > 0 .and. cols /= esLCIVec) then
798+
call FMS_DieError('CI vector length in restart file does not match initialized backend')
799+
end if
800+
else
801+
if (esLCIVec <= 0) then
802+
call FMS_DieError('Restart CI vector header must include dimensions when esLCIVec is unknown')
803+
end if
804+
rows = num_states
805+
cols = esLCIVec
806+
end if
807+
808+
end subroutine resolve_ci_restart_dimensions
809+
810+
subroutine read_matrix_from_unit(matrix, nf, rows, cols, name)
811+
!!
812+
!! Reads named matrix from nf unit
813+
!!
814+
real(kind=DefReal), allocatable, intent(inout) :: matrix(:, :)
815+
integer(kind=DefInt), intent(in) :: nf, rows, cols
816+
character(len=*), intent(in) :: name
817+
integer(kind=DefInt) :: ierr
818+
819+
3 format(10(1x, es15.8))
820+
821+
if (rows < 0 .or. cols < 0) then
822+
call FMS_DieError('Invalid dimensions for '//trim(name)//' in restart file')
823+
end if
824+
825+
if (allocated(matrix)) deallocate (matrix)
826+
if (rows > 0 .and. cols > 0) then
827+
allocate (matrix(rows, cols))
828+
read (nf, 3, iostat=ierr) matrix
829+
if (ierr /= 0) call FMS_DieError('Error reading '//trim(name)//' from restart file')
830+
end if
831+
832+
end subroutine read_matrix_from_unit
833+
834+
subroutine parse_matrix_header(header, label, rows, cols)
835+
!!
836+
!! Reads header with expected label (e.g., "# CI vectors") and extracts
837+
!! the dimensions of the stored CI vectors according to the format
838+
!! "# CI vectors [#rows] [#cols]".
839+
!!
840+
character(len=*), intent(in) :: header, label
841+
integer(kind=DefInt), intent(out) :: rows, cols
842+
integer(kind=DefInt) :: ios, start_pos
843+
character(len=len(header)) :: adjusted_header
844+
845+
call require_header(header, label)
846+
847+
rows = -1
848+
cols = -1
849+
adjusted_header = adjustl(header)
850+
start_pos = len_trim(label) + 1
851+
if (len_trim(adjusted_header) >= start_pos) then
852+
read (adjusted_header(start_pos:), *, iostat=ios) rows, cols
853+
if (ios /= 0) then
854+
rows = -1
855+
cols = -1
856+
end if
857+
end if
858+
859+
end subroutine parse_matrix_header
860+
861+
subroutine require_header(header, label)
862+
!!
863+
!! Sanity check that expected header is actually == label
864+
!!
865+
character(len=*), intent(in) :: header, label
866+
867+
if (index(adjustl(header), trim(label)) /= 1) then
868+
869+
call FMS_DieError('Unsupported restart trajectory format: expected '''//trim(label)//'''')
870+
871+
end if
872+
873+
end subroutine require_header
874+
710875
! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
711876
! PARTICLE
712877
! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

tests/AIMS-RESTART/Last_Bundle.txt.initial

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@
5757
1.206920724811525E-002 0.000000000000000E+000 0.000000000000000E+000
5858
5.598543749720466E+00 / Phase
5959
(0.98890207074517156,-1.64587765755770362E-003) / Amplitude
60-
# Orbitals
60+
# Orbitals 0 0
6161

62-
# CI vectors
62+
# CI vectors 0 0
6363

6464
# Overlap matrix
6565
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
@@ -107,9 +107,9 @@
107107
1.666180306845395E-002 0.000000000000000E+000 0.000000000000000E+000
108108
4.876812830655000E-01 / Phase
109109
(-0.14543955145958318,3.02873312433818639E-002) / Amplitude
110-
# Orbitals
110+
# Orbitals 0 0
111111

112-
# CI vectors
112+
# CI vectors 0 0
113113

114114
# Overlap matrix
115115
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
@@ -157,9 +157,9 @@
157157
1.517517889199943E-002 0.000000000000000E+000 0.000000000000000E+000
158158
4.819255093038093E-01 / Phase
159159
(-0.14498755228926799,3.00677562119372778E-002) / Amplitude
160-
# Orbitals
160+
# Orbitals 0 0
161161

162-
# CI vectors
162+
# CI vectors 0 0
163163

164164
# Overlap matrix
165165
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00

tests/AIMS-RESTART/Last_Bundle.txt.ref

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@
5757
1.235177642280282E-002 0.000000000000000E+000 0.000000000000000E+000
5858
5.577528940734926E+00 / Phase
5959
(0.98831589475674242,-1.79586289170714135E-003) / Amplitude
60-
# Orbitals
60+
# Orbitals 0 0
6161

62-
# CI vectors
62+
# CI vectors 0 0
6363

6464
# Overlap matrix
6565
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
@@ -107,9 +107,9 @@
107107
1.678084999429902E-002 0.000000000000000E+000 0.000000000000000E+000
108108
5.109671902184337E-01 / Phase
109109
(-0.14899984083154516,3.20548667099393517E-002) / Amplitude
110-
# Orbitals
110+
# Orbitals 0 0
111111

112-
# CI vectors
112+
# CI vectors 0 0
113113

114114
# Overlap matrix
115115
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
@@ -157,9 +157,9 @@
157157
1.541008853267562E-002 0.000000000000000E+000 0.000000000000000E+000
158158
4.819255093038093E-01 / Phase
159159
(-0.14498755228926799,3.00677562119372778E-002) / Amplitude
160-
# Orbitals
160+
# Orbitals 0 0
161161

162-
# CI vectors
162+
# CI vectors 0 0
163163

164164
# Overlap matrix
165165
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00

tests/ENERGY_CONS_REJECT/Last_Bundle.txt.ref

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@
5757
2.497120962482854E-003 0.000000000000000E+000 0.000000000000000E+000
5858
6.271759009116956E+00 / Phase
5959
(1.0000000000000000,-5.96311194867027439E-019) / Amplitude
60-
# Orbitals
60+
# Orbitals 0 0
6161

62-
# CI vectors
62+
# CI vectors 0 0
6363

6464
# Overlap matrix
6565
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00

0 commit comments

Comments
 (0)