Octopus
propagator_cn.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!! Copyright (C) 2022 N. Tancogne-Dejean
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
23 use accel_oct_m
25 use debug_oct_m
31 use grid_oct_m
32 use global_oct_m
36 use ions_oct_m
37 use, intrinsic :: iso_fortran_env
39 use mesh_oct_m
45 use parser_oct_m
51 use space_oct_m
56 use xc_oct_m
57
58 implicit none
59
60 private
61
62 public :: &
64
65 type(namespace_t), pointer, private :: namespace_p
66 class(mesh_t), pointer, private :: mesh_p
67 type(hamiltonian_elec_t), pointer, private :: hm_p
68 type(propagator_base_t), pointer, private :: tr_p
69 type(states_elec_t), pointer, private :: st_p
70 integer, private :: ik_op, ist_op, dim_op
71 real(real64), private :: t_op, dt_op
72
73contains
74
75 ! ---------------------------------------------------------
77 subroutine td_crank_nicolson(hm, namespace, space, gr, st, tr, time, dt, ions_dyn, ions, ext_partners, mc, use_sparskit)
78 type(hamiltonian_elec_t), target, intent(inout) :: hm
79 type(namespace_t), target, intent(in) :: namespace
80 type(electron_space_t), intent(in) :: space
81 type(grid_t), target, intent(inout) :: gr
82 type(states_elec_t), target, intent(inout) :: st
83 type(propagator_base_t), target, intent(inout) :: tr
84 real(real64), intent(in) :: time
85 real(real64), intent(in) :: dt
86 type(ion_dynamics_t), intent(inout) :: ions_dyn
87 type(ions_t), intent(inout) :: ions
88 type(partner_list_t), intent(in) :: ext_partners
89 type(multicomm_t), intent(inout) :: mc
90 logical, intent(in) :: use_sparskit
91
92 complex(real64), allocatable :: zpsi(:), rhs(:)
93 integer :: ik, ist, idim, np, max_iter
94 real(real64) :: cgtol = 1.0e-12_real64
95 integer :: ib, minst, maxst
96 integer, allocatable :: iter_used(:)
97 real(real64), allocatable :: residue(:)
98 type(density_calc_t) :: dens_calc
99 type(wfs_elec_t) :: psib_rhs
100 type(gauge_field_t), pointer :: gfield
101
102 push_sub(propagator_dt.td_crank_nicolson)
103
104 !TODO: Add gauge field support
105 gfield => list_get_gauge_field(ext_partners)
106 if(associated(gfield)) then
107 assert(gauge_field_is_propagated(gfield) .eqv. .false.)
108 end if
109
110
111#ifndef HAVE_SPARSKIT
112 if (use_sparskit) then
113 message(1) = "Cannot use SPARSKIT in Crank-Nicolson propagator: not compiled with SPARSKIT support."
114 call messages_fatal(1, namespace=namespace)
115 end if
116#endif
117
118 np = gr%np
119
120 ! define pointer and variables for usage in td_zop, td_zopt routines
121 namespace_p => namespace
122 mesh_p => gr
123 hm_p => hm
124 tr_p => tr
125 st_p => st
126 dt_op = dt
127 t_op = time - dt/m_two
128 dim_op = st%d%dim
129
130 ! we (ab)use exponential_apply to compute (1-i\delta t/2 H_n)\psi^n
131 ! exponential order needs to be only 1
132 tr%te%exp_method = exp_taylor
133 tr%te%exp_order = 1
134
135 safe_allocate(zpsi(1:np*st%d%dim))
136 safe_allocate(rhs(1:np*st%d%dim))
137
138 !move the ions to time 'time - dt/2', and save the current status to return to it later.
139 call propagation_ops_elec_move_ions(tr%propagation_ops_elec, gr, hm, st, namespace, space, ions_dyn, ions, &
140 ext_partners, mc, time - m_half*dt, m_half*dt, save_pos = .true.)
141
142 call hm%ks_pot%interpolate_potentials(tr%vks_old, 3, time, dt, time -dt/m_two)
143
144 call propagation_ops_elec_update_hamiltonian(namespace, space, st, gr, hm, ext_partners, time - dt*m_half)
145
146 call density_calc_init(dens_calc, st, gr, st%rho)
147
148 ! solve (1+i\delta t/2 H_n)\psi^{predictor}_{n+1} = (1-i\delta t/2 H_n)\psi^n
149 do ik = st%d%kpt%start, st%d%kpt%end
150 call propagation_ops_do_pack(st, hm, st%group%block_start, ik)
151 do ib = st%group%block_start, st%group%block_end
152 if (ib + 1 <= st%group%block_end) call propagation_ops_do_pack(st, hm, ib+1, ik)
153 call accel_set_stream(ib)
154
155 call st%group%psib(ib, ik)%copy_to(psib_rhs)
156 dt_op = -dt
157 call propagator_qmr_op_batch (st%group%psib(ib, ik), psib_rhs)
158 dt_op = dt
161 call batch_axpy(np, dt, hm%inh_st%group%psib(ib, ik), psib_rhs)
162 end if
164 if(use_sparskit) then !Unbatchified path
165 minst = states_elec_block_min(st, ib)
166 maxst = states_elec_block_max(st, ib)
167 do ist = minst, maxst
168 ! put the values in a continuous array
169 do idim = 1, st%d%dim
170 call batch_get_state(st%group%psib(ib, ik), (/ist, idim/), np, zpsi((idim - 1)*np+1:idim*np))
171 call batch_get_state(psib_rhs, (/ist, idim/), np, rhs((idim - 1)*np+1:idim*np))
172 end do
173
174 ist_op = ist
175 ik_op = ik
176
177 call zsparskit_solver_run(namespace, tr%tdsk, td_zop, td_zopt, zpsi, rhs)
178
179 do idim = 1, st%d%dim
180 call batch_set_state(st%group%psib(ib, ik), (/ist, idim/), gr%np, zpsi((idim - 1)*np+1:idim*np))
181 end do
182
183 end do
184
185 else
186
187 safe_allocate(iter_used(psib_rhs%nst))
188 safe_allocate(residue(psib_rhs%nst))
189 max_iter = 2000
190 call zbatch_qmr_dotu(namespace, gr, st, st%group%psib(ib, ik), psib_rhs, &
191 propagator_qmr_op_batch, max_iter, iter_used, residue, cgtol, .false.)
192
193 if (any(iter_used == max_iter)) then
194 write(message(1),'(a)') 'The linear solver used for the Crank-Nicolson'
195 write(message(2),'(a)') 'propagator did not converge: '
196 do ist=1, psib_rhs%nst
197 write(message(ist+2),'(a,i2,a,es14.4)') 'State = ', ist, ' Residual = ', residue(ist)
198 end do
199 call messages_warning(psib_rhs%nst+2, namespace=namespace)
200 end if
201
202 safe_deallocate_a(iter_used)
203 safe_deallocate_a(residue)
204 end if
205
206 !use the dt propagation to calculate the density
207 call density_calc_accumulate(dens_calc, st%group%psib(ib, ik))
208
209 call psib_rhs%end()
210
211 call propagation_ops_do_unpack(st, hm, ib, ik)
212 if (ib-1 >= st%group%block_start) call propagation_ops_finish_unpack(st, hm, ib-1, ik)
213 end do
214 call propagation_ops_finish_unpack(st, hm, st%group%block_end, ik)
215 end do
216
217 call density_calc_end(dens_calc)
218
219 !restore to time 'time - dt'
220 call propagation_ops_elec_restore_ions(tr%propagation_ops_elec, ions_dyn, ions)
221
222 safe_deallocate_a(zpsi)
223 safe_deallocate_a(rhs)
224
225 pop_sub(propagator_dt.td_crank_nicolson)
226 end subroutine td_crank_nicolson
227 ! ---------------------------------------------------------
228
229 ! ---------------------------------------------------------
231 subroutine td_zop(xre, xim, yre, yim)
232 real(real64), intent(in) :: xre(:)
233 real(real64), intent(in) :: xim(:)
234 real(real64), intent(out) :: yre(:)
235 real(real64), intent(out) :: yim(:)
236
237 integer :: idim
238 complex(real64), allocatable :: zpsi(:, :)
239
240 push_sub(td_zop)
241
242 safe_allocate(zpsi(1:mesh_p%np_part, 1:dim_op))
243 zpsi = m_z0
244 do idim = 1, dim_op
245 zpsi(1:mesh_p%np, idim) = cmplx(xre((idim-1)*mesh_p%np+1:idim*mesh_p%np), &
246 xim((idim-1)*mesh_p%np+1:idim*mesh_p%np), real64)
247 end do
248
249 call tr_p%te%apply_single(namespace_p, mesh_p, hm_p, zpsi, ist_op, ik_op, -dt_op/m_two)
250
251 do idim = 1, dim_op
252 yre((idim-1)*mesh_p%np+1:idim*mesh_p%np) = real(zpsi(1:mesh_p%np, idim), real64)
253 yim((idim-1)*mesh_p%np+1:idim*mesh_p%np) = aimag(zpsi(1:mesh_p%np, idim))
254 end do
255
256 safe_deallocate_a(zpsi)
257
258 pop_sub(td_zop)
259 end subroutine td_zop
260 ! ---------------------------------------------------------
261
262
263 ! ---------------------------------------------------------
265 subroutine td_zopt(xre, xim, yre, yim)
266 real(real64), intent(in) :: xre(:)
267 real(real64), intent(in) :: xim(:)
268 real(real64), intent(out) :: yre(:)
269 real(real64), intent(out) :: yim(:)
270
271 integer :: idim
272 complex(real64), allocatable :: zpsi(:, :)
273
274 push_sub(td_zopt)
275
276 ! To act with the transpose of H on the wfn we apply H to the conjugate of psi
277 ! and conjugate the resulting hpsi (note that H is not a purely real operator
278 ! for scattering wavefunctions anymore).
279 safe_allocate(zpsi(1:mesh_p%np_part, 1:dim_op))
280 zpsi = m_z0
281 do idim = 1, dim_op
282 zpsi(1:mesh_p%np, idim) = cmplx(xre((idim-1)*mesh_p%np+1:idim*mesh_p%np), &
283 - xim((idim-1)*mesh_p%np+1:idim*mesh_p%np), real64)
284 end do
285
286 call tr_p%te%apply_single(namespace_p, mesh_p, hm_p, zpsi, ist_op, ik_op, -dt_op/m_two)
287
288 do idim = 1, dim_op
289 yre((idim-1)*mesh_p%np+1:idim*mesh_p%np) = real(zpsi(1:mesh_p%np, idim), real64)
290 yim((idim-1)*mesh_p%np+1:idim*mesh_p%np) = - aimag(zpsi(1:mesh_p%np, idim))
291 end do
292
293 safe_deallocate_a(zpsi)
294 pop_sub(td_zopt)
295 end subroutine td_zopt
296 ! ---------------------------------------------------------
297
298
299 ! ---------------------------------------------------------
301 subroutine propagator_qmr_op_batch(xxb, yyb)
302 type(wfs_elec_t), intent(inout) :: xxb
303 type(wfs_elec_t), intent(inout) :: yyb
304
306
307 call xxb%copy_data_to(mesh_p%np, yyb)
308 call tr_p%te%apply_batch(namespace_p, mesh_p, hm_p, yyb, -dt_op/m_two)
309
311 end subroutine propagator_qmr_op_batch
312 ! ---------------------------------------------------------
313
314 ! ---------------------------------------------------------
321 subroutine zbatch_qmr_dotu(namespace, mesh, st, xb, bb, op, max_iter, iter_used, &
322 residue, threshold, use_initial_guess)
323 type(namespace_t), intent(in) :: namespace
324 class(mesh_t), intent(in) :: mesh
325 type(states_elec_t), intent(in) :: st
326 type(wfs_elec_t), intent(inout) :: xb
327 type(wfs_elec_t), intent(in) :: bb
328 interface
329 subroutine op(xxb, yyb) !< the preconditioner
330 import wfs_elec_t
331 implicit none
332 type(wfs_elec_t), intent(inout) :: xxb
333 type(wfs_elec_t), intent(inout) :: yyb
334 end subroutine op
335 end interface
336 integer, intent(in) :: max_iter
337 integer, intent(out) :: iter_used(:)
338 real(real64), contiguous, intent(out) :: residue(:)
339 real(real64), intent(in) :: threshold
340 logical, optional, intent(in) :: use_initial_guess
341
342
343 type(wfs_elec_t) :: vvb, res, qqb, ppb, deltax, deltar
344 integer :: ii, iter
345 real(real64), allocatable :: rho(:), oldrho(:), norm_b(:), xsi(:), gamma(:), alpha(:), theta(:), oldtheta(:), saved_res(:)
346 real(real64), allocatable :: oldgamma(:)
347 complex(real64), allocatable :: eta(:), beta(:), delta(:), eps(:), exception_saved(:, :, :)
348 integer, allocatable :: status(:), saved_iter(:)
349
350 integer, parameter :: &
351 QMR_NOT_CONVERGED = 0, &
352 qmr_converged = 1, &
353 qmr_res_zero = 2, &
354 qmr_b_zero = 3, &
355 qmr_breakdown_pb = 4, &
356 qmr_breakdown_vz = 5, &
357 qmr_breakdown_qp = 6, &
358 qmr_breakdown_gamma = 7
359
360 push_sub(zbatch_qmr_dotu)
361
362 safe_allocate(rho(1:xb%nst))
363 safe_allocate(oldrho(1:xb%nst))
364 safe_allocate(norm_b(1:xb%nst))
365 safe_allocate(xsi(1:xb%nst))
366 safe_allocate(gamma(1:xb%nst))
367 safe_allocate(oldgamma(1:xb%nst))
368 safe_allocate(alpha(1:xb%nst))
369 safe_allocate(eta(1:xb%nst))
370 safe_allocate(theta(1:xb%nst))
371 safe_allocate(oldtheta(1:xb%nst))
372 safe_allocate(beta(1:xb%nst))
373 safe_allocate(delta(1:xb%nst))
374 safe_allocate(eps(1:xb%nst))
375 safe_allocate(saved_res(1:xb%nst))
376
377 safe_allocate(status(1:xb%nst))
378 safe_allocate(saved_iter(1:xb%nst))
379
380 safe_allocate(exception_saved(1:mesh%np, 1:st%d%dim, 1:xb%nst))
381
382 call xb%copy_to(vvb)
383 call xb%copy_to(res)
384 call xb%copy_to(qqb)
385 call xb%copy_to(ppb)
386 call xb%copy_to(deltax)
387 call xb%copy_to(deltar)
388
389 if (optional_default(use_initial_guess, .true.)) then
390 ! Compared to the original algorithm, we assume that we have an initial guess
391 ! This means that instead of setting x^(0)=0, we have x^(0)=xb
392 ! TODO: We should implement here the proper recursion for x^(0) /= 0
393 ! as published in "Preconditioning of Symmetric, but Highly Indefinite Linear Systems"
394 ! R. W. Freund, 15th IMACS World Congress on Scientific Computation, Modelling and Applied Mathematics
395 ! 2, 551 (1997)
396 call op(xb, vvb)
397
398 call batch_xpay(mesh%np, bb, -1.0_real64, vvb)
399 call vvb%copy_data_to(mesh%np, res)
400
401 ! Norm of the right-hand side
402 call mesh_batch_nrm2(mesh, vvb, rho)
403 call mesh_batch_nrm2(mesh, bb, norm_b)
404
405 do ii = 1, xb%nst
406 ! If the initial guess is a good enough solution
407 if (abs(rho(ii)) <= threshold) then
408 status(ii) = qmr_res_zero
409 residue(ii) = rho(ii)
410 call batch_get_state(xb, ii, mesh%np, exception_saved(:, :, ii))
411 saved_iter(ii) = 0
412 saved_res(ii) = residue(ii)
413 end if
414 end do
415
416 else ! If we don't know any guess, let's stick to the original algorithm
417
418 call batch_set_zero(xb)
419 call bb%copy_data_to(mesh%np, vvb)
420 call vvb%copy_data_to(mesh%np, res)
421 call mesh_batch_nrm2(mesh, bb, norm_b)
422 rho = norm_b
423
424 end if
425
426 status = qmr_not_converged
427
428 iter = 0
429
430 do ii = 1, xb%nst
431
432 residue(ii) = rho(ii)
433 ! if b is zero, the solution is trivial
434 if (status(ii) == qmr_not_converged .and. abs(norm_b(ii)) <= m_tiny) then
435 exception_saved = m_zero
436 status(ii) = qmr_b_zero
437 residue(ii) = norm_b(ii)
438 saved_iter(ii) = iter
439 saved_res(ii) = residue(ii)
440 end if
441
442 end do
443
444 xsi = rho
445 gamma = m_one
446 oldgamma = gamma
447 eta = -1.0_real64
448 alpha = m_one
449 theta = m_zero
450
451 do while(iter < max_iter)
452 iter = iter + 1
453
454 ! Exit condition
455 if (all(status /= qmr_not_converged)) exit
456
457 ! Failure of the algorithm
458 do ii = 1, xb%nst
459 if (status(ii) == qmr_not_converged .and. (abs(rho(ii)) < m_tiny .or. abs(xsi(ii)) < m_tiny)) then
460 call batch_get_state(xb, ii, mesh%np, exception_saved(:, :, ii))
461 status(ii) = qmr_breakdown_pb
462 saved_iter(ii) = iter
463 saved_res(ii) = residue(ii)
464 end if
465
466 alpha(ii) = alpha(ii)*xsi(ii)/rho(ii)
467 end do
468
469 ! v^(i) = v^(i) / \rho_i
470 call batch_scal(mesh%np, m_one/rho, vvb, a_full = .false.)
471 ! \delta_i = v^(i)\ldotu z^(i)
472 call zmesh_batch_dotp_vector(mesh, vvb, vvb, delta, cproduct=.true.)
473
474 delta = delta / alpha
475
476
477 !If \delta_i = 0, method fails
478 do ii = 1, xb%nst
479 if (status(ii) == qmr_not_converged .and. abs(delta(ii)) < m_tiny) then
480 call batch_get_state(xb, ii, mesh%np, exception_saved(:, :, ii))
481 status(ii) = qmr_breakdown_vz
482 saved_iter(ii) = iter
483 saved_res(ii) = residue(ii)
484 end if
485 end do
486
487 if (iter == 1) then
488 ! q^(1) = z^(1)
489 call vvb%copy_data_to(mesh%np, qqb)
490 else
491 ! q^(i) = z^(i) - (\rho_i\delta_i)/(\eps_{i-1})q^(i-1)
492 call batch_xpay(mesh%np, vvb, -rho*delta/eps, qqb, a_full = .false.)
493 end if
494
495 ! ppb = H*qqb
496 call op(qqb, ppb)
497 ! p^(i) = \alpha_{i+1} (H-shift)*q^(i)
498 call batch_scal(mesh%np, alpha, ppb, a_full = .false.)
499
500 ! \eps_i = q^{(i)}\ldotu p^{(i)}
501 call zmesh_batch_dotp_vector(mesh, qqb, ppb, eps, cproduct=.true.)
502
503 ! If \eps_i == 0, method fails
504 do ii = 1, xb%nst
505 if (status(ii) == qmr_not_converged .and. abs(eps(ii)) < m_tiny) then
506 call batch_get_state(xb, ii, mesh%np, exception_saved(:, :, ii))
507 status(ii) = qmr_breakdown_qp
508 saved_iter(ii) = iter
509 saved_res(ii) = residue(ii)
510 end if
511
512 beta(ii) = eps(ii)/delta(ii)
513 end do
514
515 ! v^(i+1) = p^(i) - \beta_i v^(i)
516 call batch_xpay(mesh%np, ppb, -beta, vvb, a_full = .false.)
517
518 do ii = 1, xb%nst
519 oldrho(ii) = rho(ii)
520 end do
521
522 ! \rho_{i+1} = ||v^{i+1}||_2
523 call mesh_batch_nrm2(mesh, vvb, rho)
524
525 ! \xsi_{i+1} = ||z^{i+1}||_2
526 xsi = rho / (alpha**2)
527
528 do ii = 1, xb%nst
529
530 oldtheta(ii) = theta(ii)
531 ! \theta_i = \rho_{i+1}/(\gamma_{i-1} |\beta_i|)
532 theta(ii) = rho(ii)/(gamma(ii)*abs(beta(ii)))
533
534 oldgamma(ii) = gamma(ii)
535 ! \gamma_i = 1/sqrt(1+\theta_i^2)
536 gamma(ii) = m_one/sqrt(m_one + theta(ii)**2)
537
538 ! If \gamma_i == 0, method fails
539 if (status(ii) == qmr_not_converged .and. abs(gamma(ii)) < m_tiny) then
540 call batch_get_state(xb, ii, mesh%np, exception_saved(:, :, ii))
541 status(ii) = qmr_breakdown_gamma
542 saved_iter(ii) = iter
543 saved_res(ii) = residue(ii)
544 end if
545
546 ! \eta_i = -\eta_{i-1}\rho_i \gamma_i^2/ (\beta_i \gamma_{i-1}^2)
547 eta(ii) = -eta(ii)*oldrho(ii)*gamma(ii)**2/(beta(ii)*oldgamma(ii)**2)
548 end do
549
550 if (iter == 1) then
551
552 ! \delta_x^(1) = \eta_1 \alpha_2 q^{(1)}
553 call qqb%copy_data_to(mesh%np, deltax)
554 call batch_scal(mesh%np, eta*alpha, deltax, a_full = .false.)
555
556 ! \delta_r^(1) = \eta_1 p^1
557 call ppb%copy_data_to(mesh%np, deltar)
558 call batch_scal(mesh%np, eta, deltar, a_full = .false.)
559
560 else
561
562 ! \delta_x^{i} = (\theta_{i-1}\gamma_i)^2 \delta_x^{i-1} + \eta_i\alpha_{i+1} q^i
563 call batch_scal(mesh%np, (oldtheta*gamma)**2, deltax, a_full = .false.)
564 call batch_axpy(mesh%np, eta*alpha, qqb, deltax, a_full = .false.)
565
566 ! \delta_r^{i} = (\theta_{i-1}\gamma_i)^2 \delta_r^{i-1} + \eta_i p^i
567 call batch_scal(mesh%np, (oldtheta*gamma)**2, deltar, a_full = .false.)
568 call batch_axpy(mesh%np, eta, ppb, deltar, a_full = .false.)
569
570 end if
571
572 ! FIXME: if the states are converged, why changing them here
573 ! x^{i} = x^{i-1} + \delta_x^{i}
574 call batch_axpy(mesh%np, m_one, deltax, xb)
575 ! r^{i} = r^{i-1} - \delta_r^i
576 ! This is given by r^{i} = b - Hx^{i}
577 call batch_axpy(mesh%np, -1.0_real64, deltar, res)
578
579 ! We compute the norm of the residual
580 call mesh_batch_nrm2(mesh, res, residue)
581 do ii = 1, xb%nst
582 residue(ii) = residue(ii)/norm_b(ii)
583 end do
584
585 ! Convergence is reached once the residues are smaller than the threshold
586 do ii = 1, xb%nst
587 if (status(ii) == qmr_not_converged .and. residue(ii) < threshold) then
588 status(ii) = qmr_converged
589 write(message(1),*) 'Debug: State ', xb%ist(ii), ' converged in ', iter, ' iterations.'
590 call messages_info(1, namespace=namespace, debug_only=.true.)
591 end if
592 end do
593
594 end do
595
596 do ii = 1, xb%nst
597 if (status(ii) == qmr_not_converged .or. status(ii) == qmr_converged) then
598 ! We stop at the entrance of the next iteraction, so we substract one here
599 iter_used(ii) = iter -1
600 else
601 call batch_set_state(xb, ii, mesh%np, exception_saved(:, :, ii))
602 iter_used(ii) = saved_iter(ii)
603 residue(ii) = saved_res(ii)
604 end if
605
606 select case (status(ii))
607 case (qmr_not_converged)
608 write(message(1), '(a)') "QMR solver not converged!"
609 write(message(2), '(a)') "Try increasing the maximum number of iterations or the tolerance."
610 call messages_warning(2, namespace=namespace)
611 case (qmr_breakdown_pb)
612 write(message(1), '(a)') "QMR breakdown, cannot continue: b or P*b is the zero vector!"
613 call messages_warning(1, namespace=namespace)
614 case (qmr_breakdown_vz)
615 write(message(1), '(a)') "QMR breakdown, cannot continue: v^T*z is zero!"
616 call messages_warning(1, namespace=namespace)
617 case (qmr_breakdown_qp)
618 write(message(1), '(a)') "QMR breakdown, cannot continue: q^T*p is zero!"
619 call messages_warning(1, namespace=namespace)
620 case (qmr_breakdown_gamma)
621 write(message(1), '(a)') "QMR breakdown, cannot continue: gamma is zero!"
622 call messages_warning(1, namespace=namespace)
623 end select
624
625 end do
626
627 call vvb%end()
628 call res%end()
629 call qqb%end()
630 call ppb%end()
631 call deltax%end()
632 call deltar%end()
633
634 safe_deallocate_a(exception_saved)
635 safe_deallocate_a(rho)
636 safe_deallocate_a(oldrho)
637 safe_deallocate_a(norm_b)
638 safe_deallocate_a(xsi)
639 safe_deallocate_a(gamma)
640 safe_deallocate_a(oldgamma)
641 safe_deallocate_a(alpha)
642 safe_deallocate_a(eta)
643 safe_deallocate_a(theta)
644 safe_deallocate_a(oldtheta)
645 safe_deallocate_a(beta)
646 safe_deallocate_a(delta)
647 safe_deallocate_a(eps)
648
649 safe_deallocate_a(saved_res)
650 safe_deallocate_a(status)
651 safe_deallocate_a(saved_iter)
652
653 pop_sub(zbatch_qmr_dotu)
654 end subroutine zbatch_qmr_dotu
655
656end module propagator_cn_oct_m
657
658!! Local Variables:
659!! mode: f90
660!! coding: utf-8
661!! End:
batchified version of the BLAS axpy routine:
Definition: batch_ops.F90:154
scale a batch by a constant or vector
Definition: batch_ops.F90:162
There are several ways how to call batch_set_state and batch_get_state:
Definition: batch_ops.F90:201
batchified version of
Definition: batch_ops.F90:170
double sqrt(double __x) __attribute__((__nothrow__
subroutine, public accel_set_stream(stream_number)
Definition: accel.F90:2196
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:116
subroutine, public batch_set_zero(this, np, async)
fill all mesh functions of the batch with zero
Definition: batch_ops.F90:242
This module implements a calculator for the density and defines related functions.
Definition: density.F90:120
subroutine, public density_calc_end(this, allreduce, symmetrize)
Finalize the density calculation.
Definition: density.F90:559
subroutine, public density_calc_accumulate(this, psib, async)
Accumulate weighted orbital densities for a batch psib.
Definition: density.F90:392
subroutine, public density_calc_init(this, st, gr, density)
initialize the density calculator
Definition: density.F90:188
integer, parameter, public exp_taylor
type(gauge_field_t) function, pointer, public list_get_gauge_field(partners)
logical pure function, public gauge_field_is_propagated(this)
real(real64), parameter, public m_two
Definition: global.F90:190
real(real64), parameter, public m_zero
Definition: global.F90:188
real(real64), parameter, public m_tiny
Definition: global.F90:205
complex(real64), parameter, public m_z0
Definition: global.F90:198
real(real64), parameter, public m_half
Definition: global.F90:194
real(real64), parameter, public m_one
Definition: global.F90:189
This module implements the underlying real-space grid.
Definition: grid.F90:117
pure logical function, public hamiltonian_elec_inh_term(hm)
This module defines classes and functions for interaction partners.
This module defines functions over batches of mesh functions.
Definition: mesh_batch.F90:116
subroutine, public mesh_batch_nrm2(mesh, aa, nrm2, reduce)
Calculate the norms (norm2, not the square!) of a batch of mesh functions.
Definition: mesh_batch.F90:177
subroutine, public zmesh_batch_dotp_vector(mesh, aa, bb, dot, reduce, cproduct)
calculate the vector of dot-products of mesh functions between two batches
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:537
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:414
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:616
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:145
subroutine, public propagation_ops_elec_restore_ions(wo, ions_dyn, ions)
subroutine, public propagation_ops_do_unpack(st, hm, ib, ik)
subroutine, public propagation_ops_elec_update_hamiltonian(namespace, space, st, mesh, hm, ext_partners, time)
subroutine, public propagation_ops_do_pack(st, hm, ib, ik)
subroutine, public propagation_ops_finish_unpack(st, hm, ib, ik)
subroutine, public propagation_ops_elec_move_ions(wo, gr, hm, st, namespace, space, ions_dyn, ions, ext_partners, mc, time, dt, save_pos)
subroutine td_zop(xre, xim, yre, yim)
operators for Crank-Nicolson scheme
subroutine zbatch_qmr_dotu(namespace, mesh, st, xb, bb, op, max_iter, iter_used, residue, threshold, use_initial_guess)
for complex symmetric matrices W Chen and B Poirier, J Comput Phys 219, 198-209 (2006)
subroutine, public td_crank_nicolson(hm, namespace, space, gr, st, tr, time, dt, ions_dyn, ions, ext_partners, mc, use_sparskit)
Crank-Nicolson propagator.
subroutine td_zopt(xre, xim, yre, yim)
Transpose of H (called e.g. by bi-conjugate gradient solver)
subroutine propagator_qmr_op_batch(xxb, yyb)
operators for Crank-Nicolson scheme
This module is intended to contain "only mathematical" functions and procedures.
Definition: solvers.F90:115
subroutine, public zsparskit_solver_run(namespace, sk, op, opt, sol, rhs)
Definition: sparskit.F90:784
integer pure function, public states_elec_block_max(st, ib)
return index of last state in block ib
integer pure function, public states_elec_block_min(st, ib)
return index of first state in block ib
Definition: xc.F90:114
Describes mesh distribution to nodes.
Definition: mesh.F90:186
The states_elec_t class contains all electronic wave functions.
batches of electronic states
Definition: wfs_elec.F90:139
int true(void)
subroutine preconditioner(x, hx)
Simple preconditioner Here we need to approximate P^-1 We use the Jacobi approximation and that \nabl...
Definition: xc_fbe.F90:325