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