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