Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Main routines for GW + Bethe-Salpeter for computing electronic excitations
10 : !> \par History
11 : !> 04.2024 created [Maximilian Graml]
12 : ! **************************************************************************************************
13 :
14 : MODULE bse_main
15 :
16 : USE bse_full_diag, ONLY: create_A,&
17 : create_B,&
18 : create_hermitian_form_of_ABBA,&
19 : diagonalize_A,&
20 : diagonalize_C
21 : USE bse_iterative, ONLY: do_subspace_iterations,&
22 : fill_local_3c_arrays
23 : USE bse_print, ONLY: print_BSE_start_flag
24 : USE bse_util, ONLY: adapt_BSE_input_params,&
25 : deallocate_matrices_bse,&
26 : estimate_BSE_resources,&
27 : get_bse_spin_block_layout,&
28 : mult_B_with_W,&
29 : truncate_BSE_matrices
30 : USE cp_control_types, ONLY: dft_control_type,&
31 : tddfpt2_control_type
32 : USE cp_fm_types, ONLY: cp_fm_create,&
33 : cp_fm_release,&
34 : cp_fm_to_fm,&
35 : cp_fm_type
36 : USE cp_log_handling, ONLY: cp_get_default_logger,&
37 : cp_logger_type
38 : USE cp_output_handling, ONLY: debug_print_level
39 : USE group_dist_types, ONLY: group_dist_d1_type
40 : USE input_constants, ONLY: bse_abba,&
41 : bse_both,&
42 : bse_fulldiag,&
43 : bse_iterdiag,&
44 : bse_screening_alpha,&
45 : bse_screening_tdhf,&
46 : bse_tda
47 : USE kinds, ONLY: dp
48 : USE message_passing, ONLY: mp_para_env_type
49 : USE mo_window, ONLY: combine_mo_windows,&
50 : determine_mo_window,&
51 : mo_window_type
52 : USE mp2_types, ONLY: mp2_type
53 : USE qs_environment_types, ONLY: get_qs_env,&
54 : qs_environment_type
55 : #include "./base/base_uses.f90"
56 :
57 : IMPLICIT NONE
58 :
59 : PRIVATE
60 :
61 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'bse_main'
62 :
63 : PUBLIC :: start_bse_calculation
64 :
65 : CONTAINS
66 :
67 : ! **************************************************************************************************
68 : !> \brief Main subroutine managing BSE calculations
69 : !> \param fm_mat_S_ia_bse ...
70 : !> \param fm_mat_S_ij_bse ...
71 : !> \param fm_mat_S_ab_bse ...
72 : !> \param fm_mat_Q_static_bse_gemm ...
73 : !> \param Eigenval ...
74 : !> \param Eigenval_scf ...
75 : !> \param homo ...
76 : !> \param virtual ...
77 : !> \param dimen_RI ...
78 : !> \param dimen_RI_red ...
79 : !> \param bse_lev_virt ...
80 : !> \param gd_array ...
81 : !> \param color_sub ...
82 : !> \param mp2_env ...
83 : !> \param qs_env ...
84 : !> \param mo_coeff ...
85 : !> \param unit_nr ...
86 : ! **************************************************************************************************
87 42 : SUBROUTINE start_bse_calculation(fm_mat_S_ia_bse, fm_mat_S_ij_bse, fm_mat_S_ab_bse, &
88 : fm_mat_Q_static_bse_gemm, &
89 : Eigenval, Eigenval_scf, &
90 84 : homo, virtual, dimen_RI, dimen_RI_red, bse_lev_virt, &
91 42 : gd_array, color_sub, mp2_env, qs_env, mo_coeff, unit_nr)
92 :
93 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: fm_mat_S_ia_bse, fm_mat_S_ij_bse, &
94 : fm_mat_S_ab_bse
95 : TYPE(cp_fm_type), INTENT(INOUT) :: fm_mat_Q_static_bse_gemm
96 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
97 : INTENT(IN) :: Eigenval, Eigenval_scf
98 : INTEGER, DIMENSION(:), INTENT(IN) :: homo, virtual
99 : INTEGER, INTENT(IN) :: dimen_RI, dimen_RI_red
100 : INTEGER, DIMENSION(:), INTENT(IN) :: bse_lev_virt
101 : TYPE(group_dist_d1_type), INTENT(IN) :: gd_array
102 : INTEGER, INTENT(IN) :: color_sub
103 : TYPE(mp2_type) :: mp2_env
104 : TYPE(qs_environment_type), POINTER :: qs_env
105 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: mo_coeff
106 : INTEGER, INTENT(IN) :: unit_nr
107 :
108 : CHARACTER(LEN=*), PARAMETER :: routineN = 'start_bse_calculation'
109 :
110 : INTEGER :: handle, ispin, n_ov_joint, nspins
111 42 : INTEGER, ALLOCATABLE, DIMENSION(:) :: homo_red_arr, n_ov_arr, offsets_arr, &
112 42 : virt_red_arr
113 : LOGICAL :: my_do_abba, my_do_fulldiag, &
114 : my_do_iterat_diag, my_do_tda, &
115 : spins_differ
116 : REAL(KIND=dp) :: diag_runtime_est
117 42 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: Eigenval_reduced, Eigenval_reduced_1, &
118 42 : Eigenval_reduced_2, &
119 42 : Eigenval_reduced_joint
120 42 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: B_abQ_bse_local, B_bar_iaQ_bse_local, &
121 42 : B_bar_ijQ_bse_local, B_iaQ_bse_local
122 : TYPE(cp_fm_type) :: fm_A_BSE, fm_B_BSE, fm_C_BSE, &
123 : fm_inv_sqrt_A_minus_B, fm_Q_copy, &
124 : fm_sqrt_A_minus_B
125 42 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_mat_S_ab_trunc_arr, &
126 42 : fm_mat_S_bar_ia_bse_arr, fm_mat_S_bar_ij_bse_arr, fm_mat_S_ia_trunc_arr, &
127 42 : fm_mat_S_ij_trunc_arr
128 : TYPE(cp_logger_type), POINTER :: logger
129 : TYPE(dft_control_type), POINTER :: dft_control
130 : TYPE(mo_window_type) :: combined_window
131 42 : TYPE(mo_window_type), ALLOCATABLE, DIMENSION(:) :: spin_windows
132 : TYPE(mp_para_env_type), POINTER :: para_env
133 : TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
134 :
135 42 : CALL timeset(routineN, handle)
136 :
137 42 : nspins = SIZE(homo)
138 42 : para_env => fm_mat_S_ia_bse(1)%matrix_struct%para_env
139 :
140 42 : my_do_fulldiag = .FALSE.
141 42 : my_do_iterat_diag = .FALSE.
142 42 : my_do_tda = .FALSE.
143 42 : my_do_abba = .FALSE.
144 : !Method: Iterative or full diagonalization
145 42 : SELECT CASE (mp2_env%bse%bse_diag_method)
146 : CASE (bse_iterdiag)
147 0 : my_do_iterat_diag = .TRUE.
148 : !MG: Basics of the Davidson solver are implemented, but not rigorously checked.
149 0 : CPABORT("Iterative BSE not yet implemented")
150 : CASE (bse_fulldiag)
151 42 : my_do_fulldiag = .TRUE.
152 : END SELECT
153 : !Approximation: TDA and/or full ABBA matrix
154 62 : SELECT CASE (mp2_env%bse%flag_tda)
155 : CASE (bse_tda)
156 20 : my_do_tda = .TRUE.
157 : CASE (bse_abba)
158 22 : my_do_abba = .TRUE.
159 : CASE (bse_both)
160 0 : my_do_tda = .TRUE.
161 42 : my_do_abba = .TRUE.
162 : END SELECT
163 :
164 42 : CALL print_BSE_start_flag(my_do_tda, my_do_abba, unit_nr)
165 :
166 : ! Link BSE debug flag against debug print level
167 42 : logger => cp_get_default_logger()
168 42 : IF (logger%iter_info%print_level == debug_print_level) THEN
169 0 : mp2_env%bse%bse_debug_print = .TRUE.
170 : END IF
171 :
172 42 : CALL fm_mat_S_ia_bse(1)%matrix_struct%para_env%sync()
173 :
174 168 : ALLOCATE (homo_red_arr(nspins), virt_red_arr(nspins))
175 176 : ALLOCATE (spin_windows(nspins))
176 360 : ALLOCATE (fm_mat_S_ia_trunc_arr(nspins), fm_mat_S_ij_trunc_arr(nspins), fm_mat_S_ab_trunc_arr(nspins))
177 226 : ALLOCATE (fm_mat_S_bar_ia_bse_arr(nspins), fm_mat_S_bar_ij_bse_arr(nspins))
178 :
179 92 : DO ispin = 1, nspins
180 : CALL determine_mo_window(Eigenval_scf(:, 1, ispin), homo(ispin) + virtual(ispin), homo(ispin), &
181 : mp2_env%bse%bse_cutoff_occ, mp2_env%bse%bse_cutoff_empty, &
182 92 : spin_windows(ispin))
183 : END DO
184 :
185 42 : IF (nspins > 1) THEN
186 : CALL cp_warn(__LOCATION__, &
187 : "Open-shell (UKS/LSD) BSE is a recent addition and has not been "// &
188 : "extensively validated. Verify results carefully before using them "// &
189 8 : "for production calculations.")
190 : ! === Open-shell path: combined-window cutoff, per-spin truncation, joint A (+B for ABBA) ===
191 8 : CALL combine_mo_windows(spin_windows, combined_window, spins_differ)
192 8 : IF (spins_differ) THEN
193 0 : CPWARN("BSE: spin-resolved active MO cutoff candidates differ; using combined window.")
194 : END IF
195 24 : DO ispin = 1, nspins
196 : CALL truncate_BSE_matrices(fm_mat_S_ia_bse(ispin), fm_mat_S_ij_bse(ispin), &
197 : fm_mat_S_ab_bse(ispin), &
198 : fm_mat_S_ia_trunc_arr(ispin), fm_mat_S_ij_trunc_arr(ispin), &
199 : fm_mat_S_ab_trunc_arr(ispin), &
200 : Eigenval_scf(:, 1, ispin), Eigenval(:, 1, ispin), &
201 : Eigenval_reduced, homo(ispin), virtual(ispin), dimen_RI, &
202 : unit_nr, bse_lev_virt(ispin), homo_red_arr(ispin), &
203 16 : virt_red_arr(ispin), mp2_env, combined_window, .FALSE.)
204 16 : IF (ispin == 1) THEN
205 24 : ALLOCATE (Eigenval_reduced_1(SIZE(Eigenval_reduced)))
206 300 : Eigenval_reduced_1(:) = Eigenval_reduced(:)
207 : ELSE
208 24 : ALLOCATE (Eigenval_reduced_2(SIZE(Eigenval_reduced)))
209 300 : Eigenval_reduced_2(:) = Eigenval_reduced(:)
210 : END IF
211 24 : DEALLOCATE (Eigenval_reduced)
212 : END DO
213 : ! Flat eigenvalue layout: [sigma=1 levels, sigma=2 levels]
214 24 : ALLOCATE (Eigenval_reduced_joint(SIZE(Eigenval_reduced_1) + SIZE(Eigenval_reduced_2)))
215 300 : Eigenval_reduced_joint(1:SIZE(Eigenval_reduced_1)) = Eigenval_reduced_1
216 300 : Eigenval_reduced_joint(SIZE(Eigenval_reduced_1) + 1:) = Eigenval_reduced_2
217 8 : DEALLOCATE (Eigenval_reduced_1, Eigenval_reduced_2)
218 :
219 24 : ALLOCATE (n_ov_arr(nspins), offsets_arr(nspins))
220 8 : CALL get_bse_spin_block_layout(homo_red_arr, virt_red_arr, n_ov_arr, offsets_arr, n_ov_joint)
221 :
222 8 : CALL adapt_BSE_input_params(n_ov_joint, 1, unit_nr, mp2_env, qs_env)
223 :
224 : ! W: mult_B_with_W modifies Q in-place (Cholesky); copy the original Q for each spin call
225 24 : DO ispin = 1, nspins
226 16 : CALL cp_fm_create(fm_Q_copy, fm_mat_Q_static_bse_gemm%matrix_struct)
227 16 : CALL cp_fm_to_fm(fm_mat_Q_static_bse_gemm, fm_Q_copy)
228 : CALL mult_B_with_W(fm_mat_S_ij_trunc_arr(ispin), fm_mat_S_ia_trunc_arr(ispin), &
229 : fm_mat_S_bar_ia_bse_arr(ispin), fm_mat_S_bar_ij_bse_arr(ispin), &
230 16 : fm_Q_copy, dimen_RI_red, homo_red_arr(ispin), virt_red_arr(ispin))
231 40 : CALL cp_fm_release(fm_Q_copy)
232 : END DO
233 8 : CALL cp_fm_release(fm_mat_Q_static_bse_gemm)
234 :
235 8 : IF (my_do_fulldiag) THEN
236 8 : CALL estimate_BSE_resources(n_ov_joint, unit_nr, my_do_abba, para_env, diag_runtime_est)
237 8 : IF (mp2_env%bse%screening_method == bse_screening_tdhf .OR. &
238 : mp2_env%bse%screening_method == bse_screening_alpha) THEN
239 : CALL create_A(fm_mat_S_ia_trunc_arr, fm_mat_S_ij_trunc_arr, fm_mat_S_ab_trunc_arr, &
240 : fm_A_BSE, Eigenval_reduced_joint, unit_nr, &
241 0 : homo_red_arr, virt_red_arr, dimen_RI, mp2_env, para_env, qs_env)
242 : ELSE
243 : CALL create_A(fm_mat_S_ia_trunc_arr, fm_mat_S_bar_ij_bse_arr, fm_mat_S_ab_trunc_arr, &
244 : fm_A_BSE, Eigenval_reduced_joint, unit_nr, &
245 8 : homo_red_arr, virt_red_arr, dimen_RI, mp2_env, para_env, qs_env)
246 : END IF
247 8 : IF (my_do_abba) THEN
248 4 : IF (mp2_env%bse%screening_method == bse_screening_tdhf .OR. &
249 : mp2_env%bse%screening_method == bse_screening_alpha) THEN
250 : CALL create_B(fm_mat_S_ia_trunc_arr, fm_mat_S_ia_trunc_arr, fm_B_BSE, &
251 0 : homo_red_arr, virt_red_arr, dimen_RI, unit_nr, mp2_env)
252 : ELSE
253 : CALL create_B(fm_mat_S_ia_trunc_arr, fm_mat_S_bar_ia_bse_arr, fm_B_BSE, &
254 4 : homo_red_arr, virt_red_arr, dimen_RI, unit_nr, mp2_env)
255 : END IF
256 : CALL create_hermitian_form_of_ABBA(fm_A_BSE, fm_B_BSE, fm_C_BSE, &
257 : fm_sqrt_A_minus_B, fm_inv_sqrt_A_minus_B, &
258 4 : unit_nr, mp2_env, diag_runtime_est)
259 4 : CALL cp_fm_release(fm_B_BSE)
260 : END IF
261 8 : NULLIFY (dft_control, tddfpt_control)
262 8 : CALL get_qs_env(qs_env, dft_control=dft_control)
263 8 : tddfpt_control => dft_control%tddfpt2_control
264 : ! 4th arg (homo_irred) = full per-spin occupied counts: per-spin absolute-MO labels for
265 : ! the amplitude table, and N_e = SUM(homo_irred) for the TRK print.
266 8 : IF (my_do_tda .AND. (.NOT. tddfpt_control%do_bse)) THEN
267 : CALL diagonalize_A(fm_A_BSE, homo_red_arr, virt_red_arr, homo, &
268 4 : unit_nr, diag_runtime_est, mp2_env, qs_env, mo_coeff)
269 : END IF
270 8 : CALL cp_fm_release(fm_A_BSE)
271 8 : IF (my_do_abba) THEN
272 : CALL diagonalize_C(fm_C_BSE, homo_red_arr, virt_red_arr, homo, &
273 : fm_sqrt_A_minus_B, fm_inv_sqrt_A_minus_B, &
274 4 : unit_nr, diag_runtime_est, mp2_env, qs_env, mo_coeff)
275 4 : CALL cp_fm_release(fm_C_BSE)
276 : END IF
277 : END IF
278 :
279 24 : DO ispin = 1, nspins
280 16 : CALL cp_fm_release(fm_mat_S_bar_ia_bse_arr(ispin))
281 16 : CALL cp_fm_release(fm_mat_S_bar_ij_bse_arr(ispin))
282 16 : CALL cp_fm_release(fm_mat_S_ia_trunc_arr(ispin))
283 16 : CALL cp_fm_release(fm_mat_S_ij_trunc_arr(ispin))
284 24 : CALL cp_fm_release(fm_mat_S_ab_trunc_arr(ispin))
285 : END DO
286 8 : IF (mp2_env%bse%do_nto_analysis) DEALLOCATE (mp2_env%bse%bse_nto_state_list_final)
287 24 : DEALLOCATE (Eigenval_reduced_joint, n_ov_arr, offsets_arr)
288 :
289 : ELSE
290 : ! === Closed-shell n_spin=1 path (bit-identical) ===
291 : CALL truncate_BSE_matrices(fm_mat_S_ia_bse(1), fm_mat_S_ij_bse(1), fm_mat_S_ab_bse(1), &
292 : fm_mat_S_ia_trunc_arr(1), fm_mat_S_ij_trunc_arr(1), &
293 : fm_mat_S_ab_trunc_arr(1), &
294 : Eigenval_scf(:, 1, 1), Eigenval(:, 1, 1), Eigenval_reduced, &
295 : homo(1), virtual(1), dimen_RI, unit_nr, &
296 : bse_lev_virt(1), homo_red_arr(1), virt_red_arr(1), mp2_env, &
297 34 : spin_windows(1), .TRUE.)
298 : CALL mult_B_with_W(fm_mat_S_ij_trunc_arr(1), fm_mat_S_ia_trunc_arr(1), &
299 : fm_mat_S_bar_ia_bse_arr(1), fm_mat_S_bar_ij_bse_arr(1), &
300 34 : fm_mat_Q_static_bse_gemm, dimen_RI_red, homo_red_arr(1), virt_red_arr(1))
301 :
302 34 : IF (my_do_iterat_diag) THEN
303 : CALL fill_local_3c_arrays(fm_mat_S_ab_trunc_arr(1), fm_mat_S_ia_trunc_arr(1), &
304 : fm_mat_S_bar_ia_bse_arr(1), fm_mat_S_bar_ij_bse_arr(1), &
305 : B_bar_ijQ_bse_local, B_abQ_bse_local, B_bar_iaQ_bse_local, &
306 : B_iaQ_bse_local, dimen_RI_red, homo_red_arr(1), &
307 0 : virt_red_arr(1), gd_array, color_sub, para_env)
308 : END IF
309 :
310 34 : CALL adapt_BSE_input_params(homo_red_arr(1), virt_red_arr(1), unit_nr, mp2_env, qs_env)
311 :
312 34 : IF (my_do_fulldiag) THEN
313 34 : n_ov_joint = homo_red_arr(1)*virt_red_arr(1)
314 34 : CALL estimate_BSE_resources(n_ov_joint, unit_nr, my_do_abba, para_env, diag_runtime_est)
315 34 : IF (mp2_env%bse%screening_method == bse_screening_tdhf .OR. &
316 : mp2_env%bse%screening_method == bse_screening_alpha) THEN
317 : CALL create_A(fm_mat_S_ia_trunc_arr, fm_mat_S_ij_trunc_arr, fm_mat_S_ab_trunc_arr, &
318 : fm_A_BSE, Eigenval_reduced, unit_nr, &
319 4 : homo_red_arr, virt_red_arr, dimen_RI, mp2_env, para_env, qs_env)
320 : ELSE
321 : CALL create_A(fm_mat_S_ia_trunc_arr, fm_mat_S_bar_ij_bse_arr, fm_mat_S_ab_trunc_arr, &
322 : fm_A_BSE, Eigenval_reduced, unit_nr, &
323 30 : homo_red_arr, virt_red_arr, dimen_RI, mp2_env, para_env, qs_env)
324 : END IF
325 34 : IF (my_do_abba) THEN
326 18 : IF (mp2_env%bse%screening_method == bse_screening_tdhf .OR. &
327 : mp2_env%bse%screening_method == bse_screening_alpha) THEN
328 : CALL create_B(fm_mat_S_ia_trunc_arr, fm_mat_S_ia_trunc_arr, fm_B_BSE, &
329 4 : homo_red_arr, virt_red_arr, dimen_RI, unit_nr, mp2_env)
330 : ELSE
331 : CALL create_B(fm_mat_S_ia_trunc_arr, fm_mat_S_bar_ia_bse_arr, fm_B_BSE, &
332 14 : homo_red_arr, virt_red_arr, dimen_RI, unit_nr, mp2_env)
333 : END IF
334 : CALL create_hermitian_form_of_ABBA(fm_A_BSE, fm_B_BSE, fm_C_BSE, &
335 : fm_sqrt_A_minus_B, fm_inv_sqrt_A_minus_B, &
336 18 : unit_nr, mp2_env, diag_runtime_est)
337 : END IF
338 34 : CALL cp_fm_release(fm_B_BSE)
339 :
340 34 : NULLIFY (dft_control, tddfpt_control)
341 34 : CALL get_qs_env(qs_env, dft_control=dft_control)
342 34 : tddfpt_control => dft_control%tddfpt2_control
343 34 : IF (my_do_tda .AND. (.NOT. tddfpt_control%do_bse)) THEN
344 : CALL diagonalize_A(fm_A_BSE, homo_red_arr, virt_red_arr, homo, &
345 14 : unit_nr, diag_runtime_est, mp2_env, qs_env, mo_coeff)
346 : END IF
347 34 : CALL cp_fm_release(fm_A_BSE)
348 34 : IF (my_do_abba) THEN
349 : CALL diagonalize_C(fm_C_BSE, homo_red_arr, virt_red_arr, homo, &
350 : fm_sqrt_A_minus_B, fm_inv_sqrt_A_minus_B, &
351 18 : unit_nr, diag_runtime_est, mp2_env, qs_env, mo_coeff)
352 : END IF
353 34 : CALL cp_fm_release(fm_C_BSE)
354 : END IF
355 :
356 : CALL deallocate_matrices_bse(fm_mat_S_bar_ia_bse_arr(1), fm_mat_S_bar_ij_bse_arr(1), &
357 : fm_mat_S_ia_trunc_arr(1), fm_mat_S_ij_trunc_arr(1), &
358 34 : fm_mat_S_ab_trunc_arr(1), fm_mat_Q_static_bse_gemm, mp2_env)
359 34 : DEALLOCATE (Eigenval_reduced)
360 34 : IF (my_do_iterat_diag) THEN
361 : CALL do_subspace_iterations(B_bar_ijQ_bse_local, B_abQ_bse_local, B_bar_iaQ_bse_local, &
362 : B_iaQ_bse_local, homo(1), virtual(1), &
363 : mp2_env%bse%bse_spin_config, unit_nr, &
364 0 : Eigenval(:, 1, 1), para_env, mp2_env)
365 0 : DEALLOCATE (B_bar_ijQ_bse_local, B_abQ_bse_local, B_bar_iaQ_bse_local, B_iaQ_bse_local)
366 : END IF
367 :
368 : END IF
369 :
370 42 : DEALLOCATE (homo_red_arr, virt_red_arr)
371 42 : DEALLOCATE (spin_windows)
372 42 : DEALLOCATE (fm_mat_S_ia_trunc_arr, fm_mat_S_ij_trunc_arr, fm_mat_S_ab_trunc_arr)
373 42 : DEALLOCATE (fm_mat_S_bar_ia_bse_arr, fm_mat_S_bar_ij_bse_arr)
374 :
375 42 : IF (unit_nr > 0) THEN
376 21 : WRITE (unit_nr, '(T2,A4,T7,A53)') 'BSE|', 'The BSE was successfully calculated. Have a nice day!'
377 : END IF
378 :
379 42 : CALL timestop(handle)
380 :
381 84 : END SUBROUTINE start_bse_calculation
382 :
383 : END MODULE bse_main
|