MPI-SCATCI 2.0
An MPI version of SCATCI
Loading...
Searching...
No Matches
/scratch.ssd/codes/ukrmol-in-git/source/mpi-ci-diag/mpi_scatci.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
22!> \brief MPI-SCATCI main program
23!> \authors A Al-Refaie, J Benda
24!> \date 2017 - 2022
25!>
26!> MPI-SCATCI diagonalizes Hamiltonians for one or more irreducible representations. The input for each
27!> is read from the single input file as the pair of standard SCATCI namelists &input and &cinorn.
28!> If there are fewer MPI processes than Hamiltonians to diagonalize, each process is given several
29!> Hamiltonians to diagonalize sequentially. If there are more processes than Hamiltonians, some or all
30!> Hamiltonians will be diagonalized in a distributed regime. All processes that participate on diagonalization
31!> of the same matrix are part of a "diagonalization group" which has separate BLACS context and their own
32!> MPI communicator.
33!>
34!> The eigenvectors are kept in the memory and, if desired, are then used to calculate transition dipole
35!> moments and further derived data.
36!>
37!> \note 16/01/2019 - Jakub Benda: Unifom coding style and expanded documentation.
38!> \note 25/01/2019 - Jakub Benda: Extension to support multiple subsequent diagonalizations.
39!> \note 30/01/2019 - Jakub Benda: Evaluation of properties using libcdenprop, including cross-symmetry ones.
40!> \note 22/05/2022 - Jakub Benda: Reimplemented reading of eigensolutions from disk.
41!>
43
46 use const_gbl, only: stdout
47 use global_utils, only: print_ukrmol_header
48 use precisn, only: wp, longint
49 use mpi_gbl, only: mpi_mod_start, mpi_mod_finalize, master, myrank, mpi_mod_print_info
50 use options_module, only: optionsset, ham_pars_io_wrapper
51 use orbital_module, only: orbitaltable
52 use csf_module, only: csfobject, csforbital, csfmanager
53 use ci_hamiltonian_module, only: target_ci_hamiltonian
54 use basematrix_module, only: basematrix
55 use baseintegral_module, only: baseintegral
56 use diagonalizer_module, only: basediagonalizer
57 use memorymanager_module, only: master_memory
58 use parallelization_module, only: process_grid
59 use postprocessing_module, only: postprocess
60 use uncontracted_hamiltonian_module, only: uncontracted_hamiltonian
61 use contracted_hamiltonian_module, only: contracted_hamiltonian
62 use timing_module, only: master_timer
63 use target_rmat_ci_module, only: target_rmat_ci, read_ci_mat
64 use dispatcher_module, only: dispatchintegral, dispatchmatrixanddiagonalizer, initialize_libraries
65 use writermatrix_module, only: writermatrix
66 use solutionhandler_module, only: solutionhandler
67
68 implicit none
69
70 type(optionsset) :: scatci_input
71 type(orbitaltable) :: orbitals
72 type(uncontracted_hamiltonian) :: enrgms
73 type(contracted_hamiltonian) :: enrgmx
74 type(csfmanager) :: configuration_manager
75 class(baseintegral), pointer :: integrals => null()
76 class(target_ci_hamiltonian), pointer :: tgt_ci_hamiltonian => null()
77 class(basediagonalizer), pointer :: diagonalizer => null()
78 class(basematrix), pointer :: matrix_elements => null()
79 type(solutionhandler), allocatable :: solutions(:)
80 type(csfobject), allocatable :: csfs(:)
81 type(target_rmat_ci), allocatable :: ci_rmat(:)
82 real(wp), allocatable :: test_eig(:), test_vecs(:,:)
83 integer :: num_mat_elms, i, j
84 real(wp) :: usr_ef
85 integer :: usr_ef_type
86
87 logical, parameter :: sequential_diagonalizations = .false.
88 logical, parameter :: master_writes_to_stdout = .true.
89 logical, parameter :: allow_shared_memory = .true.
90
91 call mpi_mod_start(master_writes_to_stdout, allow_shared_memory)
92 call master_timer % initialize()
93 if (myrank == master) call print_ukrmol_header(stdout)
94 call mpi_mod_print_info(stdout)
95
96 ! Initialize all libraries used by MPI-SCATCI that need it (e.g. SLEPc)
97 call initialize_libraries
98
99 ! Read options (for all symmetries)
100 call scatci_input % read
101 allocate (solutions(size(scatci_input % opts)))
102
103 ! Set up the MPI/BLACS groups
104 call process_grid % setup(size(scatci_input % opts), sequential_diagonalizations)
105 call process_grid % summarize
106 if (.not. process_grid % sequential) call scatci_input % setup_write_order
107
108 call master_timer % start_timer("Wall Time")
109
110 ! Process all symmetries
111 symmetry_loop: do i = 1, size(scatci_input % opts)
112
113 if (.not. process_grid % is_my_group_work(i)) cycle
114
115 call orbitals % initialize(scatci_input % opts(i) % tot_num_spin_orbitals, &
116 scatci_input % opts(i) % tot_num_orbitals, &
117 scatci_input % opts(i) % sym_group_flag, &
118 scatci_input % opts(i) % num_syms, &
119 scatci_input % opts(i) % positron_flag)
120 call orbitals % construct(scatci_input % opts(i) % num_orbitals_sym, &
121 scatci_input % opts(i) % num_target_orbitals_sym_dinf_congen, &
122 scatci_input % opts(i) % num_orbitals_sym, &
123 scatci_input % opts(i) % num_electronic_orbitals_sym, &
124 scatci_input % opts(i) % num_target_orbitals_sym_congen)
125
126 ! Compute the electron number for each reference orbital
127 call orbitals % compute_electron_index(scatci_input % opts(i) % num_electrons, &
128 scatci_input % opts(i) % reference_dtrs)
129
130 ! Construct our csf manager
131 call configuration_manager % initialize(scatci_input % opts(i), orbitals)
132
133 ! Construct our CSFS
134 call master_timer % start_timer("Construct CSFs")
135 call configuration_manager % create_csfs(csfs, &
136 scatci_input % opts(i) % orbital_sequence_number, &
137 scatci_input % opts(i) % num_ci_target_sym, &
138 scatci_input % opts(i) % lambda_continuum_orbitals_target)
139 call master_timer % stop_timer("Construct CSFs")
140 call master_memory % print_memory_report
141
142 ! Read molecular integrals (assuming all symmetries use the same!)
143 if (.not. associated(integrals)) then
144 call dispatchintegral(scatci_input % opts(i) % sym_group_flag, &
145 scatci_input % opts(i) % use_UKRMOL_integrals, &
146 integrals)
147 call integrals % initialize(scatci_input % opts(i), &
148 orbitals % total_num_orbitals, &
149 orbitals % orbital_map)
150 call integrals % load_integrals(scatci_input % opts(i) % integral_unit)
151 call master_memory % print_memory_report
152 end if
153
154 ! if only reading already calculated eigensolutions (for processing in CDENPROP or outer interface)
155 if (scatci_input % opts(i) % diagonalization_flag == read_from_file) then
156 call solutions(i) % construct(scatci_input % opts(i))
157 call solutions(i) % export_header(scatci_input % opts(i), integrals)
158 call solutions(i) % read_from_file(scatci_input % opts(i))
159 deallocate(csfs)
160 call configuration_manager % finalize
161 cycle
162 end if
163
164 write (stdout, *) ' Load CI target and construct matrix elements'
165
166 ! Before we do anything else let us get our ECP if we need them
167 !call DispatchECP(SCATCI_input % opts(i) % ecp_type, &
168 ! SCATCI_input % opts(i) % ecp_filename, &
169 ! SCATCI_input % opts(i) % all_ecp_defined, &
170 ! SCATCI_input % opts(i) % num_target_sym, &
171 ! SCATCI_input % opts(i) % num_target_state_sym, &
172 ! SCATCI_input % opts(i) % target_spatial, &
173 ! SCATCI_input % opts(i) % target_multiplicity, ecp)
174
175 if (scatci_input % opts(i) % do_ci_contraction()) then
176 usr_ef = scatci_input % opts(i) % enh_factor
177 usr_ef_type = scatci_input % opts(i) % enh_factor_type
178 scatci_input % opts(i) % enh_factor = 1.0
179 scatci_input % opts(i) % enh_factor_type = 0
180 ! allocate the CIRmats
181 allocate(ci_rmat(scatci_input % opts(i) % num_target_sym))
182 do j = 1, scatci_input % opts(i) % num_target_sym
183 call ci_rmat(j) % initialize(j, &
184 scatci_input % opts(i) % num_target_state_sym(j), &
185 scatci_input % opts(i) % num_ci_target_sym(j), &
186 scatci_input % opts(i) % ci_phase(j), &
187 integrals % get_core_energy())
188 end do
189
190 if (scatci_input % opts(i) % ci_target_switch > 0) then
191 call read_ci_mat(scatci_input % opts(i), ci_rmat)
192 else
193 do j = 1, scatci_input % opts(i) % num_target_sym
194 allocate(target_ci_hamiltonian::tgt_ci_hamiltonian)
195 call dispatchmatrixanddiagonalizer(scatci_input % opts(i) % diagonalizer_choice, &
196 scatci_input % opts(i) % force_serial, &
197 scatci_input % opts(i) % num_ci_target_sym(j), &
198 ci_rmat(j) % nstat, &
199 matrix_elements, &
200 diagonalizer, &
201 integrals, &
202 scatci_input % opts(i) % hamiltonian_unit)
203
204 call matrix_elements % construct(target_hamiltonian + j)
205 call matrix_elements % set_options(scatci_input % opts(i))
206
207 call tgt_ci_hamiltonian % construct(scatci_input % opts(i), csfs, orbitals, integrals)
208 call tgt_ci_hamiltonian % initialize(j)
209
210 call master_timer % start_timer("Build CI Hamiltonian")
211 call tgt_ci_hamiltonian % build_hamiltonian(matrix_elements)
212 call master_timer % stop_timer("Build CI Hamiltonian")
213 call master_timer % report_timers
214
215 call master_timer % start_timer("Diagonalization")
216 call diagonalizer % diagonalize(matrix_elements, ci_rmat(j) % nstat, ci_rmat(j), .true., &
217 scatci_input % opts(i), integrals)
218 call master_timer % stop_timer("Diagonalization")
219
220 call ci_rmat(j) % print
221 call master_timer % report_timers
222
223 call matrix_elements % destroy
224 if (process_grid % grank == master) close (scatci_input % opts(i) % hamiltonian_unit)
225 deallocate(matrix_elements, diagonalizer)
226 deallocate(tgt_ci_hamiltonian)
227 end do
228 end if
229 scatci_input % opts(i) % enh_factor = usr_ef
230 scatci_input % opts(i) % enh_factor_type = usr_ef_type
231 end if
232
233 if (scatci_input % opts(i) % diagonalization_flag /= no_diagonalization) then
234 call dispatchmatrixanddiagonalizer(scatci_input % opts(i) % diagonalizer_choice, &
235 scatci_input % opts(i) % force_serial, &
236 scatci_input % opts(i) % contracted_mat_size, &
237 scatci_input % opts(i) % num_eigenpairs, &
238 matrix_elements, &
239 diagonalizer, &
240 integrals, &
241 scatci_input % opts(i) % hamiltonian_unit)
242 call matrix_elements % construct(main_hamiltonian)
243 call matrix_elements % set_options(scatci_input % opts(i))
244 else
245 call integrals % write_matrix_header(scatci_input % opts(i) % hamiltonian_unit, &
246 scatci_input % opts(i) % contracted_mat_size)
247 allocate(writermatrix::matrix_elements)
248 call matrix_elements % construct(main_hamiltonian)
249 call matrix_elements % set_options(scatci_input % opts(i))
250 end if
251
252 call matrix_elements % exclude_row_column(scatci_input % opts(i) % exclude_rowcolumn)
253
254 ! We are doing a scattering calculation
255 if (scatci_input % opts(i) % do_ci_contraction()) then
256 call enrgmx % construct(scatci_input % opts(i), csfs, orbitals, integrals)
257 call enrgmx % initialize(ci_rmat)
258 call master_timer % start_timer("C-Hamiltonian Build")
259 call enrgmx % build_hamiltonian(matrix_elements)
260 call master_timer % stop_timer("C-Hamiltonian Build")
261 deallocate (ci_rmat)
262 else
263 call enrgms % construct(scatci_input % opts(i), csfs, orbitals, integrals)
264 call master_timer % start_timer("Target-Hamiltonian Build")
265 call enrgms % build_hamiltonian(matrix_elements)
266 call master_timer % stop_timer("Target-Hamiltonian Build")
267 end if
268
269 ! Lets deallocate all the csfs as well
270 deallocate(csfs)
271
272 ! Clear the integrals, we dont need them anymore
273 call configuration_manager % finalize
274
275 call master_memory % print_memory_report
276 write (stdout, "('Matrix N is ',i8)") matrix_elements % get_matrix_size()
277 write (stdout, "('Num elements is ',i14)") matrix_elements % get_size()
278 call master_timer % report_timers
279
280 if (scatci_input % opts(i) % diagonalization_flag /= no_diagonalization) then
281 scatci_input % opts(i) % num_eigenpairs = min(scatci_input % opts(i) % num_eigenpairs, &
282 matrix_elements % get_matrix_size())
283 call solutions(i) % construct(scatci_input % opts(i))
284 call master_timer % start_timer("Diagonalization")
285 call diagonalizer % diagonalize(matrix_elements, &
286 scatci_input % opts(i) % num_eigenpairs, &
287 solutions(i), &
288 .false., &
289 scatci_input % opts(i), &
290 integrals)
291 call master_timer % stop_timer("Diagonalization")
292 call master_timer % report_timers
293 else
294 write (stdout, '(/,"Diagonalization not selected")')
295 num_mat_elms = matrix_elements % get_size()
296
297 call master_timer % start_timer("Matrix Save")
298 !call matrix_elements % save(SCATCI_input % hamiltonian_unit, SCATCI_input % num_matrix_elements_per_rec)
299 call master_timer % stop_timer("Matrix Save")
300
301 if (process_grid % grank == master) call ham_pars_io_wrapper(scatci_input % opts(i), .true., num_mat_elms)
302
303 write (stdout, '(/,"Parameters written to: ham_data")')
304 end if
305
306 if (process_grid % grank == master) close (scatci_input % opts(i) % hamiltonian_unit)
307
308 call matrix_elements % destroy
309
310 deallocate (diagonalizer)
311 deallocate (matrix_elements)
312
313 end do symmetry_loop
314
315 ! use solutions in outer interface etc.
316 call postprocess(scatci_input, solutions)
317 call master_timer % stop_timer("Wall Time")
318 call master_timer % report_timers
319
320 ! release (possibly shared) memory occupied by the integral storage
321 if (associated(integrals)) then
322 call integrals % finalize
323 nullify (integrals)
324 end if
325
326 ! cleanly exit MPI
327 call mpi_mod_finalize
328
329end program mpi_scatci
program mpi_scatci
MPI-SCATCI main program.
MPI SCATCI Constants module.
integer, parameter read_from_file
Do not diagonalize, just read from file.
integer, parameter no_diagonalization
No diagonalization.
integer, parameter main_hamiltonian
Hamiltonain is a scattering one.
integer, parameter no_ci_target
No Ci target contraction (target only run)
integer, parameter target_hamiltonian
Hamiltonain is target one.