22 use,
intrinsic :: iso_fortran_env, only: real64
52 integer,
private,
parameter :: ik = 1
58 type(namespace_t),
intent(in ) :: namespace
59 class(mesh_t),
intent(in ) :: mesh
60 type(states_elec_t),
intent(in ) :: st
61 type(centroids_t),
intent(in ) :: centroids
63 real(real64),
allocatable,
intent(out) :: isdf_vectors(:, :)
65 character(len=2) :: np_char
66 integer :: nocc, n_int_g
67 real(real64),
allocatable :: psi_mu(:, :)
69 real(real64),
allocatable :: p_r_mu(:, :)
71 real(real64),
allocatable :: zct(:, :)
72 real(real64),
allocatable :: p_mu_nu(:, :)
74 real(real64),
allocatable :: cct(:, :)
80 if (st%d%nspin > 1)
then
98 n_int_g = centroids%npoints_global()
103 if (st%st_start <= nocc .and. nocc <= st%st_end)
then
104 write(
message(1),
'(a, 1x, I3, 1x, a, 1x, I3)')
"ISDF: Computing ISDF vectors up to state", &
105 & nocc,
" on process", st%mpi_grp%rank
113 safe_allocate(p_r_mu(1:mesh%np, 1:n_int_g))
115 if (
debug%info)
call output_matrix(namespace,
"p_r_mu_np"//trim(adjustl(np_char))//
".txt", p_r_mu)
117 safe_allocate(zct(1:mesh%np, 1:n_int_g))
119 if (
debug%info)
call output_matrix(namespace,
"zct_np"//trim(adjustl(np_char))//
".txt", zct)
120 safe_deallocate_a(p_r_mu)
122 safe_allocate(p_mu_nu(1:n_int_g, 1:n_int_g))
124 call lalg_gemm(psi_mu, psi_mu, p_mu_nu, transa=
'T')
127 if (
debug%info)
call output_matrix(namespace,
"p_mu_nu_np"//trim(adjustl(np_char))//
".txt", p_mu_nu)
128 safe_deallocate_a(psi_mu)
130 safe_allocate(cct(1:n_int_g, 1:n_int_g))
132 if (
debug%info)
call output_matrix(namespace,
"cct_np"//trim(adjustl(np_char))//
".txt", cct)
136 safe_deallocate_a(p_mu_nu)
141 write(
message(1),
'(a)')
"ISDF: Inverting [CC^T]"
147 safe_allocate(isdf_vectors(1:mesh%np, 1:n_int_g))
148 call lalg_gemm(mesh%np, n_int_g, n_int_g, 1.0_real64, zct, cct, 0.0_real64, isdf_vectors)
151 if (
debug%info .and. .not. mesh%parallel_in_domains)
then
152 call output_matrix(namespace,
"isdf_np"//trim(adjustl(np_char))//
".txt", isdf_vectors)
155 safe_deallocate_a(zct)
156 safe_deallocate_a(cct)
174 real(real64),
target,
contiguous,
intent(in ) :: p_phi(:, :)
176 real(real64),
target,
optional,
contiguous,
intent(in ) :: p_psi(:, :)
179 real(real64),
contiguous,
intent(out) :: zct(:, :)
181 integer :: np, n_int_g, ip, i_mu
182 real(real64),
pointer,
contiguous :: p_2(:, :)
186 write(
message(1),
'(a)')
"ISDF: Constructing Z C^T"
189 if (
present(p_psi))
then
196 assert(all(shape(p_phi) == shape(p_2)))
198 assert(all(shape(p_phi) == shape(zct)))
201 n_int_g =
size(p_phi, 2)
208 zct(ip, i_mu) = p_phi(ip, i_mu) * p_2(ip, i_mu)
232 real(real64),
target,
contiguous,
intent(in ) :: p_phi(:, :)
234 real(real64),
target,
contiguous,
optional,
intent(in ) :: p_psi(:, :)
237 real(real64),
contiguous,
intent(out) :: cct(:, :)
240 integer :: n_int_g, i_mu, i_nu
241 real(real64),
contiguous,
pointer :: p_2(:, :)
245 write(
message(1),
'(a)')
"ISDF: Construct CC^T"
248 if (
present(p_psi))
then
255 assert(all(shape(p_phi) == shape(p_2)))
257 assert(all(shape(p_phi) == shape(cct)))
258 n_int_g =
size(p_phi, 1)
264 cct(i_mu, i_nu) = p_phi(i_mu, i_nu) * p_2(i_mu, i_nu)
281 class(
mesh_t),
intent(in) :: mesh
282 real(real64),
contiguous,
intent(in ) :: isdf_vectors(:, :)
283 real(real64),
contiguous,
intent(out) :: gram_matrix(:, :)
285 integer :: n_int, i, j
289 assert(mesh%np ==
size(isdf_vectors, 1))
290 n_int =
size(isdf_vectors, 2)
291 assert(all(shape(gram_matrix) == [n_int, n_int]))
297 gram_matrix(i, i) =
dmf_dotp(mesh, isdf_vectors(:, i), isdf_vectors(:, i), reduce=.false.)
303 gram_matrix(i, j) =
dmf_dotp(mesh, isdf_vectors(:, i), isdf_vectors(:, j), reduce=.false.)
305 gram_matrix(j, i) = gram_matrix(i, j)
309 call mesh%allreduce(gram_matrix)
327 integer,
intent(in) :: max_state
329 integer :: minst, maxst
351 real(real64),
contiguous,
intent(in ) :: psi_mu(:, :)
352 real(real64),
contiguous,
intent(out) :: psi_global(:, :)
354 integer :: max_state, n_int_g, ic, ist, st_end, is_local
358 if (st%group%psib(st%group%block_start, ik)%status() /=
batch_packed)
then
359 message(1) =
"Developer Error: Trying to output psi_mu when not BATCH_PACKED"
364 n_int_g =
size(psi_global, 2)
365 assert(
size(psi_mu, 2) ==
size(psi_global, 2))
368 max_state =
size(psi_global, 1)
373 do ist = 1, max_state
374 psi_global(ist, ic) = 0.0_real64
380 st_end = min(st%st_end, max_state)
383 if (
size(psi_mu, 1) > 0)
then
384 assert(st_end - st%st_start + 1 ==
size(psi_mu, 1))
389 do ist = st%st_start, st_end
390 is_local = ist - st%st_start + 1
391 psi_global(ist, ic) = psi_mu(is_local, ic)
411 integer,
intent(in) :: max_state
412 real(real64),
contiguous,
intent(in) :: psi_mu(:, :)
414 real(real64),
allocatable :: psi_global(:, :)
415 integer :: n_int_g, ic, ist, unit
416 character(len=2) :: np_char
420 if (st%group%psib(st%group%block_start, ik)%status() /=
batch_packed)
then
421 message(1) =
"Trying to output psi_mu when not BATCH_PACKED"
425 write(
message(1),
'(a)')
"ISDF: Writing psi_mu (all states/DD)"
428 n_int_g =
size(psi_mu, 2)
429 safe_allocate(psi_global(1:max_state, 1:n_int_g))
433 unit =
io_open(
"global_psi_mu_np"//trim(adjustl(np_char))//
".txt", namespace, action=
'write')
435 write(np_char,
'(I2)') st%mpi_grp%size
437 do ist = 1, max_state
438 write(unit, *) psi_global(ist, ic)
444 safe_deallocate_a(psi_global)
451#include "isdf_inc.F90"
Matrix-matrix multiplication plus matrix.
pure logical function, public accel_is_enabled()
This module implements batches of mesh functions.
integer, parameter, public batch_not_packed
functions are stored in CPU memory, unpacked order
integer, parameter, public batch_device_packed
functions are stored in device memory in packed order
integer, parameter, public batch_packed
functions are stored in CPU memory, in transposed (packed) order
type(debug_t), save, public debug
subroutine, public io_close(iunit, grp)
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Interoperable Separable Density Fitting (ISDF) molecular implementation.
integer function local_number_of_states(st, max_state)
Number of states contributing to the expansion, local to current process.
subroutine gather_psi_mu_over_states(st, psi_mu, psi_global)
Gather state-distributed psi from multiple processes.
subroutine dquasi_density_matrix_at_mesh_centroid_points(st, max_state, psi_mu, p_r_mu)
Compute the quasi-density matrix where one spatial coordinate is defined at grid points and the is de...
subroutine output_psi_mu_for_all_states(namespace, st, max_state, psi_mu)
Output the gathered psi_mu for all states, such that the matrix is the same irregardless of state par...
subroutine, public interpolative_separable_density_fitting_vectors(namespace, mesh, st, centroids, isdf_vectors)
Top-level routine for computing ISDF vectors.
subroutine dphi_at_interpolation_points(mesh, st, centroids, max_state, psi_mu)
Construct a 2D array of states, defined only at a specific subset of grid points.
subroutine, public interpolation_vector_gram_matrix(mesh, isdf_vectors, gram_matrix)
Compute the Gram matrix for the ISDF interpolation vectors.
subroutine coefficient_product_matrix(p_phi, cct, p_psi)
Construct the coefficient product matrix .
subroutine pair_product_coefficient_matrix(p_phi, zct, p_psi)
Construct the matrix-matrix product .
subroutine, public output_matrix(namespace, fname, matrix)
Helper routine to output a 2D matrix.
integer function, public highest_occupied_index(st, ik_index)
Return the index of highest occupied Kohn-Sham state for k-point ik.
This module is intended to contain "only mathematical" functions and procedures.
logical function, public is_symmetric(a, tol)
Check if a 2D array is symmetric.
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
subroutine, public messages_not_implemented(feature, namespace)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
type(mpi_grp_t), public mpi_world
pure logical function, public states_are_real(st)
integer pure function, public states_elec_block_max(st, ib)
return index of last state in block ib
integer pure function, public states_elec_block_min(st, ib)
return index of first state in block ib
Describes mesh distribution to nodes.
The states_elec_t class contains all electronic wave functions.