MPI-SCATCI  2.0
An MPI version of SCATCI
CI_Hamiltonian_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 
32 
33  use const_gbl, only: stdout
35  use precisn, only: wp
36  use basematrix_module, only: basematrix
38  use options_module, only: options
39  use parallelization_module, only: grid => process_grid
42 
43  implicit none
44 
46 
47  private
48 
57  integer :: target_symmetry
58  integer :: csf_skip
59  contains
60  procedure, public :: initialize => initialize_target_ci_hamiltonian
61  procedure, public :: build_hamiltonian => build_target_ci_hamiltonian_fast
62  end type target_ci_hamiltonian
63 
64 contains
65 
73  subroutine initialize_target_ci_hamiltonian (this, target_symmetry)
74 
75  class(target_ci_hamiltonian) :: this
76  integer, intent(in) :: target_symmetry
77 
78  this % target_symmetry = target_symmetry
79  if (this % options % csf_type == normal_csf) then
80  this % csf_skip = this % options % num_continuum_orbitals_target(target_symmetry)
81  else
82  this % csf_skip = 2
83  end if
84 
85  this % initialized = .true.
87 
88 
96  subroutine build_target_ci_hamiltonian (this, matrix_elements)
97 
98  class(target_ci_hamiltonian) :: this
99  class(basematrix), intent(inout) :: matrix_elements
100  type(symbolicelementvector) :: symbolic_elements, ref_symbolic_elements
101  integer :: starting_index, num_csfs, ido, jdo, csf_a_idx, csf_b_idx, pzero_, num_elements
102  real(wp) :: mat_coeff, element_one
103 
104  !Just a quick check in the old diagonal flag
105  if (this % diagonal_flag == no_pure_target_integral) then
106  this % diagonal_flag = matrix_evaluate_full
107  else
108  this % diagonal_flag = matrix_evaluate_diff
109  end if
110 
111  this % phase_flag = 0
112 
113  !Get the total number of CSFs within the symmetry
114  num_csfs = this % options % num_ci_target_sym(this % target_symmetry)
115 
116  !Initialize the matrix structure as DENSE with no block structure
117  call matrix_elements % initialize_matrix_structure(num_csfs, mat_dense, num_csfs)
118 
119  !Construct the symbolic elements and clear
120  call symbolic_elements % construct
121  call symbolic_elements % clear
122  call ref_symbolic_elements % construct
123 
124  starting_index = 1
125  !Get the start of the CSFs within the target symmetry
126  do ido = 2, this % target_symmetry
127  starting_index = starting_index + this % options % num_ci_target_sym(ido - 1) * this % csf_skip
128  end do
129 
130  this % orbitals % MFLG = 0
131 
132  !Do the (1,1) diagonal --------------------------------------------------------!
133  csf_a_idx = starting_index
134 
135  !Everyone must have this
136  call this % slater_rules(this % csfs(csf_a_idx), this % csfs(csf_a_idx), ref_symbolic_elements, 0, .false.)
137 
138  !Evaluate the symbols for the integral for the matrix element (1,1)
139  if (.not. ref_symbolic_elements % is_empty()) then
140  mat_coeff = this % evaluate_integrals(ref_symbolic_elements, 0)
141  this % element_one = mat_coeff
142  !Lets have the master keep it, it will eventually reach everyone else if they need it
143  if (grid % mygrow == 0 .and. grid % mygcol == 0) call matrix_elements % insert_matrix_element(1, 1, mat_coeff)
144  call matrix_elements % update_pure_L2(.false.)
145  end if
146  !write(stdout,*)this%element_one
147 
148  !Clear the symbols
149  call symbolic_elements % clear
150 
151  !------------Do the rest of diagonals---------------------------!
152  do ido = 2, num_csfs
153  call matrix_elements % update_pure_L2(.false.)
154  csf_a_idx = csf_a_idx + this % csf_skip
155  call this % slater_rules(this % csfs(csf_a_idx), this % csfs(csf_a_idx), symbolic_elements, 0)
156  if (symbolic_elements % is_empty()) cycle
157 
158  if (this % diagonal_flag == 0) call symbolic_elements % add_symbols(ref_symbolic_elements, -1.0_wp)
159  mat_coeff = this%evaluate_integrals(symbolic_elements,0)
160  if (this % diagonal_flag == 0) mat_coeff = mat_coeff + this % element_one
161  num_elements = num_elements + 1
162 
163  call matrix_elements % insert_matrix_element(ido, ido, mat_coeff)
164  call symbolic_elements % clear
165  end do
166 
167  this % orbitals % MFLG = 1
168 
169  csf_a_idx = starting_index - this % csf_skip
170  !Do the off-idagonal
171  do ido = 1, num_csfs - 1
172  !Get the first CSf index
173  csf_a_idx = csf_a_idx + this % csf_skip
174  !Start the second CSF index
175  csf_b_idx = csf_a_idx
176  !Loop thorugh the lower triangular
177  do jdo = ido + 1, num_csfs
178  !Compute the second CSf index
179  csf_b_idx = csf_b_idx + this % csf_skip
180  !Perform an update if necessary
181  call matrix_elements % update_pure_L2(.false.)
182  !Slater the CSF
183  call this % slater_rules(this % csfs(csf_a_idx), this % csfs(csf_b_idx), symbolic_elements, 1)
184  !If empty, skip
185  if (symbolic_elements % is_empty()) cycle
186 
187  num_elements = num_elements + 1
188  !Evaulate the matrix coefficient
189  mat_coeff = this % evaluate_integrals(symbolic_elements, 0)
190 
191  !Insert into the matrix
192  call matrix_elements % insert_matrix_element(jdo, ido, mat_coeff)
193  !Clear
194  call symbolic_elements % clear
195  end do
196  end do
197  !Force an update to clear the matrix cache if needed
198  call matrix_elements % update_pure_L2(.true.)
199 
200  !Cleanup
201  call symbolic_elements % destroy
202  call ref_symbolic_elements % destroy
203 
204  !Finalize if needed
205  call matrix_elements % finalize_matrix
206 
207  end subroutine build_target_ci_hamiltonian
208 
209 
219  subroutine build_target_ci_hamiltonian_fast (this, matrix_elements)
220 
221  class(target_ci_hamiltonian) :: this
222  class(basematrix), intent(inout) :: matrix_elements
223  type(symbolicelementvector) :: symbolic_elements, ref_symbolic_elements
224  integer :: starting_index, num_csfs, ido, jdo, csf_a_idx, csf_b_idx, pzero_, loop_idx, total_vals
225  integer :: num_elements,begin_csf,loop_skip,my_idx,loop_ido,m_flag
226  real(wp) :: mat_coeff, element_one
227 
228  !Just a quick check in the old diagonal flag
229  if (this % diagonal_flag == no_pure_target_integral) then
230  this % diagonal_flag = matrix_evaluate_full
231  else
232  this % diagonal_flag = matrix_evaluate_diff
233  end if
234 
235  this % phase_flag = 0
236  num_elements = 0
237 
238  !Get the total number of CSFs within the symmetry
239  num_csfs = this % options % num_ci_target_sym(this % target_symmetry)
240 
241  !Initialize the matrix structure as DENSE with no block structure
242  call matrix_elements % initialize_matrix_structure(num_csfs, mat_dense, num_csfs)
243 
244  !Construct the symbolic elements and clear
245  call symbolic_elements % construct
246  call symbolic_elements % clear
247  call ref_symbolic_elements % construct
248 
249  starting_index = 1
250  !Get the start of the CSFs within the target symmetry
251  do ido = 2, this % target_symmetry
252  starting_index = starting_index + this % options % num_ci_target_sym(ido - 1) * this % csf_skip
253  end do
254 
255  m_flag = 0
256 
257  !Do the (1,1) diagonal --------------------------------------------------------!
258  csf_a_idx = starting_index
259 
260  !Everyone must have this
261  call this % slater_rules(this % csfs(csf_a_idx), this % csfs(csf_a_idx), ref_symbolic_elements, m_flag, .false.)
262 
263  !Evaluate the symbols for the integral for the matrix element (1,1)
264  if (.not. ref_symbolic_elements % is_empty()) then
265  mat_coeff = this % evaluate_integrals(ref_symbolic_elements, 0)
266  this % element_one = mat_coeff
267  !Lets have the master keep it, it will eventually reach everyone else if they need it
268  if (grid % mygrow == 0 .and. grid % mygcol == 0) call matrix_elements % insert_matrix_element(1, 1, mat_coeff)
269  call matrix_elements % update_pure_L2(.false.)
270  end if
271  !write(stdout,*)this%element_one
272 
273  !Clear the symbols
274  call symbolic_elements % clear
275 
276  !------------Do the rest of diagonals---------------------------!
277  do ido = 2,num_csfs
278  call matrix_elements % update_pure_L2(.false.)
279  csf_a_idx = csf_a_idx + this % csf_skip
280 
281  call this % slater_rules(this % csfs(csf_a_idx), this % csfs(csf_a_idx), symbolic_elements, 0)
282  if (symbolic_elements % is_empty()) cycle
283 
284  if (this % diagonal_flag == 0) call symbolic_elements % add_symbols(ref_symbolic_elements, -1.0_wp)
285  mat_coeff = this % evaluate_integrals(symbolic_elements, 0)
286  if (this % diagonal_flag == 0) mat_coeff = mat_coeff + this % element_one
287  num_elements = num_elements + 1
288 
289  call matrix_elements % insert_matrix_element(ido, ido, mat_coeff)
290  call symbolic_elements % clear
291  end do
292 
293  begin_csf = starting_index - this % csf_skip
294  total_vals = compute_total_box(num_csfs, num_csfs)
295  loop_skip = max(1, grid % gprocs)
296  my_idx = max(grid % grank, 0)
297 
298  do loop_ido = 1, total_vals, loop_skip
299  loop_idx = loop_ido + my_idx
300  call matrix_elements % update_pure_L2(.false.)
301  if (loop_idx > total_vals) cycle
302 
303  call box_index_to_ij(loop_idx, num_csfs, ido, jdo)
304  if (ido <= jdo) cycle
305 
306  csf_a_idx = begin_csf + ido * this % csf_skip
307  csf_b_idx = begin_csf + jdo * this % csf_skip
308 
309  call this % slater_rules(this % csfs(csf_a_idx), this % csfs(csf_b_idx), symbolic_elements, 1, .false.)
310 
311  if (symbolic_elements % is_empty()) cycle
312 
313  num_elements = num_elements + 1
314  mat_coeff = this % evaluate_integrals(symbolic_elements, this % options % phase_correction_flag)
315 
316  call matrix_elements % insert_matrix_element(ido, jdo, mat_coeff)
317  call symbolic_elements % clear
318  end do
319 
320  call matrix_elements % update_pure_L2(.true.)
321  call symbolic_elements % destroy
322  call matrix_elements % finalize_matrix
323 
324  write (stdout, "('Num of elements = ',i0)") num_elements
325 
326  end subroutine build_target_ci_hamiltonian_fast
327 
328 end module ci_hamiltonian_module
hamiltonian_module::basehamiltonian
This is an abstract class that contains the majority of functionality required to construct hamiltoni...
Definition: Hamiltonian_module.f90:57
utility_module::box_index_to_ij
subroutine, public box_index_to_ij(idx, height, i, j)
Extract indices from rectangular multi-index.
Definition: Utility_module.f90:73
consts_mpi_ci::normal_csf
integer, parameter normal_csf
Use configuration state functions as is.
Definition: consts_mpi_ci.f90:67
ci_hamiltonian_module::target_ci_hamiltonian
Hamiltonian type.
Definition: CI_Hamiltonian_module.f90:56
options_module::options
Calculation setup for a single Hamiltonian diagonalization.
Definition: Options_module.f90:74
ci_hamiltonian_module
Target CI Hamiltonian module.
Definition: CI_Hamiltonian_module.f90:31
symbolic_module
Symbolic module.
Definition: Symbolic_Module.f90:33
parallelization_module::process_grid
type(processgrid) process_grid
Definition: Parallelization_module.F90:80
basematrix_module
Base matrix module.
Definition: BaseMatrix_module.f90:28
utility_module
Utility module.
Definition: Utility_module.f90:28
consts_mpi_ci
MPI SCATCI Constants module.
Definition: consts_mpi_ci.f90:31
ci_hamiltonian_module::build_target_ci_hamiltonian
subroutine build_target_ci_hamiltonian(this, matrix_elements)
Builds the Target Hamiltonian of a specific target symmetry.
Definition: CI_Hamiltonian_module.f90:97
symbolic_module::symbolicelementvector
This class handles the storage symbolic elements.
Definition: Symbolic_Module.f90:57
basematrix_module::basematrix
Base matrix type.
Definition: BaseMatrix_module.f90:47
consts_mpi_ci::matrix_evaluate_diff
integer, parameter matrix_evaluate_diff
Matrix is evaluated as a difference from the first element.
Definition: consts_mpi_ci.f90:75
parallelization_module
Distribution of processes into a grid.
Definition: Parallelization_module.F90:29
consts_mpi_ci::matrix_evaluate_full
integer, parameter matrix_evaluate_full
Matrix is evaluated as full.
Definition: consts_mpi_ci.f90:77
ci_hamiltonian_module::build_target_ci_hamiltonian_fast
subroutine build_target_ci_hamiltonian_fast(this, matrix_elements)
Builds the Target Hamiltonian of a specific target symmetry fast, currently not working.
Definition: CI_Hamiltonian_module.f90:220
consts_mpi_ci::mat_dense
integer, parameter mat_dense
Matrix is dense.
Definition: consts_mpi_ci.f90:118
utility_module::compute_total_box
integer function, public compute_total_box(width, height)
Calculate rectangular product.
Definition: Utility_module.f90:61
consts_mpi_ci::no_pure_target_integral
integer, parameter no_pure_target_integral
Same as full but dont evalute integrals belonging to the target state.
Definition: consts_mpi_ci.f90:81
options_module
Options module.
Definition: Options_module.f90:41
ci_hamiltonian_module::initialize_target_ci_hamiltonian
subroutine initialize_target_ci_hamiltonian(this, target_symmetry)
Sets up the hamiltonian to build for a specific target symmetry.
Definition: CI_Hamiltonian_module.f90:74
hamiltonian_module
Base Hamiltonian module.
Definition: Hamiltonian_module.f90:33