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