37 use,
intrinsic :: iso_fortran_env
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
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
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
106 if(
associated(gfield))
then
112 if (use_sparskit)
then
113 message(1) =
"Cannot use SPARSKIT in Crank-Nicolson propagator: not compiled with SPARSKIT support."
121 namespace_p => namespace
127 t_op = time - dt/
m_two
135 safe_allocate(zpsi(1:np*st%d%dim))
136 safe_allocate(rhs(1:np*st%d%dim))
142 call hm%ks_pot%interpolate_potentials(tr%vks_old, 3, time, dt, time -dt/
m_two)
149 do ik = st%d%kpt%start, st%d%kpt%end
151 do ib = st%group%block_start, st%group%block_end
155 call st%group%psib(ib, ik)%copy_to(psib_rhs)
161 call batch_axpy(np, dt, hm%inh_st%group%psib(ib, ik), psib_rhs)
164 if(use_sparskit)
then
167 do ist = minst, maxst
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))
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))
187 safe_allocate(iter_used(psib_rhs%nst))
188 safe_allocate(residue(psib_rhs%nst))
190 call zbatch_qmr_dotu(namespace, gr, st, st%group%psib(ib, ik), psib_rhs, &
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)
202 safe_deallocate_a(iter_used)
203 safe_deallocate_a(residue)
222 safe_deallocate_a(zpsi)
223 safe_deallocate_a(rhs)
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(:)
238 complex(real64),
allocatable :: zpsi(:, :)
242 safe_allocate(zpsi(1:mesh_p%np_part, 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)
249 call tr_p%te%apply_single(namespace_p, mesh_p, hm_p, zpsi, ist_op, ik_op, -dt_op/
m_two)
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))
256 safe_deallocate_a(zpsi)
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(:)
272 complex(real64),
allocatable :: zpsi(:, :)
279 safe_allocate(zpsi(1:mesh_p%np_part, 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)
286 call tr_p%te%apply_single(namespace_p, mesh_p, hm_p, zpsi, ist_op, ik_op, -dt_op/
m_two)
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))
293 safe_deallocate_a(zpsi)
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)
321 subroutine zbatch_qmr_dotu(namespace, mesh, st, xb, bb, op, max_iter, iter_used, &
322 residue, threshold, use_initial_guess)
324 class(
mesh_t),
intent(in) :: mesh
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
343 type(
wfs_elec_t) :: vvb, res, qqb, ppb, deltax, deltar
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(:)
350 integer,
parameter :: &
351 QMR_NOT_CONVERGED = 0, &
355 qmr_breakdown_pb = 4, &
356 qmr_breakdown_vz = 5, &
357 qmr_breakdown_qp = 6, &
358 qmr_breakdown_gamma = 7
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))
377 safe_allocate(status(1:xb%nst))
378 safe_allocate(saved_iter(1:xb%nst))
380 safe_allocate(exception_saved(1:mesh%np, 1:st%d%dim, 1:xb%nst))
386 call xb%copy_to(deltax)
387 call xb%copy_to(deltar)
398 call batch_xpay(mesh%np, bb, -1.0_real64, vvb)
399 call vvb%copy_data_to(mesh%np, res)
407 if (abs(rho(ii)) <= threshold)
then
408 status(ii) = qmr_res_zero
409 residue(ii) = rho(ii)
412 saved_res(ii) = residue(ii)
419 call bb%copy_data_to(mesh%np, vvb)
420 call vvb%copy_data_to(mesh%np, res)
426 status = qmr_not_converged
432 residue(ii) = rho(ii)
434 if (status(ii) == qmr_not_converged .and. abs(norm_b(ii)) <=
m_tiny)
then
436 status(ii) = qmr_b_zero
437 residue(ii) = norm_b(ii)
438 saved_iter(ii) = iter
439 saved_res(ii) = residue(ii)
451 do while(iter < max_iter)
455 if (all(status /= qmr_not_converged))
exit
459 if (status(ii) == qmr_not_converged .and. (abs(rho(ii)) <
m_tiny .or. abs(xsi(ii)) <
m_tiny))
then
461 status(ii) = qmr_breakdown_pb
462 saved_iter(ii) = iter
463 saved_res(ii) = residue(ii)
466 alpha(ii) = alpha(ii)*xsi(ii)/rho(ii)
474 delta = delta / alpha
479 if (status(ii) == qmr_not_converged .and. abs(delta(ii)) <
m_tiny)
then
481 status(ii) = qmr_breakdown_vz
482 saved_iter(ii) = iter
483 saved_res(ii) = residue(ii)
489 call vvb%copy_data_to(mesh%np, qqb)
492 call batch_xpay(mesh%np, vvb, -rho*delta/eps, qqb, a_full = .false.)
498 call batch_scal(mesh%np, alpha, ppb, a_full = .false.)
505 if (status(ii) == qmr_not_converged .and. abs(eps(ii)) <
m_tiny)
then
507 status(ii) = qmr_breakdown_qp
508 saved_iter(ii) = iter
509 saved_res(ii) = residue(ii)
512 beta(ii) = eps(ii)/delta(ii)
516 call batch_xpay(mesh%np, ppb, -beta, vvb, a_full = .false.)
526 xsi = rho / (alpha**2)
530 oldtheta(ii) = theta(ii)
532 theta(ii) = rho(ii)/(gamma(ii)*abs(beta(ii)))
534 oldgamma(ii) = gamma(ii)
539 if (status(ii) == qmr_not_converged .and. abs(gamma(ii)) <
m_tiny)
then
541 status(ii) = qmr_breakdown_gamma
542 saved_iter(ii) = iter
543 saved_res(ii) = residue(ii)
547 eta(ii) = -eta(ii)*oldrho(ii)*gamma(ii)**2/(beta(ii)*oldgamma(ii)**2)
553 call qqb%copy_data_to(mesh%np, deltax)
554 call batch_scal(mesh%np, eta*alpha, deltax, a_full = .false.)
557 call ppb%copy_data_to(mesh%np, deltar)
558 call batch_scal(mesh%np, eta, deltar, a_full = .false.)
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.)
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.)
577 call batch_axpy(mesh%np, -1.0_real64, deltar, res)
582 residue(ii) = residue(ii)/norm_b(ii)
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.'
597 if (status(ii) == qmr_not_converged .or. status(ii) == qmr_converged)
then
599 iter_used(ii) = iter -1
602 iter_used(ii) = saved_iter(ii)
603 residue(ii) = saved_res(ii)
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."
611 case (qmr_breakdown_pb)
612 write(
message(1),
'(a)')
"QMR breakdown, cannot continue: b or P*b is the zero vector!"
614 case (qmr_breakdown_vz)
615 write(
message(1),
'(a)')
"QMR breakdown, cannot continue: v^T*z is zero!"
617 case (qmr_breakdown_qp)
618 write(
message(1),
'(a)')
"QMR breakdown, cannot continue: q^T*p is zero!"
620 case (qmr_breakdown_gamma)
621 write(
message(1),
'(a)')
"QMR breakdown, cannot continue: gamma is zero!"
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)
649 safe_deallocate_a(saved_res)
650 safe_deallocate_a(status)
651 safe_deallocate_a(saved_iter)
batchified version of the BLAS axpy routine:
scale a batch by a constant or vector
There are several ways how to call batch_set_state and batch_get_state:
double sqrt(double __x) __attribute__((__nothrow__
subroutine, public accel_set_stream(stream_number)
This module implements common operations on batches of mesh functions.
subroutine, public batch_set_zero(this, np, async)
fill all mesh functions of the batch with zero
This module implements a calculator for the density and defines related functions.
subroutine, public density_calc_end(this, allreduce, symmetrize)
Finalize the density calculation.
subroutine, public density_calc_accumulate(this, psib, async)
Accumulate weighted orbital densities for a batch psib.
subroutine, public density_calc_init(this, st, gr, density)
initialize the density calculator
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
real(real64), parameter, public m_zero
real(real64), parameter, public m_tiny
complex(real64), parameter, public m_z0
real(real64), parameter, public m_half
real(real64), parameter, public m_one
This module implements the underlying real-space grid.
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.
subroutine, public mesh_batch_nrm2(mesh, aa, nrm2, reduce)
Calculate the norms (norm2, not the square!) of a batch of mesh functions.
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.
subroutine, public messages_warning(no_lines, all_nodes, namespace)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
This module handles the communicators for the various parallelization strategies.
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.
subroutine, public zsparskit_solver_run(namespace, sk, op, opt, sol, rhs)
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.
The states_elec_t class contains all electronic wave functions.
batches of electronic states
subroutine preconditioner(x, hx)
Simple preconditioner Here we need to approximate P^-1 We use the Jacobi approximation and that \nabl...