27 use,
intrinsic :: iso_fortran_env
81 real(real64),
allocatable :: ddf(:, :, :)
82 real(real64),
allocatable :: ddv(:, :, :)
83 real(real64),
allocatable :: df_old(:, :)
84 real(real64),
allocatable :: dvin_old(:, :)
85 real(real64),
allocatable :: dvin(:, :)
86 real(real64),
allocatable :: dvout(:, :)
87 real(real64),
allocatable :: dvnew(:, :)
88 real(real64),
allocatable :: dresidual(:, :)
91 complex(real64),
allocatable :: zdf(:, :, :)
92 complex(real64),
allocatable :: zdv(:, :, :)
93 complex(real64),
allocatable :: zf_old(:, :)
94 complex(real64),
allocatable :: zvin_old(:, :)
95 complex(real64),
allocatable :: zvin(:, :)
96 complex(real64),
allocatable :: zvout(:, :)
97 complex(real64),
allocatable :: zvnew(:, :)
98 complex(real64),
allocatable :: zresidual(:, :)
100 type(type_t) :: func_type
101 integer :: d1, d2, d3
108 type(mixfield_t),
pointer :: p
111 integer,
parameter :: MAX_AUXMIXFIELD = 5
122 type(derivatives_t),
pointer :: der
125 real(real64) :: coeff
126 real(real64) :: residual_coeff
129 integer,
public :: ns
130 integer,
public :: ns_restart
137 type(mixfield_t) :: mixfield
138 integer :: nauxmixfield
139 type(mixfield_ptr_t) :: auxmixfield(MAX_AUXMIXFIELD)
145 real(real64) :: kerker_factor
146 logical :: precondition
147 type(nl_operator_t) :: preconditioner
151 procedure :: compute_residuals_aux_field
171 subroutine mix_init(smix, namespace, space, der, d1, d2, def_, func_type_, prefix_)
172 type(mix_t),
intent(out) :: smix
173 type(namespace_t),
intent(in) :: namespace
176 integer,
intent(in) :: d1
177 integer,
intent(in) :: d2
178 integer,
optional,
intent(in) :: def_
179 type(
type_t),
optional,
intent(in) :: func_type_
180 character(len=*),
optional,
intent(in) :: prefix_
183 character(len=32) :: prefix
190 def = option__mixingscheme__broyden
191 if (
present(def_)) def = def_
192 if (
present(func_type_))
then
193 func_type = func_type_
198 if (
present(prefix_)) prefix = prefix_
239 call parse_variable(namespace, trim(prefix)+
'MixingPreconditioner', .false., smix%precondition)
240 if (der%dim /= 3) smix%precondition = .false.
251 call parse_variable(namespace, trim(prefix)+
'Mixing', 0.3_real64, smix%coeff)
264 call parse_variable(namespace, trim(prefix)+
'MixingResidual', 0.05_real64, smix%residual_coeff)
265 if (smix%residual_coeff <=
m_zero .or. smix%residual_coeff >
m_one)
then
266 call messages_input_error(namespace,
'MixingResidual',
'Value should be positive and smaller than one.')
278 if (smix%scheme /= option__mixingscheme__linear)
then
279 call parse_variable(namespace, trim(prefix)//
'MixNumberSteps', 4, smix%ns)
294 if (smix%scheme /= option__mixingscheme__linear)
then
295 call parse_variable(namespace, trim(prefix)//
'MixingRestart', 20, smix%ns_restart)
301 write(
message(1),
'(A,I4,A,I4,A)')
"Info: Mixing uses ", smix%ns,
" steps and restarts after ", &
302 smix%ns_restart,
" steps."
315 call parse_variable(namespace, trim(prefix)//
'MixInterval', 1, smix%interval)
316 if (smix%interval < 1)
call messages_input_error(namespace,
'MixInterval',
'MixInterval must be larger or equal than 1')
331 call parse_variable(namespace, trim(prefix)+
'MixingKerker', .false., smix%kerker)
344 call parse_variable(namespace, trim(prefix)+
'MixingKerkerFactor', 1._real64, smix%kerker_factor)
346 smix%nauxmixfield = 0
347 do ii = 1,max_auxmixfield
348 nullify(smix%auxmixfield(ii)%p)
351 call mixfield_init(smix, smix%mixfield, d1, d2, smix%ns, func_type)
361 integer :: ns, maxp, ip, is
362 real(real64),
parameter :: weight = 50.0_real64
369 assert(.not. der%mesh%use_curvilinear)
374 call nl_operator_build(space, der%mesh, smix%preconditioner, der%mesh%np, const_w = .not. der%mesh%use_curvilinear)
376 ns = smix%preconditioner%stencil%size
378 if (smix%preconditioner%const_w)
then
387 select case (sum(abs(smix%preconditioner%stencil%points(1:der%dim, is))))
389 smix%preconditioner%w(is, ip) =
m_one + weight/8.0_real64
391 smix%preconditioner%w(is, ip) = weight/16.0_real64
393 smix%preconditioner%w(is, ip) = weight/32.0_real64
395 smix%preconditioner%w(is, ip) = weight/64.0_real64
414 type(
mix_t),
intent(inout) :: smix
429 type(
mix_t),
intent(inout) :: smix
439 smix%nauxmixfield = 0
440 do ii = 1,max_auxmixfield
441 nullify(smix%auxmixfield(ii)%p)
449 subroutine mix_dump(namespace, restart, smix, space, mesh, ierr)
453 class(
space_t),
intent(in) :: space
454 class(
mesh_t),
intent(in) :: mesh
455 integer,
intent(out) :: ierr
457 integer :: iunit, id2, id3, err, err2(4)
458 character(len=40) :: lines(7)
459 character(len=80) :: filename
471 message(1) =
"Debug: Writing mixing restart."
476 assert(mesh%np == smix%mixfield%d1)
480 write(lines(1),
'(a11,i1)')
'scheme= ', smix%scheme
482 write(lines(2),
'(a11,i10)')
'd1= ', mesh%np_global
483 write(lines(3),
'(a11,i10)')
'd2= ', smix%mixfield%d2
484 write(lines(4),
'(a11,i10)')
'd3= ', smix%mixfield%d3
485 write(lines(5),
'(a11,i10)')
'iter= ', smix%iter
486 write(lines(6),
'(a11,i10)')
'ns= ', smix%ns
487 write(lines(7),
'(a11,i10)')
'last_ipos= ', smix%last_ipos
495 if (smix%scheme /= option__mixingscheme__linear)
then
496 do id2 = 1, smix%mixfield%d2
497 do id3 = 1, smix%mixfield%d3
499 write(filename,
'(a3,i2.2,i2.2)')
'df_', id2, id3
500 if (smix%mixfield%func_type ==
type_float)
then
505 err2(1) = err2(1) + err
507 write(filename,
'(a3,i2.2,i2.2)')
'dv_', id2, id3
508 if (smix%mixfield%func_type ==
type_float)
then
513 err2(2) = err2(2) + err
517 write(filename,
'(a6,i2.2)')
'f_old_', id2
518 if (smix%mixfield%func_type ==
type_float)
then
523 err2(3) = err2(3) + err
525 write(filename,
'(a8,i2.2)')
'vin_old_', id2
526 if (smix%mixfield%func_type ==
type_float)
then
531 err2(4) = err2(4) + err
535 if (err2(1) /= 0) ierr = ierr + 2
536 if (err2(2) /= 0) ierr = ierr + 4
537 if (err2(3) /= 0) ierr = ierr + 8
538 if (err2(4) /= 0) ierr = ierr + 16
542 message(1) =
"Debug: Writing mixing restart done."
551 subroutine mix_load(namespace, restart, smix, space, mesh, ierr)
554 type(
mix_t),
intent(inout) :: smix
555 class(
space_t),
intent(in) :: space
556 class(
mesh_t),
intent(in) :: mesh
557 integer,
intent(out) :: ierr
559 integer :: iunit, err, err2(4)
560 integer :: scheme, d1, d2, d3, ns
562 character(len=11) :: str
563 character(len=80) :: filename
564 character(len=256) :: lines(7)
577 message(1) =
"Debug: Reading mixing restart."
587 read(lines(1), *) str, scheme
588 read(lines(2), *) str, d1
589 read(lines(3), *) str, d2
590 read(lines(4), *) str, d3
591 read(lines(5), *) str, smix%iter
592 read(lines(6), *) str, ns
593 read(lines(7), *) str, smix%last_ipos
600 if (scheme /= smix%scheme .or. ns /= smix%ns)
then
601 message(1) =
"The mixing scheme from the restart data is not the same as the one used in the current calculation."
607 if (mesh%np_global /= d1 .or. mesh%np /= smix%mixfield%d1 .or. d2 /= smix%mixfield%d2)
then
608 message(1) =
"The dimensions of the arrays from the mixing restart data"
609 message(2) =
"are not the same as the ones used in this calculation."
619 if (smix%scheme /= option__mixingscheme__linear)
then
621 do id2 = 1, smix%mixfield%d2
622 do id3 = 1, smix%mixfield%d3
624 write(filename,
'(a3,i2.2,i2.2)')
'df_', id2, id3
625 if (smix%mixfield%func_type ==
type_float)
then
630 if (err /= 0) err2(1) = err2(1) + 1
632 write(filename,
'(a3,i2.2,i2.2)')
'dv_', id2, id3
633 if (smix%mixfield%func_type ==
type_float)
then
638 if (err /= 0) err2(2) = err2(2) + 1
642 write(filename,
'(a6,i2.2)')
'f_old_', id2
643 if (smix%mixfield%func_type ==
type_float)
then
648 if (err /= 0) err2(3) = err2(3) + 1
650 write(filename,
'(a8,i2.2)')
'vin_old_', id2
651 if (smix%mixfield%func_type ==
type_float)
then
656 if (err /= 0) err2(4) = err2(4) + 1
660 if (err2(1) /= 0) ierr = ierr + 8
661 if (err2(2) /= 0) ierr = ierr + 16
662 if (err2(3) /= 0) ierr = ierr + 32
663 if (err2(4) /= 0) ierr = ierr + 64
673 message(1) =
"Debug: Reading mixing restart done."
681 type(
mix_t),
intent(in) :: this
683 coefficient = this%coeff
686 integer pure function
mix_scheme(this) result(scheme)
687 type(
mix_t),
intent(in) :: this
692 integer pure function
mix_d3(this)
693 type(
mix_t),
intent(in) :: this
699 type(
mix_t),
target,
intent(in) :: this
700 type(
mixfield_t),
pointer,
intent(out) :: mixfield
702 mixfield => this%mixfield
706 subroutine mixing(namespace, smix)
707 type(namespace_t),
intent(in) :: namespace
708 type(
mix_t),
intent(inout) :: smix
712 if (smix%mixfield%func_type == type_float)
then
713 call dmixing(namespace, smix, smix%mixfield%dvin, smix%mixfield%dvout, smix%mixfield%dvnew)
715 call zmixing(namespace, smix, smix%mixfield%zvin, smix%mixfield%zvout, smix%mixfield%zvnew)
722 type(namespace_t),
intent(in) :: namespace
723 type(
mix_t),
intent(inout) :: smix
724 type(
mixfield_t),
target,
intent(in) :: mixfield
728 smix%nauxmixfield = smix%nauxmixfield + 1
729 smix%auxmixfield(smix%nauxmixfield)%p => mixfield
731 if (smix%scheme == option__mixingscheme__diis)
then
732 message(1) =
'Mixing scheme DIIS is not implemented for auxiliary mixing fields'
733 call messages_fatal(1, namespace=namespace)
740 subroutine mixfield_init(smix, mixfield, d1, d2, d3, func_type)
741 type(
mix_t),
intent(in) :: smix
743 integer,
intent(in) :: d1, d2, d3
744 type(type_t),
intent(in) :: func_type
752 mixfield%func_type = func_type
754 if (smix%scheme /= option__mixingscheme__linear)
then
755 if (mixfield%func_type == type_float)
then
756 safe_allocate( mixfield%ddf(1:d1, 1:d2, 1:d3))
757 safe_allocate( mixfield%ddv(1:d1, 1:d2, 1:d3))
758 safe_allocate(mixfield%dvin_old(1:d1, 1:d2))
759 safe_allocate( mixfield%df_old(1:d1, 1:d2))
761 safe_allocate( mixfield%zdf(1:d1, 1:d2, 1:d3))
762 safe_allocate( mixfield%zdv(1:d1, 1:d2, 1:d3))
763 safe_allocate(mixfield%zvin_old(1:d1, 1:d2))
764 safe_allocate( mixfield%zf_old(1:d1, 1:d2))
768 if (mixfield%func_type == type_float)
then
769 safe_allocate(mixfield%dvin(1:d1, 1:d2))
770 safe_allocate(mixfield%dvout(1:d1, 1:d2))
771 safe_allocate(mixfield%dvnew(1:d1, 1:d2))
772 safe_allocate(mixfield%dresidual(1:d1, 1:d2))
774 safe_allocate(mixfield%zvin(1:d1, 1:d2))
775 safe_allocate(mixfield%zvout(1:d1, 1:d2))
776 safe_allocate(mixfield%zvnew(1:d1, 1:d2))
777 safe_allocate(mixfield%zresidual(1:d1, 1:d2))
791 if (smix%scheme /= option__mixingscheme__linear)
then
792 if (mixfield%func_type == type_float)
then
793 safe_deallocate_a(mixfield%ddf)
794 safe_deallocate_a(mixfield%ddv)
795 safe_deallocate_a(mixfield%dvin_old)
796 safe_deallocate_a(mixfield%df_old)
798 safe_deallocate_a(mixfield%zdf)
799 safe_deallocate_a(mixfield%zdv)
800 safe_deallocate_a(mixfield%zvin_old)
801 safe_deallocate_a(mixfield%zf_old)
805 if (mixfield%func_type == type_float)
then
806 safe_deallocate_a(mixfield%dvin)
807 safe_deallocate_a(mixfield%dvout)
808 safe_deallocate_a(mixfield%dvnew)
809 safe_deallocate_a(mixfield%dresidual)
811 safe_deallocate_a(mixfield%zvin)
812 safe_deallocate_a(mixfield%zvout)
813 safe_deallocate_a(mixfield%zvnew)
814 safe_deallocate_a(mixfield%zresidual)
822 integer,
intent(in) :: scheme
824 integer :: d1, d2, d3
832 if (scheme /= option__mixingscheme__linear)
then
833 if (mixfield%func_type == type_float)
then
834 assert(
allocated(mixfield%ddf))
835 mixfield%ddf(1:d1, 1:d2, 1:d3) = m_zero
836 mixfield%ddv(1:d1, 1:d2, 1:d3) = m_zero
837 mixfield%dvin_old(1:d1, 1:d2) = m_zero
838 mixfield%df_old(1:d1, 1:d2) = m_zero
840 assert(
allocated(mixfield%zdf))
841 mixfield%zdf(1:d1, 1:d2, 1:d3) = m_z0
842 mixfield%zdv(1:d1, 1:d2, 1:d3) = m_z0
843 mixfield%zvin_old(1:d1, 1:d2) = m_z0
844 mixfield%zf_old(1:d1, 1:d2) = m_z0
848 if (mixfield%func_type == type_float)
then
849 mixfield%dvin(1:d1, 1:d2) = m_zero
850 mixfield%dvout(1:d1, 1:d2) = m_zero
851 mixfield%dvnew(1:d1, 1:d2) = m_zero
852 mixfield%dresidual(1:d1, 1:d2) = m_zero
854 mixfield%zvin(1:d1, 1:d2) = m_z0
855 mixfield%zvout(1:d1, 1:d2) = m_z0
856 mixfield%zvnew(1:d1, 1:d2) = m_z0
857 mixfield%zresidual(1:d1, 1:d2) = m_z0
869 real(real64),
intent(in) :: vin_re(:,:), vin_im(:,:)
873 mixfield%zvin(1:mixfield%d1, 1:mixfield%d2) = vin_re(1:mixfield%d1, 1:mixfield%d2) &
874 + m_zi * vin_im(1:mixfield%d1, 1:mixfield%d2)
881 real(real64),
intent(in) :: vout_re(:,:), vout_im(:,:)
885 mixfield%zvout(1:mixfield%d1, 1:mixfield%d2) = vout_re(1:mixfield%d1, 1:mixfield%d2) &
886 + m_zi * vout_im(1:mixfield%d1, 1:mixfield%d2)
893 real(real64),
intent(inout) :: re(:,:), im(:,:)
895 push_sub(mixfield_get_ddvnew)
897 re(1:mixfield%d1, 1:mixfield%d2) = real(mixfield%zvnew(1:mixfield%d1, 1:mixfield%d2), real64)
898 im(1:mixfield%d1, 1:mixfield%d2) = aimag(mixfield%zvnew(1:mixfield%d1, 1:mixfield%d2))
900 pop_sub(mixfield_get_ddvnew)
912 class(
mix_t),
intent(inout) :: this
920 do i = 1, this%nauxmixfield
921 aux_field => this%auxmixfield(i)%p
922 dims = [aux_field%d1, aux_field%d2]
924 if (aux_field%func_type == type_float)
then
925 call dcompute_residual(this, dims, aux_field%dvin, aux_field%dvout, aux_field%dresidual)
927 call zcompute_residual(this, dims, aux_field%zvin, aux_field%zvout, aux_field%zresidual)
949 type(
mix_t),
intent(inout) :: smix
956 call smix%compute_residuals_aux_field()
958 do i = 1, smix%nauxmixfield
959 field => smix%auxmixfield(i)%p
961 if (field%func_type == type_float)
then
962 call dmixing_linear(field%d1, field%d2, smix%coeff, field%dvin, field%dresidual, field%dvnew)
964 call zmixing_linear(field%d1, field%d2, smix%coeff, field%zvin, field%zresidual, field%zvnew)
977#include "mix_inc.F90"
980#include "complex.F90"
982#include "mix_inc.F90"
subroutine init_preconditioner()
type(debug_t), save, public debug
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
real(real64), parameter, public m_zero
real(real64), parameter, public m_one
This module is intended to contain "only mathematical" functions and procedures.
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)
subroutine, public messages_obsolete_variable(namespace, name, rep)
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_input_error(namespace, var, details, row, column)
subroutine, public messages_experimental(name, namespace)
subroutine, public mixfield_end(smix, mixfield)
Deallocate all arrays of a mixfield instance.
integer pure function, public mix_scheme(this)
subroutine dmixfield_set_vin(mixfield, vin)
real(real64) pure function, public mix_coefficient(this)
subroutine, public mixing(namespace, smix)
Main entry-point to SCF mixer.
subroutine, public mixfield_init(smix, mixfield, d1, d2, d3, func_type)
Initialise all attributes of a mixfield instance.
subroutine ddmixfield_get_vnew(mixfield, re, im)
subroutine zmixfield_get_vnew(mixfield, vnew)
subroutine dcompute_residual(smix, dims, vin, vout, residual)
Compute the residual of the potential (or density) for SCF mixing.
subroutine, public mix_get_field(this, mixfield)
subroutine compute_residuals_aux_field(this)
Compute the residuals of the auxilliary fields.
subroutine zmixfield_set_vout(mixfield, vout)
subroutine, public mix_add_auxmixfield(namespace, smix, mixfield)
subroutine dmixfield_get_vnew(mixfield, vnew)
subroutine dmixing_linear(d1, d2, coeff, vin, residual, vnew)
Linear mixing of the input and output potentials.
subroutine, public mix_dump(namespace, restart, smix, space, mesh, ierr)
subroutine, public mixfield_clear(scheme, mixfield)
Zero all potential and field attributes of a mixfield instance.
subroutine, public mix_load(namespace, restart, smix, space, mesh, ierr)
subroutine, public mix_init(smix, namespace, space, der, d1, d2, def_, func_type_, prefix_)
Initialise mix_t instance.
subroutine ddmixfield_set_vin(mixfield, vin_re, vin_im)
subroutine zmixfield_set_vin(mixfield, vin)
subroutine, public zmixing(namespace, smix, vin, vout, vnew)
Mix the input and output potentials (or densities) according to some scheme.
integer pure function, public mix_d3(this)
subroutine dmixfield_set_vout(mixfield, vout)
subroutine zcompute_residual(smix, dims, vin, vout, residual)
Compute the residual of the potential (or density) for SCF mixing.
subroutine ddmixfield_set_vout(mixfield, vout_re, vout_im)
subroutine, public dmixing(namespace, smix, vin, vout, vnew)
Mix the input and output potentials (or densities) according to some scheme.
subroutine linear_mixing_aux_field(smix)
Linear mixing of the auxilliary fields.
subroutine zmixing_linear(d1, d2, coeff, vin, residual, vnew)
Linear mixing of the input and output potentials.
subroutine, public mix_end(smix)
subroutine, public mix_clear(smix)
This module defines non-local operators.
subroutine, public nl_operator_init(op, label)
initialize an instance of a non-local operator by setting the label
subroutine, public nl_operator_update_gpu_buffers(op)
subroutine, public nl_operator_output_weights(this)
subroutine, public nl_operator_end(op)
subroutine, public nl_operator_build(space, mesh, op, np, const_w, regenerate)
subroutine, public nl_operator_allocate_gpu_buffers(op)
subroutine, public restart_read(restart, iunit, lines, nlines, ierr)
subroutine, public restart_close(restart, iunit)
Close a file previously opened with restart_open.
subroutine, public restart_write(restart, iunit, lines, nlines, ierr)
logical pure function, public restart_skip(restart)
Returns true if the restart information should neither be read nor written. This might happen because...
integer function, public restart_open(restart, filename, status, position, silent)
Open file "filename" found inside the current restart directory. Depending on the type of restart,...
This module is intended to contain "only mathematical" functions and procedures.
This module defines routines, generating operators for a cubic stencil.
subroutine, public stencil_cube_get_lapl(this, dim, order)
type(type_t), public type_float
class representing derivatives
Describes mesh distribution to nodes.
Quantities used in mixing: Input, output and new potentials, and the residuals.