26 use,
intrinsic :: iso_fortran_env
80 real(real64),
allocatable :: ddf(:, :, :)
81 real(real64),
allocatable :: ddv(:, :, :)
82 real(real64),
allocatable :: df_old(:, :)
83 real(real64),
allocatable :: dvin_old(:, :)
84 real(real64),
allocatable :: dvin(:, :)
85 real(real64),
allocatable :: dvout(:, :)
86 real(real64),
allocatable :: dvnew(:, :)
87 real(real64),
allocatable :: dresidual(:, :)
90 complex(real64),
allocatable :: zdf(:, :, :)
91 complex(real64),
allocatable :: zdv(:, :, :)
92 complex(real64),
allocatable :: zf_old(:, :)
93 complex(real64),
allocatable :: zvin_old(:, :)
94 complex(real64),
allocatable :: zvin(:, :)
95 complex(real64),
allocatable :: zvout(:, :)
96 complex(real64),
allocatable :: zvnew(:, :)
97 complex(real64),
allocatable :: zresidual(:, :)
99 type(type_t) :: func_type
100 integer :: d1, d2, d3
103 logical :: mix_spin_density_matrix
104 real(real64) :: last_residue
109 type(mixfield_t),
pointer :: p
112 integer,
parameter :: MAX_AUXMIXFIELD = 5
123 type(derivatives_t),
pointer :: der
126 real(real64),
allocatable :: coeff(:)
127 real(real64) :: adaptive_damping
128 integer :: n_backtrack = 0
129 real(real64) :: residual_coeff
132 integer,
public :: ns
133 integer,
public :: ns_restart
140 type(mixfield_t) :: mixfield
141 integer :: nauxmixfield
142 type(mixfield_ptr_t) :: auxmixfield(MAX_AUXMIXFIELD)
148 real(real64) :: kerker_factor
149 logical :: precondition
150 type(nl_operator_t) :: preconditioner
153 logical :: mix_spin_density_matrix
155 procedure :: compute_residuals_aux_field
174 subroutine mix_init(smix, namespace, space, der, d1, d2, def_, func_type_, prefix_)
179 integer,
intent(in) :: d1
180 integer,
intent(in) :: d2
181 integer,
optional,
intent(in) :: def_
182 type(
type_t),
optional,
intent(in) :: func_type_
183 character(len=*),
optional,
intent(in) :: prefix_
186 character(len=32) :: prefix
188 real(real64) :: coeff
194 def = option__mixingscheme__broyden
195 if (
present(def_)) def = def_
196 if (
present(func_type_))
then
197 func_type = func_type_
202 if (
present(prefix_)) prefix = prefix_
251 call parse_variable(namespace, trim(prefix)+
'MixingPreconditioner', .false., smix%precondition)
252 if (der%dim /= 3) smix%precondition = .false.
264 call parse_variable(namespace, trim(prefix)+
'Mixing', 0.3_real64, coeff)
268 safe_allocate(smix%coeff(1:d2))
270 smix%adaptive_damping =
m_one
284 call parse_variable(namespace, trim(prefix)+
'MixingSpinDensityMatrix', .false., smix%mix_spin_density_matrix)
294 call parse_variable(namespace, trim(prefix)+
'MixingMagnetization', 1.5_real64, coeff)
296 if (.not. smix%mix_spin_density_matrix) smix%coeff(2:d2) = coeff
298 smix%mix_spin_density_matrix = .
true.
309 call parse_variable(namespace, trim(prefix)+
'MixingResidual', 0.05_real64, smix%residual_coeff)
310 if (smix%residual_coeff <=
m_zero .or. smix%residual_coeff >
m_one)
then
311 call messages_input_error(namespace,
'MixingResidual',
'Value should be positive and smaller than one.')
323 if (smix%scheme /= option__mixingscheme__linear)
then
324 call parse_variable(namespace, trim(prefix)//
'MixNumberSteps', 4, smix%ns)
339 if (smix%scheme /= option__mixingscheme__linear)
then
340 call parse_variable(namespace, trim(prefix)//
'MixingRestart', 20, smix%ns_restart)
346 write(
message(1),
'(A,I4,A,I4,A)')
"Info: Mixing uses ", smix%ns,
" steps and restarts after ", &
347 smix%ns_restart,
" steps."
360 call parse_variable(namespace, trim(prefix)//
'MixInterval', 1, smix%interval)
361 if (smix%interval < 1)
call messages_input_error(namespace,
'MixInterval',
'MixInterval must be larger or equal than 1')
376 call parse_variable(namespace, trim(prefix)+
'MixingKerker', .false., smix%kerker)
389 call parse_variable(namespace, trim(prefix)+
'MixingKerkerFactor', 1._real64, smix%kerker_factor)
391 smix%nauxmixfield = 0
392 do ii = 1,max_auxmixfield
393 nullify(smix%auxmixfield(ii)%p)
396 call mixfield_init(smix, smix%mixfield, d1, d2, smix%ns, func_type)
406 integer :: ns, maxp, ip, is
407 real(real64),
parameter :: weight = 50.0_real64
414 assert(.not. der%mesh%use_curvilinear)
419 call nl_operator_build(space, der%mesh, smix%preconditioner, der%mesh%np, const_w = .not. der%mesh%use_curvilinear)
421 ns = smix%preconditioner%stencil%size
423 if (smix%preconditioner%const_w)
then
432 select case (sum(abs(smix%preconditioner%stencil%points(1:der%dim, is))))
434 smix%preconditioner%w(is, ip) =
m_one + weight/8.0_real64
436 smix%preconditioner%w(is, ip) = weight/16.0_real64
438 smix%preconditioner%w(is, ip) = weight/32.0_real64
440 smix%preconditioner%w(is, ip) = weight/64.0_real64
459 type(
mix_t),
intent(inout) :: smix
467 smix%adaptive_damping =
m_one
476 type(
mix_t),
intent(inout) :: smix
486 smix%nauxmixfield = 0
487 do ii = 1,max_auxmixfield
488 nullify(smix%auxmixfield(ii)%p)
491 safe_deallocate_a(smix%coeff)
498 subroutine mix_dump(namespace, restart, smix, mesh, ierr)
501 type(
mix_t),
intent(in) :: smix
502 class(
mesh_t),
intent(in) :: mesh
503 integer,
intent(out) :: ierr
505 integer :: iunit, id2, id3, err, err2(4)
506 character(len=40) :: lines(7)
507 character(len=80) :: filename
513 if (restart%skip())
then
518 message(1) =
"Debug: Writing mixing restart."
522 assert(mesh%np == smix%mixfield%d1)
525 iunit = restart%open(
'mixing')
526 if(restart%do_i_write())
then
527 write(lines(1),
'(a11,i1)')
'scheme= ', smix%scheme
529 write(lines(2),
'(a11,i10)')
'd1= ', mesh%np_global
530 write(lines(3),
'(a11,i10)')
'd2= ', smix%mixfield%d2
531 write(lines(4),
'(a11,i10)')
'd3= ', smix%mixfield%d3
532 write(lines(5),
'(a11,i10)')
'iter= ', smix%iter
533 write(lines(6),
'(a11,i10)')
'ns= ', smix%ns
534 write(lines(7),
'(a11,i10)')
'last_ipos= ', smix%last_ipos
535 call restart%write(iunit, lines, 7, err)
538 call restart%close(iunit)
543 if (smix%scheme /= option__mixingscheme__linear)
then
544 do id2 = 1, smix%mixfield%d2
545 do id3 = 1, smix%mixfield%d3
547 write(filename,
'(a3,i2.2,i2.2)')
'df_', id2, id3
548 if (smix%mixfield%func_type ==
type_float)
then
549 call restart%write_mesh_function(filename, mesh, smix%mixfield%ddf(1:mesh%np, id2, id3), err)
551 call restart%write_mesh_function(filename, mesh, smix%mixfield%zdf(1:mesh%np, id2, id3), err)
553 err2(1) = err2(1) + err
555 write(filename,
'(a3,i2.2,i2.2)')
'dv_', id2, id3
556 if (smix%mixfield%func_type ==
type_float)
then
557 call restart%write_mesh_function(filename, mesh, smix%mixfield%ddv(1:mesh%np, id2, id3), err)
559 call restart%write_mesh_function(filename, mesh, smix%mixfield%zdv(1:mesh%np, id2, id3), err)
561 err2(2) = err2(2) + err
565 write(filename,
'(a6,i2.2)')
'f_old_', id2
566 if (smix%mixfield%func_type ==
type_float)
then
567 call restart%write_mesh_function(filename, mesh, smix%mixfield%df_old(1:mesh%np, id2), err)
569 call restart%write_mesh_function(filename, mesh, smix%mixfield%zf_old(1:mesh%np, id2), err)
571 err2(3) = err2(3) + err
573 write(filename,
'(a8,i2.2)')
'vin_old_', id2
574 if (smix%mixfield%func_type ==
type_float)
then
575 call restart%write_mesh_function(filename, mesh, smix%mixfield%dvin_old(1:mesh%np, id2), err)
577 call restart%write_mesh_function(filename, mesh, smix%mixfield%zvin_old(1:mesh%np, id2), err)
579 err2(4) = err2(4) + err
583 if (err2(1) /= 0) ierr = ierr + 2
584 if (err2(2) /= 0) ierr = ierr + 4
585 if (err2(3) /= 0) ierr = ierr + 8
586 if (err2(4) /= 0) ierr = ierr + 16
589 message(1) =
"Debug: Writing mixing restart done."
597 subroutine mix_load(namespace, restart, smix, mesh, ierr)
600 type(
mix_t),
intent(inout) :: smix
601 class(
mesh_t),
intent(in) :: mesh
602 integer,
intent(out) :: ierr
604 integer :: iunit, err, err2(4)
605 integer :: scheme, d1, d2, d3, ns
607 character(len=11) :: str
608 character(len=80) :: filename
609 character(len=256) :: lines(7)
615 if (restart%skip())
then
621 message(1) =
"Debug: Reading mixing restart."
625 iunit = restart%open(
'mixing')
626 call restart%read(iunit, lines, 7, err)
630 read(lines(1), *) str, scheme
631 read(lines(2), *) str, d1
632 read(lines(3), *) str, d2
633 read(lines(4), *) str, d3
634 read(lines(5), *) str, smix%iter
635 read(lines(6), *) str, ns
636 read(lines(7), *) str, smix%last_ipos
638 call restart%close(iunit)
643 if (scheme /= smix%scheme .or. ns /= smix%ns)
then
644 message(1) =
"The mixing scheme from the restart data is not the same as the one used in the current calculation."
650 if (mesh%np_global /= d1 .or. mesh%np /= smix%mixfield%d1 .or. d2 /= smix%mixfield%d2)
then
651 message(1) =
"The dimensions of the arrays from the mixing restart data"
652 message(2) =
"are not the same as the ones used in this calculation."
662 if (smix%scheme /= option__mixingscheme__linear)
then
664 do id2 = 1, smix%mixfield%d2
665 do id3 = 1, smix%mixfield%d3
667 write(filename,
'(a3,i2.2,i2.2)')
'df_', id2, id3
668 if (smix%mixfield%func_type ==
type_float)
then
669 call restart%read_mesh_function(filename, mesh, smix%mixfield%ddf(1:mesh%np, id2, id3), err)
671 call restart%read_mesh_function(filename, mesh, smix%mixfield%zdf(1:mesh%np, id2, id3), err)
673 if (err /= 0) err2(1) = err2(1) + 1
675 write(filename,
'(a3,i2.2,i2.2)')
'dv_', id2, id3
676 if (smix%mixfield%func_type ==
type_float)
then
677 call restart%read_mesh_function(filename, mesh, smix%mixfield%ddv(1:mesh%np, id2, id3), err)
679 call restart%read_mesh_function(filename, mesh, smix%mixfield%zdv(1:mesh%np, id2, id3), err)
681 if (err /= 0) err2(2) = err2(2) + 1
685 write(filename,
'(a6,i2.2)')
'f_old_', id2
686 if (smix%mixfield%func_type ==
type_float)
then
687 call restart%read_mesh_function(filename, mesh, smix%mixfield%df_old(1:mesh%np, id2), err)
689 call restart%read_mesh_function(filename, mesh, smix%mixfield%zf_old(1:mesh%np, id2), err)
691 if (err /= 0) err2(3) = err2(3) + 1
693 write(filename,
'(a8,i2.2)')
'vin_old_', id2
694 if (smix%mixfield%func_type ==
type_float)
then
695 call restart%read_mesh_function(filename, mesh, smix%mixfield%dvin_old(1:mesh%np, id2), err)
697 call restart%read_mesh_function(filename, mesh, smix%mixfield%zvin_old(1:mesh%np, id2), err)
699 if (err /= 0) err2(4) = err2(4) + 1
703 if (err2(1) /= 0) ierr = ierr + 8
704 if (err2(2) /= 0) ierr = ierr + 16
705 if (err2(3) /= 0) ierr = ierr + 32
706 if (err2(4) /= 0) ierr = ierr + 64
715 if (ierr == 0 .and. smix%scheme == option__mixingscheme__broyden_adaptive)
then
716 smix%adaptive_damping =
m_one
718 smix%mixfield%last_residue =
m_zero
722 message(1) =
"Debug: Reading mixing restart done."
729 type(
mix_t),
intent(in) :: this
731 coefficient = this%coeff(1)
734 integer pure function
mix_scheme(this) result(scheme)
735 type(
mix_t),
intent(in) :: this
740 integer pure function
mix_d3(this)
741 type(
mix_t),
intent(in) :: this
747 type(
mix_t),
target,
intent(in) :: this
748 type(
mixfield_t),
pointer,
intent(out) :: mixfield
750 mixfield => this%mixfield
754 subroutine mixing(namespace, smix)
755 type(namespace_t),
intent(in) :: namespace
756 type(
mix_t),
intent(inout) :: smix
760 if (smix%mixfield%func_type == type_float)
then
761 call dmixing(namespace, smix, smix%mixfield%dvin, smix%mixfield%dvout, smix%mixfield%dvnew)
763 call zmixing(namespace, smix, smix%mixfield%zvin, smix%mixfield%zvout, smix%mixfield%zvnew)
770 type(namespace_t),
intent(in) :: namespace
771 type(
mix_t),
intent(inout) :: smix
772 type(
mixfield_t),
target,
intent(in) :: mixfield
776 smix%nauxmixfield = smix%nauxmixfield + 1
777 smix%auxmixfield(smix%nauxmixfield)%p => mixfield
779 if (smix%scheme == option__mixingscheme__diis)
then
780 message(1) =
'Mixing scheme DIIS is not implemented for auxiliary mixing fields'
781 call messages_fatal(1, namespace=namespace)
788 subroutine mixfield_init(smix, mixfield, d1, d2, d3, func_type)
789 type(
mix_t),
intent(in) :: smix
791 integer,
intent(in) :: d1, d2, d3
792 type(type_t),
intent(in) :: func_type
800 mixfield%func_type = func_type
802 mixfield%mix_spin_density_matrix = smix%mix_spin_density_matrix
803 mixfield%last_residue = m_zero
805 if (smix%scheme /= option__mixingscheme__linear)
then
806 if (mixfield%func_type == type_float)
then
807 safe_allocate( mixfield%ddf(1:d1, 1:d2, 1:d3))
808 safe_allocate( mixfield%ddv(1:d1, 1:d2, 1:d3))
809 safe_allocate(mixfield%dvin_old(1:d1, 1:d2))
810 safe_allocate( mixfield%df_old(1:d1, 1:d2))
812 safe_allocate( mixfield%zdf(1:d1, 1:d2, 1:d3))
813 safe_allocate( mixfield%zdv(1:d1, 1:d2, 1:d3))
814 safe_allocate(mixfield%zvin_old(1:d1, 1:d2))
815 safe_allocate( mixfield%zf_old(1:d1, 1:d2))
819 if (mixfield%func_type == type_float)
then
820 safe_allocate(mixfield%dvin(1:d1, 1:d2))
821 safe_allocate(mixfield%dvout(1:d1, 1:d2))
822 safe_allocate(mixfield%dvnew(1:d1, 1:d2))
823 safe_allocate(mixfield%dresidual(1:d1, 1:d2))
825 safe_allocate(mixfield%zvin(1:d1, 1:d2))
826 safe_allocate(mixfield%zvout(1:d1, 1:d2))
827 safe_allocate(mixfield%zvnew(1:d1, 1:d2))
828 safe_allocate(mixfield%zresidual(1:d1, 1:d2))
836 type(
mix_t),
intent(inout) :: smix
842 if (smix%scheme /= option__mixingscheme__linear)
then
843 if (mixfield%func_type == type_float)
then
844 safe_deallocate_a(mixfield%ddf)
845 safe_deallocate_a(mixfield%ddv)
846 safe_deallocate_a(mixfield%dvin_old)
847 safe_deallocate_a(mixfield%df_old)
849 safe_deallocate_a(mixfield%zdf)
850 safe_deallocate_a(mixfield%zdv)
851 safe_deallocate_a(mixfield%zvin_old)
852 safe_deallocate_a(mixfield%zf_old)
856 if (mixfield%func_type == type_float)
then
857 safe_deallocate_a(mixfield%dvin)
858 safe_deallocate_a(mixfield%dvout)
859 safe_deallocate_a(mixfield%dvnew)
860 safe_deallocate_a(mixfield%dresidual)
862 safe_deallocate_a(mixfield%zvin)
863 safe_deallocate_a(mixfield%zvout)
864 safe_deallocate_a(mixfield%zvnew)
865 safe_deallocate_a(mixfield%zresidual)
873 integer,
intent(in) :: scheme
875 integer :: d1, d2, d3
883 if (scheme /= option__mixingscheme__linear)
then
884 if (mixfield%func_type == type_float)
then
885 assert(
allocated(mixfield%ddf))
886 mixfield%ddf(1:d1, 1:d2, 1:d3) = m_zero
887 mixfield%ddv(1:d1, 1:d2, 1:d3) = m_zero
888 mixfield%dvin_old(1:d1, 1:d2) = m_zero
889 mixfield%df_old(1:d1, 1:d2) = m_zero
891 assert(
allocated(mixfield%zdf))
892 mixfield%zdf(1:d1, 1:d2, 1:d3) = m_z0
893 mixfield%zdv(1:d1, 1:d2, 1:d3) = m_z0
894 mixfield%zvin_old(1:d1, 1:d2) = m_z0
895 mixfield%zf_old(1:d1, 1:d2) = m_z0
899 if (mixfield%func_type == type_float)
then
900 mixfield%dvin(1:d1, 1:d2) = m_zero
901 mixfield%dvout(1:d1, 1:d2) = m_zero
902 mixfield%dvnew(1:d1, 1:d2) = m_zero
903 mixfield%dresidual(1:d1, 1:d2) = m_zero
905 mixfield%zvin(1:d1, 1:d2) = m_z0
906 mixfield%zvout(1:d1, 1:d2) = m_z0
907 mixfield%zvnew(1:d1, 1:d2) = m_z0
908 mixfield%zresidual(1:d1, 1:d2) = m_z0
923 class(
mix_t),
intent(inout) :: this
931 do i = 1, this%nauxmixfield
932 aux_field => this%auxmixfield(i)%p
933 dims = [aux_field%d1, aux_field%d2]
936 if (aux_field%func_type == type_float)
then
937 call dcompute_residual(this, dims, aux_field%dvin, aux_field%dvout, aux_field%dresidual, precondition=.false.)
939 call zcompute_residual(this, dims, aux_field%zvin, aux_field%zvout, aux_field%zresidual, precondition=.false.)
961 type(
mix_t),
intent(inout) :: smix
968 call smix%compute_residuals_aux_field()
970 do i = 1, smix%nauxmixfield
971 field => smix%auxmixfield(i)%p
973 if (field%func_type == type_float)
then
974 call dmixing_linear(field%d1, field%d2, smix%coeff, field%dvin, field%dresidual, field%dvnew)
976 call zmixing_linear(field%d1, field%d2, smix%coeff, field%zvin, field%zresidual, field%zvnew)
989#include "mix_inc.F90"
992#include "complex.F90"
994#include "mix_inc.F90"
subroutine init_preconditioner()
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)
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 messages_info(no_lines, iunit, debug_only, stress, all_nodes, 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 zmixfield_get_vnew(mixfield, vnew)
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 zcompute_residual(smix, dims, vin, vout, residual, precondition)
Compute the residual of the potential (or density) for SCF mixing.
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, mesh, ierr)
subroutine, public mixfield_clear(scheme, mixfield)
Zero all potential and field attributes of a mixfield instance.
subroutine dcompute_residual(smix, dims, vin, vout, residual, precondition)
Compute the residual of the potential (or density) for SCF mixing.
subroutine, public mix_init(smix, namespace, space, der, d1, d2, def_, func_type_, prefix_)
Initialise mix_t instance.
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, public mix_load(namespace, restart, smix, mesh, ierr)
subroutine dmixfield_set_vout(mixfield, vout)
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, symm)
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)
Creates the nonlocal operators for the stencils used for finite differences.
subroutine, public nl_operator_allocate_gpu_buffers(op)
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), parameter, public type_float
class representing derivatives
Describes mesh distribution to nodes.
Quantities used in mixing: Input, output and new potentials, and the residuals.