1!--------------------------------------------------------------------------------------------------!
2!   CP2K: A general program to perform molecular dynamics simulations                              !
3!   Copyright (C) 2000 - 2020  CP2K developers group                                               !
4!--------------------------------------------------------------------------------------------------!
5
6! **************************************************************************************************
7!> \brief Types and set/get functions for auxiliary density matrix methods
8!> \par History
9!>      05.2008 created [Manuel Guidon]
10!>      12.2019 Made GAPW compatiblae [Augustin Bussy]
11!> \author Manuel Guidon
12! **************************************************************************************************
13MODULE admm_types
14   USE bibliography,                    ONLY: Guidon2010,&
15                                              cite_reference
16   USE cp_control_types,                ONLY: admm_control_type
17   USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
18                                              cp_fm_struct_release,&
19                                              cp_fm_struct_type
20   USE cp_fm_types,                     ONLY: cp_fm_create,&
21                                              cp_fm_p_type,&
22                                              cp_fm_release,&
23                                              cp_fm_type
24   USE cp_para_types,                   ONLY: cp_para_env_type
25   USE input_constants,                 ONLY: do_admm_blocked_projection,&
26                                              do_admm_blocking_purify_full,&
27                                              do_admm_charge_constrained_projection
28   USE input_section_types,             ONLY: section_vals_release,&
29                                              section_vals_type
30   USE kinds,                           ONLY: dp
31   USE qs_kind_types,                   ONLY: deallocate_qs_kind_set,&
32                                              qs_kind_type
33   USE qs_local_rho_types,              ONLY: local_rho_set_release,&
34                                              local_rho_type
35   USE qs_mo_types,                     ONLY: get_mo_set,&
36                                              mo_set_p_type
37   USE qs_oce_types,                    ONLY: deallocate_oce_set,&
38                                              oce_matrix_type
39   USE task_list_types,                 ONLY: deallocate_task_list,&
40                                              task_list_type
41#include "./base/base_uses.f90"
42
43   IMPLICIT NONE
44   PRIVATE
45   PUBLIC :: admm_env_create, admm_env_release, admm_type, admm_gapw_type
46
47   CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'admm_types'
48
49   TYPE eigvals_type
50      REAL(dp), DIMENSION(:), POINTER          :: DATA
51   END TYPE
52
53   TYPE eigvals_p_type
54      TYPE(eigvals_type), POINTER              :: eigvals
55   END TYPE
56
57! **************************************************************************************************
58!> \brief A subtype of the admm_env that contains the extra data needed for an ADMM GAPW calculation
59!> \param admm_kind_set gets its own qs_kind set to store all relevant basis/grid/etc info
60!> \param local_rho_set caontains soft and hard AUX_FIT atomoc densities
61!> \param task_list the task list used for all soft density pw operations
62!> \param oce stores the precomputed oce integrals
63! **************************************************************************************************
64   TYPE admm_gapw_type
65      TYPE(qs_kind_type), DIMENSION(:), POINTER          :: admm_kind_set => Null()
66      TYPE(local_rho_type), POINTER                      :: local_rho_set => Null()
67      TYPE(task_list_type), POINTER                      :: task_list => Null()
68      TYPE(oce_matrix_type), POINTER                     :: oce => Null()
69   END TYPE admm_gapw_type
70
71! **************************************************************************************************
72!> \brief stores some data used in wavefunction fitting
73!> \param S overlap matrix for auxiliary fit basis set
74!> \param P overlap matrix for mixed aux_fit/orb basis set
75!> \param A contains inv(S)*P
76!> \param B contains transpose(P)*inv(S)*P = transpose(P)*A
77!> \param lambda contains transpose(mo_coeff_aux_fit)*B*mo_coeff_aux_fit
78!> \param lambda_inv_sqrt contains inv(SQRT(lambda))
79!> \param R contains eigenvectors of lambda
80!> \param work_aux_aux temporary matrix
81!> \param work_orb_nmo temporary matrix
82!> \param work_nmo_nmo1 temporary matrix
83!> \param work_nmo_nmo2 temporary matrix
84!> \param work_aux_nmo temporary matrix
85!> \param H contains KS_matrix * mo_coeff for auxiliary basis set
86!> \param K contains KS matrix for auxiliary basis set
87!> \param M contains matrix holding the 2nd order residues
88!> \param nao_orb number of atomic orbitals in orb basis set
89!> \param nao_aux_fit number of atomic orbitals in aux basis set
90!> \param nmo number of molecular orbitals per spin
91!> \param eigvals_lamda eigenvalues of lambda matrix
92!> \param gsi contains ratio N_dens_m/N_aux_dens_m
93!> \param admm_gapw_env the type containing ADMM GAPW specific data
94!> \param do_gapw an internal logical switch for GAPW
95!> \par History
96!>      05.2008 created [Manuel Guidon]
97!> \author Manuel Guidon
98! **************************************************************************************************
99   TYPE admm_type
100      TYPE(cp_fm_type), POINTER                :: S_inv => Null(), &
101                                                  S => Null(), &
102                                                  Q => Null(), &
103                                                  A => Null(), &
104                                                  B => Null(), &
105                                                  work_orb_orb => Null(), &
106                                                  work_orb_orb2 => Null(), &
107                                                  work_orb_orb3 => Null(), &
108                                                  work_aux_orb => Null(), &
109                                                  work_aux_orb2 => Null(), &
110                                                  work_aux_orb3 => Null(), &
111                                                  work_aux_aux => Null(), &
112                                                  work_aux_aux2 => Null(), &
113                                                  work_aux_aux3 => Null(), &
114                                                  work_aux_aux4 => Null(), &
115                                                  work_aux_aux5 => Null()
116
117      TYPE(cp_fm_p_type), DIMENSION(:), &
118         POINTER                                :: lambda => Null(), &
119                                                   lambda_inv => Null(), &
120                                                   lambda_inv_sqrt => Null(), &
121                                                   R => Null(), &
122                                                   R_purify => Null(), &
123                                                   work_orb_nmo => Null(), &
124                                                   work_nmo_nmo1 => Null(), &
125                                                   R_schur_R_t => Null(), &
126                                                   work_nmo_nmo2 => Null(), &
127                                                   work_aux_nmo => Null(), &
128                                                   work_aux_nmo2 => Null(), &
129                                                   H => Null(), &
130                                                   H_corr => Null(), &
131                                                   mo_derivs_tmp => Null(), &
132                                                   K => Null(), &
133                                                   M => Null(), &
134                                                   M_purify => Null(), &
135                                                   P_to_be_purified => Null(), &
136                                                   lambda_inv2 => Null(), &
137                                                   C_hat => Null(), &
138                                                   P_tilde => Null(), &
139                                                   ks_to_be_merged => Null()
140      TYPE(eigvals_p_type), DIMENSION(:), &
141         POINTER                                :: eigvals_lambda => Null(), &
142                                                   eigvals_P_to_be_purified => Null()
143      TYPE(section_vals_type), POINTER         :: xc_section_primary => Null(), &
144                                                  xc_section_aux => Null()
145      REAL(KIND=dp)                            :: gsi(3) = 0.0_dp, &
146                                                  lambda_merlot(2) = 0.0_dp, &
147                                                  n_large_basis(3) = 0.0_dp
148      INTEGER                                  :: nao_orb, nao_aux_fit, nmo(2)
149      INTEGER                                  :: purification_method
150      LOGICAL                                  :: charge_constrain = .FALSE.
151      INTEGER                                  :: scaling_model, &
152                                                  aux_exch_func
153      LOGICAL                                  :: aux_exch_func_param
154      REAL(KIND=dp), DIMENSION(3)              :: aux_x_param
155      LOGICAL                                  :: block_dm = .FALSE.
156      LOGICAL                                  :: block_fit = .FALSE.
157      INTEGER, DIMENSION(:, :), POINTER        :: block_map => Null()
158      TYPE(admm_gapw_type), POINTER            :: admm_gapw_env
159      LOGICAL                                  :: do_gapw = .FALSE.
160   END TYPE
161
162CONTAINS
163
164! **************************************************************************************************
165!> \brief creates ADMM environment, initializes the basic types
166!>
167!> \param admm_env The ADMM env
168!> \param admm_control ...
169!> \param mos the MO's of the orbital basis set
170!> \param mos_aux_fit the MO's of the auxiliary fitting basis set
171!> \param para_env The parallel env
172!> \param natoms ...
173!> \par History
174!>      05.2008 created [Manuel Guidon]
175!> \author Manuel Guidon
176! **************************************************************************************************
177   SUBROUTINE admm_env_create(admm_env, admm_control, mos, mos_aux_fit, para_env, natoms)
178      TYPE(admm_type), POINTER                           :: admm_env
179      TYPE(admm_control_type), POINTER                   :: admm_control
180      TYPE(mo_set_p_type), DIMENSION(:), POINTER         :: mos, mos_aux_fit
181      TYPE(cp_para_env_type), POINTER                    :: para_env
182      INTEGER, INTENT(IN)                                :: natoms
183
184      CHARACTER(LEN=*), PARAMETER :: routineN = 'admm_env_create', &
185         routineP = moduleN//':'//routineN
186
187      INTEGER                                            :: i, iatom, iblock, ispin, j, jatom, &
188                                                            nao_aux_fit, nao_orb, nmo, nspins
189      TYPE(cp_fm_struct_type), POINTER :: fm_struct_aux_aux, fm_struct_aux_nmo, fm_struct_aux_orb, &
190         fm_struct_nmo_nmo, fm_struct_orb_aux, fm_struct_orb_nmo, fm_struct_orb_orb
191      TYPE(cp_fm_type), POINTER                          :: mo_coeff
192
193      CALL cite_reference(Guidon2010)
194
195      ALLOCATE (admm_env)
196
197      nspins = SIZE(mos)
198      CALL get_mo_set(mos(1)%mo_set, mo_coeff=mo_coeff, nmo=nmo, nao=nao_orb)
199      CALL get_mo_set(mos_aux_fit(1)%mo_set, nao=nao_aux_fit)
200      admm_env%nmo = 0
201      admm_env%nao_aux_fit = nao_aux_fit
202      admm_env%nao_orb = nao_orb
203      CALL cp_fm_struct_create(fm_struct_aux_aux, &
204                               context=mo_coeff%matrix_struct%context, &
205                               nrow_global=nao_aux_fit, &
206                               ncol_global=nao_aux_fit, &
207                               para_env=para_env)
208      CALL cp_fm_struct_create(fm_struct_aux_orb, &
209                               context=mo_coeff%matrix_struct%context, &
210                               nrow_global=nao_aux_fit, &
211                               ncol_global=nao_orb, &
212                               para_env=para_env)
213      CALL cp_fm_struct_create(fm_struct_orb_aux, &
214                               context=mo_coeff%matrix_struct%context, &
215                               nrow_global=nao_orb, &
216                               ncol_global=nao_aux_fit, &
217                               para_env=para_env)
218      CALL cp_fm_struct_create(fm_struct_orb_orb, &
219                               context=mo_coeff%matrix_struct%context, &
220                               nrow_global=nao_orb, &
221                               ncol_global=nao_orb, &
222                               para_env=para_env)
223
224      CALL cp_fm_create(admm_env%S, fm_struct_aux_aux, name="aux_fit_overlap")
225      CALL cp_fm_create(admm_env%S_inv, fm_struct_aux_aux, name="aux_fit_overlap_inv")
226      CALL cp_fm_create(admm_env%Q, fm_struct_aux_orb, name="mixed_overlap")
227      CALL cp_fm_create(admm_env%A, fm_struct_aux_orb, name="work_A")
228      CALL cp_fm_create(admm_env%B, fm_struct_orb_orb, name="work_B")
229      CALL cp_fm_create(admm_env%work_orb_orb, fm_struct_orb_orb, name="work_orb_orb")
230      CALL cp_fm_create(admm_env%work_orb_orb2, fm_struct_orb_orb, name="work_orb_orb")
231      CALL cp_fm_create(admm_env%work_orb_orb3, fm_struct_orb_orb, name="work_orb_orb3")
232      CALL cp_fm_create(admm_env%work_aux_orb, fm_struct_aux_orb, name="work_aux_orb")
233      CALL cp_fm_create(admm_env%work_aux_orb2, fm_struct_aux_orb, name="work_aux_orb2")
234      CALL cp_fm_create(admm_env%work_aux_orb3, fm_struct_aux_orb, name="work_aux_orb3")
235      CALL cp_fm_create(admm_env%work_aux_aux, fm_struct_aux_aux, name="work_aux_aux")
236      CALL cp_fm_create(admm_env%work_aux_aux2, fm_struct_aux_aux, name="work_aux_aux2")
237      CALL cp_fm_create(admm_env%work_aux_aux3, fm_struct_aux_aux, name="work_aux_aux3")
238      CALL cp_fm_create(admm_env%work_aux_aux4, fm_struct_aux_aux, name="work_aux_aux4")
239      CALL cp_fm_create(admm_env%work_aux_aux5, fm_struct_aux_aux, name="work_aux_aux5")
240
241      ALLOCATE (admm_env%lambda_inv(nspins))
242      ALLOCATE (admm_env%lambda(nspins))
243      ALLOCATE (admm_env%lambda_inv_sqrt(nspins))
244      ALLOCATE (admm_env%R(nspins))
245      ALLOCATE (admm_env%R_purify(nspins))
246      ALLOCATE (admm_env%work_orb_nmo(nspins))
247      ALLOCATE (admm_env%work_nmo_nmo1(nspins))
248      ALLOCATE (admm_env%R_schur_R_t(nspins))
249      ALLOCATE (admm_env%work_nmo_nmo2(nspins))
250      ALLOCATE (admm_env%eigvals_lambda(nspins))
251      ALLOCATE (admm_env%eigvals_P_to_be_purified(nspins))
252      ALLOCATE (admm_env%H(nspins))
253      ALLOCATE (admm_env%K(nspins))
254      ALLOCATE (admm_env%M(nspins))
255      ALLOCATE (admm_env%M_purify(nspins))
256      ALLOCATE (admm_env%P_to_be_purified(nspins))
257      ALLOCATE (admm_env%work_aux_nmo(nspins))
258      ALLOCATE (admm_env%work_aux_nmo2(nspins))
259      ALLOCATE (admm_env%mo_derivs_tmp(nspins))
260      ALLOCATE (admm_env%H_corr(nspins))
261      ALLOCATE (admm_env%ks_to_be_merged(nspins))
262      ALLOCATE (admm_env%lambda_inv2(nspins))
263      ALLOCATE (admm_env%C_hat(nspins))
264      ALLOCATE (admm_env%P_tilde(nspins))
265
266      DO ispin = 1, nspins
267         CALL get_mo_set(mos(ispin)%mo_set, mo_coeff=mo_coeff, nmo=nmo)
268         admm_env%nmo(ispin) = nmo
269         CALL cp_fm_struct_create(fm_struct_aux_nmo, &
270                                  context=mo_coeff%matrix_struct%context, &
271                                  nrow_global=nao_aux_fit, &
272                                  ncol_global=nmo, &
273                                  para_env=para_env)
274         CALL cp_fm_struct_create(fm_struct_orb_nmo, &
275                                  context=mo_coeff%matrix_struct%context, &
276                                  nrow_global=nao_orb, &
277                                  ncol_global=nmo, &
278                                  para_env=para_env)
279         CALL cp_fm_struct_create(fm_struct_nmo_nmo, &
280                                  context=mo_coeff%matrix_struct%context, &
281                                  nrow_global=nmo, &
282                                  ncol_global=nmo, &
283                                  para_env=para_env)
284
285         CALL cp_fm_create(admm_env%work_orb_nmo(ispin)%matrix, fm_struct_orb_nmo, name="work_orb_nmo")
286         CALL cp_fm_create(admm_env%work_nmo_nmo1(ispin)%matrix, fm_struct_nmo_nmo, name="work_nmo_nmo1")
287         CALL cp_fm_create(admm_env%R_schur_R_t(ispin)%matrix, fm_struct_nmo_nmo, name="R_schur_R_t")
288         CALL cp_fm_create(admm_env%work_nmo_nmo2(ispin)%matrix, fm_struct_nmo_nmo, name="work_nmo_nmo2")
289         CALL cp_fm_create(admm_env%lambda(ispin)%matrix, fm_struct_nmo_nmo, name="lambda")
290         CALL cp_fm_create(admm_env%lambda_inv(ispin)%matrix, fm_struct_nmo_nmo, name="lambda_inv")
291         CALL cp_fm_create(admm_env%lambda_inv_sqrt(ispin)%matrix, fm_struct_nmo_nmo, name="lambda_inv_sqrt")
292         CALL cp_fm_create(admm_env%R(ispin)%matrix, fm_struct_nmo_nmo, name="R")
293         CALL cp_fm_create(admm_env%R_purify(ispin)%matrix, fm_struct_aux_aux, name="R_purify")
294         CALL cp_fm_create(admm_env%K(ispin)%matrix, fm_struct_aux_aux, name="K")
295         CALL cp_fm_create(admm_env%H(ispin)%matrix, fm_struct_aux_nmo, name="H")
296         CALL cp_fm_create(admm_env%H_corr(ispin)%matrix, fm_struct_orb_orb, name="H_corr")
297         CALL cp_fm_create(admm_env%M(ispin)%matrix, fm_struct_nmo_nmo, name="M")
298         CALL cp_fm_create(admm_env%M_purify(ispin)%matrix, fm_struct_aux_aux, name="M aux")
299         CALL cp_fm_create(admm_env%P_to_be_purified(ispin)%matrix, fm_struct_aux_aux, name="P_to_be_purified")
300         CALL cp_fm_create(admm_env%work_aux_nmo(ispin)%matrix, fm_struct_aux_nmo, name="work_aux_nmo")
301         CALL cp_fm_create(admm_env%work_aux_nmo2(ispin)%matrix, fm_struct_aux_nmo, name="work_aux_nmo2")
302         CALL cp_fm_create(admm_env%mo_derivs_tmp(ispin)%matrix, fm_struct_orb_nmo, name="mo_derivs_tmp")
303
304         CALL cp_fm_create(admm_env%lambda_inv2(ispin)%matrix, fm_struct_nmo_nmo, name="lambda_inv2")
305         CALL cp_fm_create(admm_env%C_hat(ispin)%matrix, fm_struct_aux_nmo, name="C_hat")
306         CALL cp_fm_create(admm_env%P_tilde(ispin)%matrix, fm_struct_aux_aux, name="P_tilde")
307
308         CALL cp_fm_create(admm_env%ks_to_be_merged(ispin)%matrix, fm_struct_orb_orb, name="KS_to_be_merged ")
309
310         ALLOCATE (admm_env%eigvals_lambda(ispin)%eigvals)
311         ALLOCATE (admm_env%eigvals_P_to_be_purified(ispin)%eigvals)
312         ALLOCATE (admm_env%eigvals_lambda(ispin)%eigvals%data(nmo))
313         ALLOCATE (admm_env%eigvals_P_to_be_purified(ispin)%eigvals%data(nao_aux_fit))
314         admm_env%eigvals_lambda(ispin)%eigvals%data = 0.0_dp
315         admm_env%eigvals_P_to_be_purified(ispin)%eigvals%data = 0.0_dp
316         CALL cp_fm_struct_release(fm_struct_aux_nmo)
317         CALL cp_fm_struct_release(fm_struct_orb_nmo)
318         CALL cp_fm_struct_release(fm_struct_nmo_nmo)
319      END DO
320
321      CALL cp_fm_struct_release(fm_struct_aux_aux)
322      CALL cp_fm_struct_release(fm_struct_aux_orb)
323      CALL cp_fm_struct_release(fm_struct_orb_aux)
324      CALL cp_fm_struct_release(fm_struct_orb_orb)
325
326      ! copy settings from admm_control
327      admm_env%purification_method = admm_control%purification_method
328      admm_env%scaling_model = admm_control%scaling_model
329      admm_env%aux_exch_func = admm_control%aux_exch_func
330      admm_env%charge_constrain = (admm_control%method == do_admm_charge_constrained_projection)
331      admm_env%block_dm = ((admm_control%method == do_admm_blocking_purify_full) .OR. &
332                           (admm_control%method == do_admm_blocked_projection))
333      admm_env%block_fit = admm_control%method == do_admm_blocked_projection
334      admm_env%aux_exch_func_param = admm_control%aux_exch_func_param
335      admm_env%aux_x_param(:) = admm_control%aux_x_param(:)
336
337      IF ((admm_control%method == do_admm_blocking_purify_full) .OR. &
338          (admm_control%method == do_admm_blocked_projection)) THEN
339         ! create block map
340         ALLOCATE (admm_env%block_map(natoms, natoms))
341         admm_env%block_map(:, :) = 0
342         DO iblock = 1, SIZE(admm_control%blocks)
343            DO i = 1, SIZE(admm_control%blocks(iblock)%list)
344               iatom = admm_control%blocks(iblock)%list(i)
345               DO j = 1, SIZE(admm_control%blocks(iblock)%list)
346                  jatom = admm_control%blocks(iblock)%list(j)
347                  admm_env%block_map(iatom, jatom) = 1
348               END DO
349            END DO
350         END DO
351      ENDIF
352
353      NULLIFY (admm_env%admm_gapw_env)
354      admm_env%do_gapw = .FALSE.
355
356   END SUBROUTINE admm_env_create
357
358! **************************************************************************************************
359!> \brief releases the ADMM environment, cleans up all types
360!>
361!> \param admm_env The ADMM env
362!> \par History
363!>      05.2008 created [Manuel Guidon]
364!> \author Manuel Guidon
365! **************************************************************************************************
366   SUBROUTINE admm_env_release(admm_env)
367      TYPE(admm_type), POINTER                           :: admm_env
368
369      CHARACTER(LEN=*), PARAMETER :: routineN = 'admm_env_release', &
370         routineP = moduleN//':'//routineN
371
372      INTEGER                                            :: ispin
373
374      CALL cp_fm_release(admm_env%S)
375      CALL cp_fm_release(admm_env%S_inv)
376      CALL cp_fm_release(admm_env%Q)
377      CALL cp_fm_release(admm_env%A)
378      CALL cp_fm_release(admm_env%B)
379      CALL cp_fm_release(admm_env%work_orb_orb)
380      CALL cp_fm_release(admm_env%work_orb_orb2)
381      CALL cp_fm_release(admm_env%work_orb_orb3)
382      CALL cp_fm_release(admm_env%work_aux_aux)
383      CALL cp_fm_release(admm_env%work_aux_aux2)
384      CALL cp_fm_release(admm_env%work_aux_aux3)
385      CALL cp_fm_release(admm_env%work_aux_aux4)
386      CALL cp_fm_release(admm_env%work_aux_aux5)
387      CALL cp_fm_release(admm_env%work_aux_orb)
388      CALL cp_fm_release(admm_env%work_aux_orb2)
389      CALL cp_fm_release(admm_env%work_aux_orb3)
390      DO ispin = 1, SIZE(admm_env%lambda)
391         CALL cp_fm_release(admm_env%lambda(ispin)%matrix)
392         CALL cp_fm_release(admm_env%lambda_inv(ispin)%matrix)
393         CALL cp_fm_release(admm_env%lambda_inv_sqrt(ispin)%matrix)
394         CALL cp_fm_release(admm_env%lambda_inv2(ispin)%matrix)
395         CALL cp_fm_release(admm_env%C_hat(ispin)%matrix)
396         CALL cp_fm_release(admm_env%P_tilde(ispin)%matrix)
397         CALL cp_fm_release(admm_env%R(ispin)%matrix)
398         CALL cp_fm_release(admm_env%R_purify(ispin)%matrix)
399         CALL cp_fm_release(admm_env%H(ispin)%matrix)
400         CALL cp_fm_release(admm_env%H_corr(ispin)%matrix)
401         CALL cp_fm_release(admm_env%K(ispin)%matrix)
402         CALL cp_fm_release(admm_env%M(ispin)%matrix)
403         CALL cp_fm_release(admm_env%M_purify(ispin)%matrix)
404         CALL cp_fm_release(admm_env%P_to_be_purified(ispin)%matrix)
405         CALL cp_fm_release(admm_env%work_orb_nmo(ispin)%matrix)
406         CALL cp_fm_release(admm_env%work_nmo_nmo1(ispin)%matrix)
407         CALL cp_fm_release(admm_env%R_schur_R_t(ispin)%matrix)
408         CALL cp_fm_release(admm_env%work_nmo_nmo2(ispin)%matrix)
409         CALL cp_fm_release(admm_env%work_aux_nmo(ispin)%matrix)
410         CALL cp_fm_release(admm_env%work_aux_nmo2(ispin)%matrix)
411         CALL cp_fm_release(admm_env%mo_derivs_tmp(ispin)%matrix)
412         CALL cp_fm_release(admm_env%ks_to_be_merged(ispin)%matrix)
413         CALL cp_fm_release(admm_env%lambda_inv2(ispin)%matrix)
414         DEALLOCATE (admm_env%eigvals_lambda(ispin)%eigvals%data)
415         DEALLOCATE (admm_env%eigvals_P_to_be_purified(ispin)%eigvals%data)
416         DEALLOCATE (admm_env%eigvals_lambda(ispin)%eigvals)
417         DEALLOCATE (admm_env%eigvals_P_to_be_purified(ispin)%eigvals)
418      END DO
419      DEALLOCATE (admm_env%eigvals_lambda)
420      DEALLOCATE (admm_env%eigvals_P_to_be_purified)
421      DEALLOCATE (admm_env%lambda)
422      DEALLOCATE (admm_env%lambda_inv)
423      DEALLOCATE (admm_env%lambda_inv_sqrt)
424      DEALLOCATE (admm_env%R)
425      DEALLOCATE (admm_env%R_purify)
426      DEALLOCATE (admm_env%M)
427      DEALLOCATE (admm_env%M_purify)
428      DEALLOCATE (admm_env%P_to_be_purified)
429      DEALLOCATE (admm_env%H)
430      DEALLOCATE (admm_env%H_corr)
431      DEALLOCATE (admm_env%K)
432      DEALLOCATE (admm_env%work_orb_nmo)
433      DEALLOCATE (admm_env%work_nmo_nmo1)
434      DEALLOCATE (admm_env%R_schur_R_t)
435      DEALLOCATE (admm_env%work_nmo_nmo2)
436      DEALLOCATE (admm_env%work_aux_nmo)
437      DEALLOCATE (admm_env%work_aux_nmo2)
438      DEALLOCATE (admm_env%mo_derivs_tmp)
439      DEALLOCATE (admm_env%ks_to_be_merged)
440      DEALLOCATE (admm_env%lambda_inv2)
441      DEALLOCATE (admm_env%C_hat)
442      DEALLOCATE (admm_env%P_tilde)
443
444      IF (ASSOCIATED(admm_env%block_map)) &
445         DEALLOCATE (admm_env%block_map)
446
447      IF (ASSOCIATED(admm_env%xc_section_primary)) &
448         CALL section_vals_release(admm_env%xc_section_primary)
449      IF (ASSOCIATED(admm_env%xc_section_aux)) &
450         CALL section_vals_release(admm_env%xc_section_aux)
451
452      IF (ASSOCIATED(admm_env%admm_gapw_env)) CALL admm_gapw_env_release(admm_env%admm_gapw_env)
453
454      DEALLOCATE (admm_env)
455
456   END SUBROUTINE admm_env_release
457
458! **************************************************************************************************
459!> \brief Release the ADMM GAPW stuff
460!> \param admm_gapw_env ...
461! **************************************************************************************************
462   SUBROUTINE admm_gapw_env_release(admm_gapw_env)
463
464      TYPE(admm_gapw_type), POINTER                      :: admm_gapw_env
465
466      CHARACTER(LEN=*), PARAMETER :: routineN = 'admm_gapw_env_release', &
467         routineP = moduleN//':'//routineN
468
469      IF (ASSOCIATED(admm_gapw_env%admm_kind_set)) THEN
470         CALL deallocate_qs_kind_set(admm_gapw_env%admm_kind_set)
471      END IF
472
473      IF (ASSOCIATED(admm_gapw_env%local_rho_set)) THEN
474         CALL local_rho_set_release(admm_gapw_env%local_rho_set)
475      END IF
476
477      IF (ASSOCIATED(admm_gapw_env%task_list)) THEN
478         CALL deallocate_task_list(admm_gapw_env%task_list)
479      END IF
480
481      IF (ASSOCIATED(admm_gapw_env%oce)) THEN
482         CALL deallocate_oce_set(admm_gapw_env%oce)
483      END IF
484
485      DEALLOCATE (admm_gapw_env)
486
487   END SUBROUTINE admm_gapw_env_release
488
489END MODULE admm_types
490
491