1!--------------------------------------------------------------------------------------------------!
2!   CP2K: A general program to perform molecular dynamics simulations                              !
3!   Copyright (C) 2000 - 2019  CP2K developers group                                               !
4!--------------------------------------------------------------------------------------------------!
5
6! **************************************************************************************************
7!> \brief New version of the module for the localization of the molecular orbitals
8!>      This should be able to use different definition of the spread functional
9!>      It should also calculate the integrals analytically so that it can be
10!>      used irrespective of the pw_env and the collocation of wfn on the grids
11!>      It should also work with a selected set of states, instead than all of them,
12!>      in this case one should check that the selected states have the same occupation number
13!>      The spread functional can be only estimated, or also optimized by minimization
14!>      and in principle also maximization should be available.
15!>      This operations can be required irrespective of the printing requirements
16!>      It would be highly desirable to do all this along a MD run every N steps,
17!>      and have a trajectory of the centeroids of the localized wfn
18!>      In addition these functions can be used for properties calculations
19!>      like NMR and XAS. Therefore it is necessary that the rotated wfn are then copied
20!>      in the mos fm matrix to be available for next use.
21!> \author MI (05-2005)
22! **************************************************************************************************
23MODULE qs_loc_types
24
25   USE cell_types,                      ONLY: cell_release,&
26                                              cell_retain,&
27                                              cell_type
28   USE cp_array_utils,                  ONLY: cp_2d_r_p_type
29   USE cp_fm_types,                     ONLY: cp_fm_p_type,&
30                                              cp_fm_release
31   USE cp_para_env,                     ONLY: cp_para_env_release,&
32                                              cp_para_env_retain
33   USE cp_para_types,                   ONLY: cp_para_env_type
34   USE dbcsr_api,                       ONLY: dbcsr_deallocate_matrix,&
35                                              dbcsr_p_type
36   USE distribution_1d_types,           ONLY: distribution_1d_release,&
37                                              distribution_1d_retain,&
38                                              distribution_1d_type
39   USE kinds,                           ONLY: default_string_length,&
40                                              dp
41   USE particle_types,                  ONLY: particle_type
42#include "./base/base_uses.f90"
43
44   IMPLICIT NONE
45
46   PRIVATE
47
48! *** Global parameters ***
49
50   CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_loc_types'
51
52!****t* qs_loc_types/qs_loc_env_new_type [1.0] *
53
54! **************************************************************************************************
55!> \brief contains all the info needed by quickstep to calculate
56!>      the spread of a selected set of orbitals and if required
57!>      to minimize or maximize the spread by rotation of the orbitals
58!> \param para_env info for the distribution of the calculations
59!> \param mo_coeff full matrix containing only the selected subset of orbitals
60!> \param local_molecules molecules distributed
61!> \param cell box that contains the system
62!> \param localized_wfn_control variables and parameter that define the spread
63!>                             functional and the optimization algorithm
64!> \param particle_set position, type, ao_indexes etc for each atom
65!> \param op_sm_set set of sparse matrices used to define the spread operator
66!>                  when the functional is defined by the use operator acting on the
67!>                  basis functions, e.g. the Berry phase definition
68!>                  The matrix element of the type <a|O|b> are computed in initialization
69!>                  of qs_loc_env
70!> \param op_fm_set set of full matrices used to define the spread operator
71!>                 when the functional has to be defined directly using the products of MOS
72!>                 as in the case of the Pipek-Mezek definition.
73!> \param weights for a spread defined as extension of the orbitral in the box, these
74!>               factors renormalize with respect to the box size
75!> \note
76!>      this type should replace the previous set up for the localization of the wfn
77!> \par History
78!>      04-05 created
79!> \author MI
80! **************************************************************************************************
81   TYPE qs_loc_env_new_type
82      INTEGER :: ref_count
83      LOGICAL :: molecular_states, do_localize, first_time
84      LOGICAL :: wannier_states
85      CHARACTER(LEN=default_string_length)        :: tag_mo
86      TYPE(cp_para_env_type), POINTER          :: para_env
87      TYPE(cp_fm_p_type), DIMENSION(:), &
88         POINTER                                :: moloc_coeff
89      TYPE(cp_fm_p_type), DIMENSION(:, :), &
90         POINTER                                :: op_fm_set
91      TYPE(distribution_1d_type), POINTER         :: local_molecules
92      TYPE(cell_type), POINTER                 :: cell
93      TYPE(localized_wfn_control_type), &
94         POINTER                                :: localized_wfn_control
95      TYPE(particle_type), DIMENSION(:), &
96         POINTER                                :: particle_set
97      TYPE(dbcsr_p_type), DIMENSION(:, :), &
98         POINTER                                :: op_sm_set
99
100      REAL(KIND=dp)                            :: start_time, target_time
101      REAL(KIND=dp)                            :: weights(6)
102      INTEGER                                     :: dim_op
103   END TYPE qs_loc_env_new_type
104
105! **************************************************************************************************
106!> \brief A type that holds controling information for the
107!>    calculation of the spread of wfn and the optimization of
108!>    the spread functional
109!> \param ref_count ...
110!> \param localization_method which algorithm is used for the optimization
111!> \param operator_type how the spread is defined
112!> \param nloc_states number of states on which the spread is computed
113!> \param set_of_states how to choose the states
114!> \param lu_bound_states lower and upper bounds of the set of states
115!>    print_cubes:
116!>    print_centers:
117!>    print_spreads:
118!> \param loc_states list of states on which the spread is computed
119!> \param centers_set arrais containing centers and spreads of the selected wfn
120!> \param centers_file_name output file names
121!> \param spreads_file_name output file names
122! **************************************************************************************************
123   TYPE localized_wfn_control_type
124      INTEGER                              :: ref_count
125      INTEGER                              :: min_or_max
126      INTEGER                              :: localization_method
127      INTEGER                              :: operator_type
128      INTEGER, DIMENSION(2)                :: nloc_states
129      INTEGER                              :: set_of_states
130      INTEGER, DIMENSION(2, 2)              :: lu_bound_states
131      INTEGER                              :: max_iter
132      INTEGER                              :: out_each
133      REAL(KIND=dp)                        :: eps_localization
134      REAL(KIND=dp)                        :: max_crazy_angle
135      REAL(KIND=dp)                        :: crazy_scale
136      REAL(KIND=dp)                        :: eps_occ
137      REAL(KIND=dp), DIMENSION(2)          :: lu_ene_bound
138      LOGICAL                              :: crazy_use_diag
139      LOGICAL                              :: print_cubes, jacobi_fallback, jacobi_refinement
140      LOGICAL                              :: print_centers
141      LOGICAL                              :: print_spreads
142      LOGICAL                              :: do_homo
143      LOGICAL                              :: loc_restart
144      LOGICAL                              :: use_history
145      INTEGER, POINTER, DIMENSION(:, :)       :: loc_states
146      TYPE(cp_2d_r_p_type), DIMENSION(2)   :: centers_set
147   END TYPE localized_wfn_control_type
148
149! *** Public ***
150   PUBLIC :: qs_loc_env_create, qs_loc_env_destroy, &
151             qs_loc_env_release, qs_loc_env_retain, &
152             get_qs_loc_env, set_qs_loc_env, &
153             localized_wfn_control_create, localized_wfn_control_release
154   PUBLIC :: qs_loc_env_new_type, localized_wfn_control_type
155
156CONTAINS
157
158!****f* qs_loc_types/qs_loc_env_create [1.0] *
159
160! **************************************************************************************************
161!> \brief ...
162!> \param qs_loc_env ...
163!> \par History
164!>      04-05 created
165!> \author MI
166! **************************************************************************************************
167   SUBROUTINE qs_loc_env_create(qs_loc_env)
168
169      TYPE(qs_loc_env_new_type), POINTER                 :: qs_loc_env
170
171      CHARACTER(len=*), PARAMETER :: routineN = 'qs_loc_env_create', &
172         routineP = moduleN//':'//routineN
173
174      CPASSERT(.NOT. ASSOCIATED(qs_loc_env))
175
176      ALLOCATE (qs_loc_env)
177
178      qs_loc_env%ref_count = 1
179      qs_loc_env%tag_mo = ""
180      NULLIFY (qs_loc_env%para_env)
181      NULLIFY (qs_loc_env%cell)
182      NULLIFY (qs_loc_env%op_sm_set)
183      NULLIFY (qs_loc_env%op_fm_set)
184      NULLIFY (qs_loc_env%local_molecules)
185      NULLIFY (qs_loc_env%moloc_coeff)
186      NULLIFY (qs_loc_env%particle_set)
187      NULLIFY (qs_loc_env%localized_wfn_control)
188      qs_loc_env%weights = 0.0_dp
189
190   END SUBROUTINE qs_loc_env_create
191
192!****f* qs_loc_types/qs_loc_env_destroy [1.0] *
193
194! **************************************************************************************************
195!> \brief ...
196!> \param qs_loc_env ...
197!> \par History
198!>      04-05 created
199!> \author MI
200! **************************************************************************************************
201   SUBROUTINE qs_loc_env_destroy(qs_loc_env)
202
203      TYPE(qs_loc_env_new_type), POINTER                 :: qs_loc_env
204
205      CHARACTER(len=*), PARAMETER :: routineN = 'qs_loc_env_destroy', &
206         routineP = moduleN//':'//routineN
207
208      INTEGER                                            :: i, ii, j
209
210      CPASSERT(ASSOCIATED(qs_loc_env))
211
212      IF (ASSOCIATED(qs_loc_env%cell)) CALL cell_release(qs_loc_env%cell)
213      IF (ASSOCIATED(qs_loc_env%local_molecules)) &
214         CALL distribution_1d_release(qs_loc_env%local_molecules)
215      IF (ASSOCIATED(qs_loc_env%localized_wfn_control)) THEN
216         CALL localized_wfn_control_release(qs_loc_env%localized_wfn_control)
217      END IF
218      IF (ASSOCIATED(qs_loc_env%para_env)) CALL cp_para_env_release(qs_loc_env%para_env)
219      IF (ASSOCIATED(qs_loc_env%particle_set)) NULLIFY (qs_loc_env%particle_set)
220
221      IF (ASSOCIATED(qs_loc_env%moloc_coeff)) THEN
222         DO i = 1, SIZE(qs_loc_env%moloc_coeff, 1)
223            ii = LBOUND(qs_loc_env%moloc_coeff, 1) + i - 1
224            CALL cp_fm_release(qs_loc_env%moloc_coeff(ii)%matrix)
225         END DO
226         DEALLOCATE (qs_loc_env%moloc_coeff)
227      END IF
228
229      IF (ASSOCIATED(qs_loc_env%op_fm_set)) THEN
230         DO i = 1, SIZE(qs_loc_env%op_fm_set, 2)
231            DO j = 1, SIZE(qs_loc_env%op_fm_set, 1)
232               CALL cp_fm_release(qs_loc_env%op_fm_set(j, i)%matrix)
233            END DO
234         END DO
235         DEALLOCATE (qs_loc_env%op_fm_set)
236      END IF
237
238      IF (ASSOCIATED(qs_loc_env%op_sm_set)) THEN
239         DO i = 1, SIZE(qs_loc_env%op_sm_set, 2)
240            DO j = 1, SIZE(qs_loc_env%op_sm_set, 1)
241               CALL dbcsr_deallocate_matrix(qs_loc_env%op_sm_set(j, i)%matrix)
242            ENDDO
243         END DO
244         DEALLOCATE (qs_loc_env%op_sm_set)
245      END IF
246
247      DEALLOCATE (qs_loc_env)
248
249   END SUBROUTINE qs_loc_env_destroy
250
251!****f* qs_loc_types/qs_loc_env_release [1.0] *
252
253! **************************************************************************************************
254!> \brief ...
255!> \param qs_loc_env ...
256!> \par History
257!>      04-05 created
258!> \author MI
259! **************************************************************************************************
260   SUBROUTINE qs_loc_env_release(qs_loc_env)
261
262      TYPE(qs_loc_env_new_type), POINTER                 :: qs_loc_env
263
264      CHARACTER(len=*), PARAMETER :: routineN = 'qs_loc_env_release', &
265         routineP = moduleN//':'//routineN
266
267      IF (ASSOCIATED(qs_loc_env)) THEN
268         CPASSERT(qs_loc_env%ref_count > 0)
269         qs_loc_env%ref_count = qs_loc_env%ref_count - 1
270         IF (qs_loc_env%ref_count == 0) THEN
271            CALL qs_loc_env_destroy(qs_loc_env)
272         END IF
273      END IF
274   END SUBROUTINE qs_loc_env_release
275
276!****f* qs_loc_types/qs_loc_env_retain [1.0] *
277
278! **************************************************************************************************
279!> \brief ...
280!> \param qs_loc_env ...
281!> \par History
282!>      04-05 created
283!> \author MI
284! **************************************************************************************************
285   SUBROUTINE qs_loc_env_retain(qs_loc_env)
286
287      TYPE(qs_loc_env_new_type), POINTER                 :: qs_loc_env
288
289      CHARACTER(len=*), PARAMETER :: routineN = 'qs_loc_env_retain', &
290         routineP = moduleN//':'//routineN
291
292      CPASSERT(ASSOCIATED(qs_loc_env))
293      CPASSERT(qs_loc_env%ref_count > 0)
294      qs_loc_env%ref_count = qs_loc_env%ref_count + 1
295   END SUBROUTINE qs_loc_env_retain
296
297! **************************************************************************************************
298!> \brief create the localized_wfn_control_type
299!> \param localized_wfn_control ...
300!> \par History
301!>      04.2005 created [MI]
302! **************************************************************************************************
303   SUBROUTINE localized_wfn_control_create(localized_wfn_control)
304      TYPE(localized_wfn_control_type), POINTER          :: localized_wfn_control
305
306      CHARACTER(len=*), PARAMETER :: routineN = 'localized_wfn_control_create', &
307         routineP = moduleN//':'//routineN
308
309      CPASSERT(.NOT. ASSOCIATED(localized_wfn_control))
310      ALLOCATE (localized_wfn_control)
311
312      localized_wfn_control%ref_count = 1
313      localized_wfn_control%nloc_states = 0
314      localized_wfn_control%lu_bound_states = 0
315      localized_wfn_control%lu_ene_bound = 0.0_dp
316      localized_wfn_control%print_cubes = .FALSE.
317      localized_wfn_control%print_centers = .FALSE.
318      localized_wfn_control%print_spreads = .FALSE.
319      localized_wfn_control%do_homo = .TRUE.
320      localized_wfn_control%use_history = .FALSE.
321      NULLIFY (localized_wfn_control%loc_states)
322      NULLIFY (localized_wfn_control%centers_set(1)%array)
323      NULLIFY (localized_wfn_control%centers_set(2)%array)
324   END SUBROUTINE localized_wfn_control_create
325
326! **************************************************************************************************
327!> \brief release the localized_wfn_control_type
328!> \param localized_wfn_control ...
329!> \par History
330!>      04.2005 created [MI]
331! **************************************************************************************************
332   SUBROUTINE localized_wfn_control_release(localized_wfn_control)
333
334      TYPE(localized_wfn_control_type), POINTER          :: localized_wfn_control
335
336      CHARACTER(len=*), PARAMETER :: routineN = 'localized_wfn_control_release', &
337         routineP = moduleN//':'//routineN
338
339      IF (ASSOCIATED(localized_wfn_control)) THEN
340         CPASSERT(localized_wfn_control%ref_count > 0)
341         localized_wfn_control%ref_count = localized_wfn_control%ref_count - 1
342         IF (localized_wfn_control%ref_count == 0) THEN
343            IF (ASSOCIATED(localized_wfn_control%loc_states)) THEN
344               DEALLOCATE (localized_wfn_control%loc_states)
345            ENDIF
346            IF (ASSOCIATED(localized_wfn_control%centers_set(1)%array)) THEN
347               DEALLOCATE (localized_wfn_control%centers_set(1)%array)
348            ENDIF
349            IF (ASSOCIATED(localized_wfn_control%centers_set(2)%array)) THEN
350               DEALLOCATE (localized_wfn_control%centers_set(2)%array)
351            ENDIF
352            localized_wfn_control%ref_count = 0
353            DEALLOCATE (localized_wfn_control)
354         ENDIF
355      END IF
356   END SUBROUTINE localized_wfn_control_release
357
358! **************************************************************************************************
359!> \brief retain the localized_wfn_control_type
360!> \param localized_wfn_control ...
361!> \par History
362!>      04.2005 created [MI]
363! **************************************************************************************************
364   SUBROUTINE localized_wfn_control_retain(localized_wfn_control)
365      TYPE(localized_wfn_control_type), POINTER          :: localized_wfn_control
366
367      CHARACTER(len=*), PARAMETER :: routineN = 'localized_wfn_control_retain', &
368         routineP = moduleN//':'//routineN
369
370      CPASSERT(ASSOCIATED(localized_wfn_control))
371
372      localized_wfn_control%ref_count = localized_wfn_control%ref_count + 1
373   END SUBROUTINE localized_wfn_control_retain
374
375!****f* qs_loc_types/get_qs_loc_env [1.0] *
376
377! **************************************************************************************************
378!> \brief ...
379!> \param qs_loc_env ...
380!> \param cell ...
381!> \param local_molecules ...
382!> \param localized_wfn_control ...
383!> \param moloc_coeff ...
384!> \param op_sm_set ...
385!> \param op_fm_set ...
386!> \param para_env ...
387!> \param particle_set ...
388!> \param weights ...
389!> \param dim_op ...
390!> \par History
391!>      04-05 created
392!> \author MI
393! **************************************************************************************************
394   SUBROUTINE get_qs_loc_env(qs_loc_env, cell, local_molecules, localized_wfn_control, &
395                             moloc_coeff, op_sm_set, op_fm_set, para_env, particle_set, weights, dim_op)
396
397      TYPE(qs_loc_env_new_type), POINTER                 :: qs_loc_env
398      TYPE(cell_type), OPTIONAL, POINTER                 :: cell
399      TYPE(distribution_1d_type), OPTIONAL, POINTER      :: local_molecules
400      TYPE(localized_wfn_control_type), OPTIONAL, &
401         POINTER                                         :: localized_wfn_control
402      TYPE(cp_fm_p_type), DIMENSION(:), OPTIONAL, &
403         POINTER                                         :: moloc_coeff
404      TYPE(dbcsr_p_type), DIMENSION(:, :), OPTIONAL, &
405         POINTER                                         :: op_sm_set
406      TYPE(cp_fm_p_type), DIMENSION(:, :), OPTIONAL, &
407         POINTER                                         :: op_fm_set
408      TYPE(cp_para_env_type), OPTIONAL, POINTER          :: para_env
409      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
410         POINTER                                         :: particle_set
411      REAL(dp), DIMENSION(6), OPTIONAL                   :: weights
412      INTEGER, OPTIONAL                                  :: dim_op
413
414      CHARACTER(len=*), PARAMETER :: routineN = 'get_qs_loc_env', routineP = moduleN//':'//routineN
415
416      CPASSERT(ASSOCIATED(qs_loc_env))
417
418      IF (PRESENT(cell)) cell => qs_loc_env%cell
419      IF (PRESENT(moloc_coeff)) moloc_coeff => qs_loc_env%moloc_coeff
420      IF (PRESENT(local_molecules)) local_molecules => qs_loc_env%local_molecules
421      IF (PRESENT(localized_wfn_control)) &
422         localized_wfn_control => qs_loc_env%localized_wfn_control
423      IF (PRESENT(op_sm_set)) op_sm_set => qs_loc_env%op_sm_set
424      IF (PRESENT(op_fm_set)) op_fm_set => qs_loc_env%op_fm_set
425      IF (PRESENT(para_env)) para_env => qs_loc_env%para_env
426      IF (PRESENT(particle_set)) particle_set => qs_loc_env%particle_set
427      IF (PRESENT(weights)) weights(1:6) = qs_loc_env%weights(1:6)
428      IF (PRESENT(dim_op)) dim_op = qs_loc_env%dim_op
429
430   END SUBROUTINE get_qs_loc_env
431
432!****f* qs_loc_types/set_qs_loc_env [1.0] *
433
434! **************************************************************************************************
435!> \brief ...
436!> \param qs_loc_env ...
437!> \param cell ...
438!> \param local_molecules ...
439!> \param localized_wfn_control ...
440!> \param moloc_coeff ...
441!> \param op_sm_set ...
442!> \param op_fm_set ...
443!> \param para_env ...
444!> \param particle_set ...
445!> \param weights ...
446!> \param dim_op ...
447!> \par History
448!>      04-05 created
449!> \author MI
450! **************************************************************************************************
451   SUBROUTINE set_qs_loc_env(qs_loc_env, cell, local_molecules, localized_wfn_control, &
452                             moloc_coeff, op_sm_set, op_fm_set, para_env, particle_set, weights, dim_op)
453
454      TYPE(qs_loc_env_new_type), POINTER                 :: qs_loc_env
455      TYPE(cell_type), OPTIONAL, POINTER                 :: cell
456      TYPE(distribution_1d_type), OPTIONAL, POINTER      :: local_molecules
457      TYPE(localized_wfn_control_type), OPTIONAL, &
458         POINTER                                         :: localized_wfn_control
459      TYPE(cp_fm_p_type), DIMENSION(:), OPTIONAL, &
460         POINTER                                         :: moloc_coeff
461      TYPE(dbcsr_p_type), DIMENSION(:, :), OPTIONAL, &
462         POINTER                                         :: op_sm_set
463      TYPE(cp_fm_p_type), DIMENSION(:, :), OPTIONAL, &
464         POINTER                                         :: op_fm_set
465      TYPE(cp_para_env_type), OPTIONAL, POINTER          :: para_env
466      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
467         POINTER                                         :: particle_set
468      REAL(dp), DIMENSION(6), OPTIONAL                   :: weights
469      INTEGER, OPTIONAL                                  :: dim_op
470
471      CHARACTER(len=*), PARAMETER :: routineN = 'set_qs_loc_env', routineP = moduleN//':'//routineN
472
473      INTEGER                                            :: i
474
475      CPASSERT(ASSOCIATED(qs_loc_env))
476      IF (PRESENT(cell)) THEN
477         CALL cell_retain(cell)
478         CALL cell_release(qs_loc_env%cell)
479         qs_loc_env%cell => cell
480      END IF
481
482      IF (PRESENT(local_molecules)) THEN
483         CALL distribution_1d_retain(local_molecules)
484         IF (ASSOCIATED(qs_loc_env%local_molecules)) &
485            CALL distribution_1d_release(qs_loc_env%local_molecules)
486         qs_loc_env%local_molecules => local_molecules
487      END IF
488
489      IF (PRESENT(localized_wfn_control)) THEN
490         CALL localized_wfn_control_retain(localized_wfn_control)
491         CALL localized_wfn_control_release(qs_loc_env%localized_wfn_control)
492         qs_loc_env%localized_wfn_control => localized_wfn_control
493      END IF
494      IF (PRESENT(para_env)) THEN
495         CALL cp_para_env_retain(para_env)
496         CALL cp_para_env_release(qs_loc_env%para_env)
497         qs_loc_env%para_env => para_env
498      END IF
499      IF (PRESENT(particle_set)) qs_loc_env%particle_set => particle_set
500      IF (PRESENT(moloc_coeff)) THEN
501         IF (ASSOCIATED(qs_loc_env%moloc_coeff)) THEN
502            DO i = 1, SIZE(qs_loc_env%moloc_coeff, 1)
503               CALL cp_fm_release(qs_loc_env%moloc_coeff(i)%matrix)
504            END DO
505            DEALLOCATE (qs_loc_env%moloc_coeff)
506         END IF
507         qs_loc_env%moloc_coeff => moloc_coeff
508      END IF
509      IF (PRESENT(op_sm_set)) THEN
510         qs_loc_env%op_sm_set => op_sm_set
511      END IF
512      IF (PRESENT(op_fm_set)) THEN
513         qs_loc_env%op_fm_set => op_fm_set
514      END IF
515      IF (PRESENT(weights)) THEN
516         qs_loc_env%weights = weights
517      END IF
518      IF (PRESENT(dim_op)) THEN
519         qs_loc_env%dim_op = dim_op
520      END IF
521
522   END SUBROUTINE set_qs_loc_env
523
524END MODULE qs_loc_types
525
526