Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : MODULE soc_pseudopotential_utils
9 : USE cp_cfm_basic_linalg, ONLY: cp_cfm_scale,&
10 : cp_cfm_scale_and_add,&
11 : cp_cfm_scale_and_add_fm,&
12 : cp_cfm_transpose
13 : USE cp_cfm_types, ONLY: cp_cfm_create,&
14 : cp_cfm_get_info,&
15 : cp_cfm_release,&
16 : cp_cfm_set_all,&
17 : cp_cfm_to_fm,&
18 : cp_cfm_type,&
19 : cp_fm_to_cfm
20 : USE cp_dbcsr_api, ONLY: dbcsr_type
21 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm
22 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
23 : cp_fm_struct_release,&
24 : cp_fm_struct_type
25 : USE cp_fm_types, ONLY: cp_fm_create,&
26 : cp_fm_get_info,&
27 : cp_fm_release,&
28 : cp_fm_set_all,&
29 : cp_fm_to_fm_submat,&
30 : cp_fm_type
31 : USE kinds, ONLY: dp
32 : USE mathconstants, ONLY: gaussi,&
33 : z_one,&
34 : z_zero
35 : #include "./base/base_uses.f90"
36 :
37 : IMPLICIT NONE
38 :
39 : PRIVATE
40 :
41 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'soc_pseudopotential_utils'
42 :
43 : PUBLIC :: add_dbcsr_submat, cfm_add_on_diag, add_fm_submat, add_cfm_submat, &
44 : get_cfm_submat, create_cfm_double
45 :
46 : CONTAINS
47 :
48 : ! **************************************************************************************************
49 : !> \brief ...
50 : !> \param cfm_mat_target ...
51 : !> \param mat_source ...
52 : !> \param fm_struct_source ...
53 : !> \param nstart_row ...
54 : !> \param nstart_col ...
55 : !> \param factor ...
56 : !> \param add_also_herm_conj ...
57 : ! **************************************************************************************************
58 288 : SUBROUTINE add_dbcsr_submat(cfm_mat_target, mat_source, fm_struct_source, &
59 : nstart_row, nstart_col, factor, add_also_herm_conj)
60 : TYPE(cp_cfm_type) :: cfm_mat_target
61 : TYPE(dbcsr_type) :: mat_source
62 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_source
63 : INTEGER :: nstart_row, nstart_col
64 : COMPLEX(KIND=dp) :: factor
65 : LOGICAL :: add_also_herm_conj
66 :
67 : CHARACTER(LEN=*), PARAMETER :: routineN = 'add_dbcsr_submat'
68 :
69 : INTEGER :: handle, nao
70 : TYPE(cp_cfm_type) :: cfm_mat_work_double, &
71 : cfm_mat_work_double_2
72 : TYPE(cp_fm_type) :: fm_mat_work_double_im, fm_mat_work_im
73 :
74 48 : CALL timeset(routineN, handle)
75 :
76 48 : CALL cp_fm_create(fm_mat_work_double_im, cfm_mat_target%matrix_struct)
77 48 : CALL cp_fm_set_all(fm_mat_work_double_im, 0.0_dp)
78 :
79 48 : CALL cp_cfm_create(cfm_mat_work_double, cfm_mat_target%matrix_struct)
80 48 : CALL cp_cfm_create(cfm_mat_work_double_2, cfm_mat_target%matrix_struct)
81 48 : CALL cp_cfm_set_all(cfm_mat_work_double, z_zero)
82 48 : CALL cp_cfm_set_all(cfm_mat_work_double_2, z_zero)
83 :
84 48 : CALL cp_fm_create(fm_mat_work_im, fm_struct_source)
85 :
86 48 : CALL copy_dbcsr_to_fm(mat_source, fm_mat_work_im)
87 :
88 48 : CALL cp_fm_get_info(fm_mat_work_im, nrow_global=nao)
89 :
90 : CALL cp_fm_to_fm_submat(msource=fm_mat_work_im, mtarget=fm_mat_work_double_im, &
91 : nrow=nao, ncol=nao, &
92 : s_firstrow=1, s_firstcol=1, &
93 48 : t_firstrow=nstart_row, t_firstcol=nstart_col)
94 : ! careful: inside add_dbcsr_submat, mat_V_SOC_xyz is multiplied by i because the real matrix
95 : ! mat_V_SOC_xyz is antisymmetric as V_SOC matrix is purely imaginary and Hermitian
96 48 : CALL cp_cfm_scale_and_add_fm(z_zero, cfm_mat_work_double, gaussi, fm_mat_work_double_im)
97 :
98 48 : CALL cp_cfm_scale(factor, cfm_mat_work_double)
99 :
100 48 : CALL cp_cfm_scale_and_add(z_one, cfm_mat_target, z_one, cfm_mat_work_double)
101 :
102 48 : IF (add_also_herm_conj) THEN
103 24 : CALL cp_cfm_transpose(cfm_mat_work_double, 'C', cfm_mat_work_double_2)
104 24 : CALL cp_cfm_scale_and_add(z_one, cfm_mat_target, z_one, cfm_mat_work_double_2)
105 : END IF
106 :
107 48 : CALL cp_fm_release(fm_mat_work_double_im)
108 48 : CALL cp_cfm_release(cfm_mat_work_double)
109 48 : CALL cp_cfm_release(cfm_mat_work_double_2)
110 48 : CALL cp_fm_release(fm_mat_work_im)
111 :
112 48 : CALL timestop(handle)
113 :
114 48 : END SUBROUTINE add_dbcsr_submat
115 :
116 : ! **************************************************************************************************
117 : !> \brief ...
118 : !> \param cfm ...
119 : !> \param alpha ...
120 : ! **************************************************************************************************
121 480 : SUBROUTINE cfm_add_on_diag(cfm, alpha)
122 :
123 : TYPE(cp_cfm_type) :: cfm
124 : REAL(KIND=dp), DIMENSION(:) :: alpha
125 :
126 : CHARACTER(LEN=*), PARAMETER :: routineN = 'cfm_add_on_diag'
127 :
128 : INTEGER :: handle, i_global, i_row, j_col, &
129 : j_global, nao, ncol_local, nrow_local
130 480 : INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
131 :
132 480 : CALL timeset(routineN, handle)
133 :
134 : CALL cp_cfm_get_info(matrix=cfm, &
135 : nrow_local=nrow_local, &
136 : ncol_local=ncol_local, &
137 : row_indices=row_indices, &
138 480 : col_indices=col_indices)
139 :
140 480 : nao = SIZE(alpha)
141 :
142 9760 : DO j_col = 1, ncol_local
143 9280 : j_global = col_indices(j_col)
144 102240 : DO i_row = 1, nrow_local
145 92480 : i_global = row_indices(i_row)
146 101760 : IF (j_global == i_global) THEN
147 4640 : IF (i_global .LE. nao) THEN
148 : cfm%local_data(i_row, j_col) = cfm%local_data(i_row, j_col) + &
149 4640 : alpha(i_global)*z_one
150 : ELSE
151 : cfm%local_data(i_row, j_col) = cfm%local_data(i_row, j_col) + &
152 0 : alpha(i_global - nao)*z_one
153 : END IF
154 : END IF
155 : END DO
156 : END DO
157 :
158 480 : CALL timestop(handle)
159 :
160 480 : END SUBROUTINE cfm_add_on_diag
161 :
162 : ! **************************************************************************************************
163 : !> \brief ...
164 : !> \param cfm_mat_target ...
165 : !> \param fm_mat_source ...
166 : !> \param nstart_row ...
167 : !> \param nstart_col ...
168 : ! **************************************************************************************************
169 0 : SUBROUTINE add_fm_submat(cfm_mat_target, fm_mat_source, nstart_row, nstart_col)
170 :
171 : TYPE(cp_cfm_type) :: cfm_mat_target
172 : TYPE(cp_fm_type) :: fm_mat_source
173 : INTEGER :: nstart_row, nstart_col
174 :
175 : CHARACTER(LEN=*), PARAMETER :: routineN = 'add_fm_submat'
176 :
177 : INTEGER :: handle, nao
178 : TYPE(cp_fm_type) :: fm_mat_work_double_re
179 :
180 0 : CALL timeset(routineN, handle)
181 :
182 0 : CALL cp_fm_create(fm_mat_work_double_re, cfm_mat_target%matrix_struct)
183 0 : CALL cp_fm_set_all(fm_mat_work_double_re, 0.0_dp)
184 :
185 0 : CALL cp_fm_get_info(fm_mat_source, nrow_global=nao)
186 :
187 : CALL cp_fm_to_fm_submat(msource=fm_mat_source, mtarget=fm_mat_work_double_re, &
188 : nrow=nao, ncol=nao, &
189 : s_firstrow=1, s_firstcol=1, &
190 0 : t_firstrow=nstart_row, t_firstcol=nstart_col)
191 :
192 0 : CALL cp_cfm_scale_and_add_fm(z_one, cfm_mat_target, z_one, fm_mat_work_double_re)
193 :
194 0 : CALL cp_fm_release(fm_mat_work_double_re)
195 :
196 0 : CALL timestop(handle)
197 :
198 0 : END SUBROUTINE add_fm_submat
199 :
200 : ! **************************************************************************************************
201 : !> \brief ...
202 : !> \param cfm_mat_target ...
203 : !> \param cfm_mat_source ...
204 : !> \param nstart_row ...
205 : !> \param nstart_col ...
206 : !> \param factor ...
207 : ! **************************************************************************************************
208 15600 : SUBROUTINE add_cfm_submat(cfm_mat_target, cfm_mat_source, nstart_row, nstart_col, factor)
209 :
210 : TYPE(cp_cfm_type) :: cfm_mat_target, cfm_mat_source
211 : INTEGER :: nstart_row, nstart_col
212 : COMPLEX(KIND=dp), OPTIONAL :: factor
213 :
214 : CHARACTER(LEN=*), PARAMETER :: routineN = 'add_cfm_submat'
215 :
216 : COMPLEX(KIND=dp) :: factor_im, factor_re
217 : INTEGER :: handle, nao
218 : TYPE(cp_fm_type) :: fm_mat_source_im, fm_mat_source_re, &
219 : fm_mat_work_double_im, &
220 : fm_mat_work_double_re
221 :
222 2600 : CALL timeset(routineN, handle)
223 :
224 2600 : CALL cp_fm_create(fm_mat_work_double_re, cfm_mat_target%matrix_struct)
225 2600 : CALL cp_fm_create(fm_mat_work_double_im, cfm_mat_target%matrix_struct)
226 2600 : CALL cp_fm_set_all(fm_mat_work_double_re, 0.0_dp)
227 2600 : CALL cp_fm_set_all(fm_mat_work_double_im, 0.0_dp)
228 :
229 2600 : CALL cp_fm_create(fm_mat_source_re, cfm_mat_source%matrix_struct)
230 2600 : CALL cp_fm_create(fm_mat_source_im, cfm_mat_source%matrix_struct)
231 2600 : CALL cp_cfm_to_fm(cfm_mat_source, fm_mat_source_re, fm_mat_source_im)
232 :
233 2600 : CALL cp_cfm_get_info(cfm_mat_source, nrow_global=nao)
234 :
235 : CALL cp_fm_to_fm_submat(msource=fm_mat_source_re, mtarget=fm_mat_work_double_re, &
236 : nrow=nao, ncol=nao, &
237 : s_firstrow=1, s_firstcol=1, &
238 2600 : t_firstrow=nstart_row, t_firstcol=nstart_col)
239 :
240 : CALL cp_fm_to_fm_submat(msource=fm_mat_source_im, mtarget=fm_mat_work_double_im, &
241 : nrow=nao, ncol=nao, &
242 : s_firstrow=1, s_firstcol=1, &
243 2600 : t_firstrow=nstart_row, t_firstcol=nstart_col)
244 :
245 2600 : IF (PRESENT(factor)) THEN
246 160 : factor_re = factor
247 160 : factor_im = gaussi*factor
248 : ELSE
249 2440 : factor_re = z_one
250 2440 : factor_im = gaussi
251 : END IF
252 :
253 2600 : CALL cp_cfm_scale_and_add_fm(z_one, cfm_mat_target, factor_re, fm_mat_work_double_re)
254 2600 : CALL cp_cfm_scale_and_add_fm(z_one, cfm_mat_target, factor_im, fm_mat_work_double_im)
255 :
256 2600 : CALL cp_fm_release(fm_mat_work_double_re)
257 2600 : CALL cp_fm_release(fm_mat_work_double_im)
258 2600 : CALL cp_fm_release(fm_mat_source_re)
259 2600 : CALL cp_fm_release(fm_mat_source_im)
260 :
261 2600 : CALL timestop(handle)
262 :
263 2600 : END SUBROUTINE add_cfm_submat
264 :
265 : ! **************************************************************************************************
266 : !> \brief ...
267 : !> \param cfm_mat_target ...
268 : !> \param cfm_mat_source ...
269 : !> \param nstart_row ...
270 : !> \param nstart_col ...
271 : ! **************************************************************************************************
272 1152 : SUBROUTINE get_cfm_submat(cfm_mat_target, cfm_mat_source, nstart_row, nstart_col)
273 :
274 : TYPE(cp_cfm_type) :: cfm_mat_target, cfm_mat_source
275 : INTEGER :: nstart_row, nstart_col
276 :
277 : CHARACTER(LEN=*), PARAMETER :: routineN = 'get_cfm_submat'
278 :
279 : INTEGER :: handle, nao
280 : TYPE(cp_fm_type) :: fm_mat_source_double_im, &
281 : fm_mat_source_double_re, &
282 : fm_mat_work_im, fm_mat_work_re
283 :
284 192 : CALL timeset(routineN, handle)
285 :
286 192 : CALL cp_fm_create(fm_mat_source_double_re, cfm_mat_source%matrix_struct)
287 192 : CALL cp_fm_create(fm_mat_source_double_im, cfm_mat_source%matrix_struct)
288 192 : CALL cp_cfm_to_fm(cfm_mat_source, fm_mat_source_double_re, fm_mat_source_double_im)
289 :
290 192 : CALL cp_fm_create(fm_mat_work_re, cfm_mat_target%matrix_struct)
291 192 : CALL cp_fm_create(fm_mat_work_im, cfm_mat_target%matrix_struct)
292 192 : CALL cp_fm_set_all(fm_mat_work_re, 0.0_dp)
293 192 : CALL cp_fm_set_all(fm_mat_work_im, 0.0_dp)
294 :
295 192 : CALL cp_cfm_get_info(cfm_mat_target, nrow_global=nao)
296 :
297 : CALL cp_fm_to_fm_submat(msource=fm_mat_source_double_re, mtarget=fm_mat_work_re, &
298 : nrow=nao, ncol=nao, &
299 : s_firstrow=nstart_row, s_firstcol=nstart_col, &
300 192 : t_firstrow=1, t_firstcol=1)
301 :
302 : CALL cp_fm_to_fm_submat(msource=fm_mat_source_double_im, mtarget=fm_mat_work_im, &
303 : nrow=nao, ncol=nao, &
304 : s_firstrow=nstart_row, s_firstcol=nstart_col, &
305 192 : t_firstrow=1, t_firstcol=1)
306 :
307 192 : CALL cp_fm_to_cfm(fm_mat_work_re, fm_mat_work_im, cfm_mat_target)
308 :
309 192 : CALL cp_fm_release(fm_mat_work_re)
310 192 : CALL cp_fm_release(fm_mat_work_im)
311 192 : CALL cp_fm_release(fm_mat_source_double_re)
312 192 : CALL cp_fm_release(fm_mat_source_double_im)
313 :
314 192 : CALL timestop(handle)
315 :
316 192 : END SUBROUTINE get_cfm_submat
317 :
318 : ! **************************************************************************************************
319 : !> \brief ...
320 : !> \param cfm_double ...
321 : !> \param fm_orig ...
322 : !> \param cfm_orig ...
323 : ! **************************************************************************************************
324 464 : SUBROUTINE create_cfm_double(cfm_double, fm_orig, cfm_orig)
325 : TYPE(cp_cfm_type) :: cfm_double
326 : TYPE(cp_fm_type), OPTIONAL :: fm_orig
327 : TYPE(cp_cfm_type), OPTIONAL :: cfm_orig
328 :
329 : CHARACTER(LEN=*), PARAMETER :: routineN = 'create_cfm_double'
330 :
331 : INTEGER :: handle, ncol_global_orig, &
332 : nrow_global_orig
333 : LOGICAL :: do_cfm_templ, do_fm_templ
334 : TYPE(cp_fm_struct_type), POINTER :: matrix_struct, matrix_struct_double
335 :
336 232 : CALL timeset(routineN, handle)
337 :
338 232 : do_fm_templ = PRESENT(fm_orig)
339 232 : do_cfm_templ = PRESENT(cfm_orig)
340 :
341 : ! either fm template or cfm template
342 232 : CPASSERT(do_fm_templ .NEQV. do_cfm_templ)
343 :
344 232 : IF (do_fm_templ) THEN
345 : CALL cp_fm_get_info(matrix=fm_orig, nrow_global=nrow_global_orig, &
346 12 : ncol_global=ncol_global_orig)
347 12 : matrix_struct => fm_orig%matrix_struct
348 : END IF
349 232 : IF (do_cfm_templ) THEN
350 : CALL cp_cfm_get_info(matrix=cfm_orig, nrow_global=nrow_global_orig, &
351 220 : ncol_global=ncol_global_orig)
352 220 : matrix_struct => cfm_orig%matrix_struct
353 : END IF
354 :
355 : CALL cp_fm_struct_create(matrix_struct_double, &
356 : nrow_global=2*nrow_global_orig, &
357 : ncol_global=2*ncol_global_orig, &
358 232 : template_fmstruct=matrix_struct)
359 :
360 232 : CALL cp_cfm_create(cfm_double, matrix_struct_double)
361 :
362 232 : CALL cp_cfm_set_all(cfm_double, z_zero)
363 :
364 232 : CALL cp_fm_struct_release(matrix_struct_double)
365 :
366 232 : CALL timestop(handle)
367 :
368 232 : END SUBROUTINE create_cfm_double
369 :
370 : END MODULE soc_pseudopotential_utils
|