@@ -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
6746753 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
6947163 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! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
0 commit comments