Octopus
test_isdf.F90
Go to the documentation of this file.
1!! Copyright (C) 2024 A Buccheri.
2
3#include "global.h"
4
7 use, intrinsic :: iso_fortran_env
8
10 use comm_oct_m
11 use debug_oct_m
14 use global_oct_m
18 use lcao_oct_m, only: lcao_run
19 use mesh_oct_m
21 use mpi_oct_m, only: mpi_world, mpi_double_precision
24 use scf_oct_m
25 use sort_oct_m, only: sort
27 use types_oct_m
30
31 ! Modules under test
34
35 implicit none
36 private
37 public :: test_isdf
38
39contains
40
44 subroutine map_centroid_positions_to_indices(mesh, positions, indices)
45 class(mesh_t), intent(in ) :: mesh
46 real(real64), intent(in ) :: positions(:, :)
47 integer(int64), intent(out) :: indices(:)
48
49 integer(int64) :: ipg
50 integer :: n_centroids, ic
51 integer :: ix(size(positions, 1))
52 real(real64) :: chi(size(positions, 1))
53
55
56 if (mesh%parallel_in_domains) then
57 message(1) = "map_centroid_positions_to_indices is not domain-parallel"
58 call messages_fatal(1)
59 endif
60
61 n_centroids = size(positions, 2)
62 assert(size(indices) == n_centroids)
63
64 do ic = 1, n_centroids
65 chi = mesh%coord_system%from_cartesian(positions(:, ic))
66 ix = nint(chi / mesh%spacing)
67 ipg = mesh_global_index_from_coords(mesh, ix)
68 indices(ic) = ipg
69 enddo
70
72
74
75
78 subroutine test_isdf(namespace)
79 type(namespace_t), intent(in) :: namespace
80
81 type(electrons_t), pointer :: sys
82 integer :: i
83 real(real64), parameter :: LMM_R_SINGLE_ATOM = 100.0_real64
84
85 ! Centroids
86 integer :: n_duplicates
87 integer :: cnt, unit
88 integer(int64) :: rng_seed
89 integer(int64), allocatable :: indices(:), unique_indices(:)
90 real(real64), allocatable :: centroid_positions(:, :)
91 character(len=1), allocatable :: dummy_species(:)
92
93 ! ISDF
94 type(isdf_options_t) :: isdf_options
95 logical :: output_cubes
96 real(real64), allocatable :: phi(:, :)
97 real(real64), allocatable :: isdf_vectors(:, :)
98
99 push_sub(test_isdf)
100
101 call messages_write('Info: Testing ISDF')
102 call messages_new_line()
103 call messages_new_line()
104 call messages_info(namespace=namespace)
105
106 ! Set up a system of electrons
107 call calc_mode_par%set_parallelization(p_strategy_states, default=.false.)
108 ! If generate_epot is false, the code will crash in v_ks_calc
109 sys => electrons_t(namespace, generate_epot=.true.)
110 call sys%init_parallelization(mpi_world)
111
112 ! Initialise a view of the wave functions
113 ! Note, this does not change the underlying data layout of the states
114 call states_elec_allocate_wfns(sys%st, sys%gr, wfs_type = type_float, packed=.true.)
115
116 ! Guess at the states using lcao
117 call lcao_run(namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, &
118 sys%st, sys%ks, sys%hm, lmm_r = lmm_r_single_atom)
119
120 call isdf_options%init(namespace, sys%st)
121
122 ! Perform kmeans - Random seed fixed for test reproducibility
123 rng_seed = int(101, int64)
124 safe_allocate(centroid_positions(1:sys%space%dim, 1:isdf_options%n_interp))
125
126 call sample_initial_centroids(sys%gr, centroid_positions, seed_value=rng_seed)
127 if (debug%info) then
128 allocate(dummy_species(isdf_options%n_interp), source='A')
129 call io_mkdir(static_dir, namespace)
130 call write_standard_xyz_file(namespace, static_dir // "/initial_centroids", centroid_positions, dummy_species)
131 endif
132
133 call weighted_kmeans(sys%space, sys%gr, sys%st%rho(1:sys%gr%np, 1), centroid_positions)
134
135 if (debug%info) then
136 dummy_species = 'B'
137 call write_standard_xyz_file(namespace, static_dir // "/final_centroids", centroid_positions, dummy_species)
138 endif
139
140 ! Convert positions to indices
141 safe_allocate(indices(1:isdf_options%n_interp))
142 call map_centroid_positions_to_indices(sys%gr, centroid_positions, indices)
143
144 ! Output the centroid indices so they can be asserted on
145 if (mpi_world%is_root()) then
146 open(newunit=unit, file="centroid_indices.dat")
147 write(unit, *) 'N centroids', isdf_options%n_interp
148 do i = 1, isdf_options%n_interp
149 write(unit, *) indices(i)
150 enddo
151 close(unit)
152 endif
153
154 ! Confirm no duplicates are present
155 call sort(indices)
156
157 ! For the sake of testing, remove any duplicates
158 allocate(unique_indices(isdf_options%n_interp))
159
160 n_duplicates = 0
161 cnt = 1
162 unique_indices(1) = indices(1)
163 do i = 1, isdf_options%n_interp - 1
164 if (indices(i) == indices(i+1)) then
165 n_duplicates = n_duplicates + 1
166 cycle
167 endif
168 cnt = cnt + 1
169 unique_indices(cnt) = indices(i+1)
170 enddo
171 safe_deallocate_a(indices)
172 allocate(indices(cnt), source=unique_indices(1:cnt))
173 deallocate(unique_indices)
174
175 if (n_duplicates > 0) then
176 write(message(1), '(I0)') n_duplicates
177 message(1) = trim(message(1)) // " duplicates found after discretisation of centroid positions"
178 write(message(2), '(I0)') cnt
179 message(2) = " Removed the duplicate/s and resized 'indices' array to " // trim(message(2))
180 call messages_warning(2)
181 !call messages_fatal(1)
182 endif
183
184 ! ISDF Testing - Serial code
185 if (.not. sys%st%parallel_in_states .and. .not. sys%gr%parallel_in_domains) then
186
187 ! Returns isdf_vectors, and phi for reuse
189 sys%gr, sys%st, indices, phi, isdf_vectors)
190
191 ! Error quantification and visualisation
192 output_cubes = .false.
193
194 ! This deallocates phi and isdf_vectors to save memory
195 call quantify_error_and_visualise(namespace, sys%st, sys%space, sys%gr, &
196 sys%ions, phi, indices, isdf_vectors, output_cubes)
197 endif
198
199 call states_elec_deallocate_wfns(sys%st)
200 safe_deallocate_p(sys)
201 safe_deallocate_a(indices)
202
203 pop_sub(test_isdf)
204
205 end subroutine test_isdf
206
207end module test_isdf_oct_m
208
209!! Local Variables:
210!! mode: f90
211!! coding: utf-8
212!! End:
This is the common interface to a sorting routine. It performs the shell algorithm,...
Definition: sort.F90:149
This module handles the calculation mode.
type(calc_mode_par_t), public calc_mode_par
Singleton instance of parallel calculation mode.
integer, parameter, public p_strategy_states
parallelization in states
type(debug_t), save, public debug
Definition: debug.F90:156
character(len= *), parameter, public static_dir
Definition: global.F90:252
subroutine, public write_standard_xyz_file(namespace, fname, pos, species, header)
Write a standard xyz file with atom labels and positions (in Angstrom).
Definition: io.F90:114
subroutine, public io_close(iunit, grp)
Definition: io.F90:418
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:311
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:352
Serial prototype for benchmarking and validating ISDF implementation.
subroutine, public serial_interpolative_separable_density_fitting_vectors(namespace, mesh, st, int_indices, phi, isdf_vectors)
Compute a set of ISDF interpolation vectors in serial, for code validation.
subroutine, public quantify_error_and_visualise(namespace, st, space, mesh, ions, phi, indices, isdf_vectors, output_cubes)
Wrapper for quantifying the error in the expansion of the product basis.
subroutine, public weighted_kmeans(space, mesh, weight, centroids, n_iter, centroid_tol, discretize, inertia)
Weighted K-means clustering.
subroutine, public sample_initial_centroids(mesh, centroids, seed_value)
Sample initial centroids from the full mesh.
subroutine, public lcao_run(namespace, space, gr, ions, ext_partners, st, ks, hm, st_start, lmm_r)
Definition: lcao.F90:808
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
integer(int64) function, public mesh_global_index_from_coords(mesh, ix)
This function returns the true global index of the point for a given vector of integer coordinates.
Definition: mesh.F90:920
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:537
subroutine, public messages_new_line()
Definition: messages.F90:1134
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:414
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:616
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:270
This module is intended to contain "only mathematical" functions and procedures.
Definition: sort.F90:117
subroutine, public states_elec_deallocate_wfns(st)
Deallocates the KS wavefunctions defined within a states_elec_t structure.
subroutine, public states_elec_allocate_wfns(st, mesh, wfs_type, skip, packed)
Allocates the KS wavefunctions defined within a states_elec_t structure.
Integration tests for ISDF.
Definition: test_isdf.F90:99
subroutine, public test_isdf(namespace)
Set up an electron system, compute some optimal centroid positions, and use these to build a set of I...
Definition: test_isdf.F90:172
subroutine map_centroid_positions_to_indices(mesh, positions, indices)
Helper function: Map centroid positions to indices.
Definition: test_isdf.F90:138
type(type_t), public type_float
Definition: types.F90:133
This module defines the unit system, used for input and output.
type(unit_t), public unit_angstrom
For XYZ files.
type(unit_t), public unit_one
some special units required for particular quantities
Class describing the electron system.
Definition: electrons.F90:218
int true(void)