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 real(real64) :: residual_coeff
131 integer,
public :: ns
132 integer,
public :: ns_restart
139 type(mixfield_t) :: mixfield
140 integer :: nauxmixfield
141 type(mixfield_ptr_t) :: auxmixfield(MAX_AUXMIXFIELD)
147 real(real64) :: kerker_factor
148 logical :: precondition
149 type(nl_operator_t) :: preconditioner
152 logical :: mix_spin_density_matrix
154 procedure :: compute_residuals_aux_field
173 subroutine mix_init(smix, namespace, space, der, d1, d2, def_, func_type_, prefix_)
174 type(mix_t),
intent(out) :: smix
178 integer,
intent(in) :: d1
179 integer,
intent(in) :: d2
180 integer,
optional,
intent(in) :: def_
181 type(
type_t),
optional,
intent(in) :: func_type_
182 character(len=*),
optional,
intent(in) :: prefix_
185 character(len=32) :: prefix
187 real(real64) :: coeff
193 def = option__mixingscheme__broyden
194 if (
present(def_)) def = def_
195 if (
present(func_type_))
then
196 func_type = func_type_
201 if (
present(prefix_)) prefix = prefix_
250 call parse_variable(namespace, trim(prefix)+
'MixingPreconditioner', .false., smix%precondition)
251 if (der%dim /= 3) smix%precondition = .false.
263 call parse_variable(namespace, trim(prefix)+
'Mixing', 0.3_real64, coeff)
267 safe_allocate(smix%coeff(1:d2))
269 smix%adaptive_damping =
m_one
282 call parse_variable(namespace, trim(prefix)+
'MixingSpinDensityMatrix', .false., smix%mix_spin_density_matrix)
292 call parse_variable(namespace, trim(prefix)+
'MixingMagnetization', 1.5_real64, coeff)
294 if (.not. smix%mix_spin_density_matrix) smix%coeff(2:d2) = coeff
296 smix%mix_spin_density_matrix = .
true.
307 call parse_variable(namespace, trim(prefix)+
'MixingResidual', 0.05_real64, smix%residual_coeff)
308 if (smix%residual_coeff <=
m_zero .or. smix%residual_coeff >
m_one)
then
309 call messages_input_error(namespace,
'MixingResidual',
'Value should be positive and smaller than one.')
321 if (smix%scheme /= option__mixingscheme__linear)
then
322 call parse_variable(namespace, trim(prefix)//
'MixNumberSteps', 4, smix%ns)
337 if (smix%scheme /= option__mixingscheme__linear)
then
338 call parse_variable(namespace, trim(prefix)//
'MixingRestart', 20, smix%ns_restart)
344 write(
message(1),
'(A,I4,A,I4,A)')
"Info: Mixing uses ", smix%ns,
" steps and restarts after ", &
345 smix%ns_restart,
" steps."
358 call parse_variable(namespace, trim(prefix)//
'MixInterval', 1, smix%interval)
359 if (smix%interval < 1)
call messages_input_error(namespace,
'MixInterval',
'MixInterval must be larger or equal than 1')
374 call parse_variable(namespace, trim(prefix)+
'MixingKerker', .false., smix%kerker)
387 call parse_variable(namespace, trim(prefix)+
'MixingKerkerFactor', 1._real64, smix%kerker_factor)
389 smix%nauxmixfield = 0
390 do ii = 1,max_auxmixfield
391 nullify(smix%auxmixfield(ii)%p)
394 call mixfield_init(smix, smix%mixfield, d1, d2, smix%ns, func_type)
404 integer :: ns, maxp, ip, is
405 real(real64),
parameter :: weight = 50.0_real64
412 assert(.not. der%mesh%use_curvilinear)
417 call nl_operator_build(space, der%mesh, smix%preconditioner, der%mesh%np, const_w = .not. der%mesh%use_curvilinear)
419 ns = smix%preconditioner%stencil%size
421 if (smix%preconditioner%const_w)
then
430 select case (sum(abs(smix%preconditioner%stencil%points(1:der%dim, is))))
432 smix%preconditioner%w(is, ip) =
m_one + weight/8.0_real64
434 smix%preconditioner%w(is, ip) = weight/16.0_real64
436 smix%preconditioner%w(is, ip) = weight/32.0_real64
438 smix%preconditioner%w(is, ip) = weight/64.0_real64
457 type(
mix_t),
intent(inout) :: smix
465 smix%adaptive_damping =
m_one
473 type(
mix_t),
intent(inout) :: smix
483 smix%nauxmixfield = 0
484 do ii = 1,max_auxmixfield
485 nullify(smix%auxmixfield(ii)%p)
488 safe_deallocate_a(smix%coeff)
495 subroutine mix_dump(namespace, restart, smix, mesh, ierr)
498 type(
mix_t),
intent(in) :: smix
499 class(
mesh_t),
intent(in) :: mesh
500 integer,
intent(out) :: ierr
502 integer :: iunit, id2, id3, err, err2(4)
503 character(len=40) :: lines(7)
504 character(len=80) :: filename
510 if (restart%skip())
then
515 message(1) =
"Debug: Writing mixing restart."
519 assert(mesh%np == smix%mixfield%d1)
522 iunit = restart%open(
'mixing')
523 if(restart%do_i_write())
then
524 write(lines(1),
'(a11,i1)')
'scheme= ', smix%scheme
526 write(lines(2),
'(a11,i10)')
'd1= ', mesh%np_global
527 write(lines(3),
'(a11,i10)')
'd2= ', smix%mixfield%d2
528 write(lines(4),
'(a11,i10)')
'd3= ', smix%mixfield%d3
529 write(lines(5),
'(a11,i10)')
'iter= ', smix%iter
530 write(lines(6),
'(a11,i10)')
'ns= ', smix%ns
531 write(lines(7),
'(a11,i10)')
'last_ipos= ', smix%last_ipos
532 call restart%write(iunit, lines, 7, err)
535 call restart%close(iunit)
540 if (smix%scheme /= option__mixingscheme__linear)
then
541 do id2 = 1, smix%mixfield%d2
542 do id3 = 1, smix%mixfield%d3
544 write(filename,
'(a3,i2.2,i2.2)')
'df_', id2, id3
545 if (smix%mixfield%func_type ==
type_float)
then
546 call restart%write_mesh_function(filename, mesh, smix%mixfield%ddf(1:mesh%np, id2, id3), err)
548 call restart%write_mesh_function(filename, mesh, smix%mixfield%zdf(1:mesh%np, id2, id3), err)
550 err2(1) = err2(1) + err
552 write(filename,
'(a3,i2.2,i2.2)')
'dv_', id2, id3
553 if (smix%mixfield%func_type ==
type_float)
then
554 call restart%write_mesh_function(filename, mesh, smix%mixfield%ddv(1:mesh%np, id2, id3), err)
556 call restart%write_mesh_function(filename, mesh, smix%mixfield%zdv(1:mesh%np, id2, id3), err)
558 err2(2) = err2(2) + err
562 write(filename,
'(a6,i2.2)')
'f_old_', id2
563 if (smix%mixfield%func_type ==
type_float)
then
564 call restart%write_mesh_function(filename, mesh, smix%mixfield%df_old(1:mesh%np, id2), err)
566 call restart%write_mesh_function(filename, mesh, smix%mixfield%zf_old(1:mesh%np, id2), err)
568 err2(3) = err2(3) + err
570 write(filename,
'(a8,i2.2)')
'vin_old_', id2
571 if (smix%mixfield%func_type ==
type_float)
then
572 call restart%write_mesh_function(filename, mesh, smix%mixfield%dvin_old(1:mesh%np, id2), err)
574 call restart%write_mesh_function(filename, mesh, smix%mixfield%zvin_old(1:mesh%np, id2), err)
576 err2(4) = err2(4) + err
580 if (err2(1) /= 0) ierr = ierr + 2
581 if (err2(2) /= 0) ierr = ierr + 4
582 if (err2(3) /= 0) ierr = ierr + 8
583 if (err2(4) /= 0) ierr = ierr + 16
586 message(1) =
"Debug: Writing mixing restart done."
594 subroutine mix_load(namespace, restart, smix, mesh, ierr)
597 type(
mix_t),
intent(inout) :: smix
598 class(
mesh_t),
intent(in) :: mesh
599 integer,
intent(out) :: ierr
601 integer :: iunit, err, err2(4)
602 integer :: scheme, d1, d2, d3, ns
604 character(len=11) :: str
605 character(len=80) :: filename
606 character(len=256) :: lines(7)
612 if (restart%skip())
then
618 message(1) =
"Debug: Reading mixing restart."
622 iunit = restart%open(
'mixing')
623 call restart%read(iunit, lines, 7, err)
627 read(lines(1), *) str, scheme
628 read(lines(2), *) str, d1
629 read(lines(3), *) str, d2
630 read(lines(4), *) str, d3
631 read(lines(5), *) str, smix%iter
632 read(lines(6), *) str, ns
633 read(lines(7), *) str, smix%last_ipos
635 call restart%close(iunit)
640 if (scheme /= smix%scheme .or. ns /= smix%ns)
then
641 message(1) =
"The mixing scheme from the restart data is not the same as the one used in the current calculation."
647 if (mesh%np_global /= d1 .or. mesh%np /= smix%mixfield%d1 .or. d2 /= smix%mixfield%d2)
then
648 message(1) =
"The dimensions of the arrays from the mixing restart data"
649 message(2) =
"are not the same as the ones used in this calculation."
659 if (smix%scheme /= option__mixingscheme__linear)
then
661 do id2 = 1, smix%mixfield%d2
662 do id3 = 1, smix%mixfield%d3
664 write(filename,
'(a3,i2.2,i2.2)')
'df_', id2, id3
665 if (smix%mixfield%func_type ==
type_float)
then
666 call restart%read_mesh_function(filename, mesh, smix%mixfield%ddf(1:mesh%np, id2, id3), err)
668 call restart%read_mesh_function(filename, mesh, smix%mixfield%zdf(1:mesh%np, id2, id3), err)
670 if (err /= 0) err2(1) = err2(1) + 1
672 write(filename,
'(a3,i2.2,i2.2)')
'dv_', id2, id3
673 if (smix%mixfield%func_type ==
type_float)
then
674 call restart%read_mesh_function(filename, mesh, smix%mixfield%ddv(1:mesh%np, id2, id3), err)
676 call restart%read_mesh_function(filename, mesh, smix%mixfield%zdv(1:mesh%np, id2, id3), err)
678 if (err /= 0) err2(2) = err2(2) + 1
682 write(filename,
'(a6,i2.2)')
'f_old_', id2
683 if (smix%mixfield%func_type ==
type_float)
then
684 call restart%read_mesh_function(filename, mesh, smix%mixfield%df_old(1:mesh%np, id2), err)
686 call restart%read_mesh_function(filename, mesh, smix%mixfield%zf_old(1:mesh%np, id2), err)
688 if (err /= 0) err2(3) = err2(3) + 1
690 write(filename,
'(a8,i2.2)')
'vin_old_', id2
691 if (smix%mixfield%func_type ==
type_float)
then
692 call restart%read_mesh_function(filename, mesh, smix%mixfield%dvin_old(1:mesh%np, id2), err)
694 call restart%read_mesh_function(filename, mesh, smix%mixfield%zvin_old(1:mesh%np, id2), err)
696 if (err /= 0) err2(4) = err2(4) + 1
700 if (err2(1) /= 0) ierr = ierr + 8
701 if (err2(2) /= 0) ierr = ierr + 16
702 if (err2(3) /= 0) ierr = ierr + 32
703 if (err2(4) /= 0) ierr = ierr + 64
712 if (ierr == 0 .and. smix%scheme == option__mixingscheme__broyden_adaptive)
then
713 smix%adaptive_damping =
m_one
714 smix%mixfield%last_residue =
m_zero
718 message(1) =
"Debug: Reading mixing restart done."
725 type(
mix_t),
intent(in) :: this
727 coefficient = this%coeff(1)
730 integer pure function
mix_scheme(this) result(scheme)
731 type(
mix_t),
intent(in) :: this
736 integer pure function
mix_d3(this)
737 type(
mix_t),
intent(in) :: this
743 type(
mix_t),
target,
intent(in) :: this
744 type(
mixfield_t),
pointer,
intent(out) :: mixfield
746 mixfield => this%mixfield
750 subroutine mixing(namespace, smix)
751 type(namespace_t),
intent(in) :: namespace
752 type(
mix_t),
intent(inout) :: smix
756 if (smix%mixfield%func_type == type_float)
then
757 call dmixing(namespace, smix, smix%mixfield%dvin, smix%mixfield%dvout, smix%mixfield%dvnew)
759 call zmixing(namespace, smix, smix%mixfield%zvin, smix%mixfield%zvout, smix%mixfield%zvnew)
766 type(namespace_t),
intent(in) :: namespace
767 type(
mix_t),
intent(inout) :: smix
768 type(
mixfield_t),
target,
intent(in) :: mixfield
772 smix%nauxmixfield = smix%nauxmixfield + 1
773 smix%auxmixfield(smix%nauxmixfield)%p => mixfield
775 if (smix%scheme == option__mixingscheme__diis)
then
776 message(1) =
'Mixing scheme DIIS is not implemented for auxiliary mixing fields'
777 call messages_fatal(1, namespace=namespace)
784 subroutine mixfield_init(smix, mixfield, d1, d2, d3, func_type)
785 type(
mix_t),
intent(in) :: smix
787 integer,
intent(in) :: d1, d2, d3
788 type(type_t),
intent(in) :: func_type
796 mixfield%func_type = func_type
798 mixfield%mix_spin_density_matrix = smix%mix_spin_density_matrix
799 mixfield%last_residue = m_zero
801 if (smix%scheme /= option__mixingscheme__linear)
then
802 if (mixfield%func_type == type_float)
then
803 safe_allocate( mixfield%ddf(1:d1, 1:d2, 1:d3))
804 safe_allocate( mixfield%ddv(1:d1, 1:d2, 1:d3))
805 safe_allocate(mixfield%dvin_old(1:d1, 1:d2))
806 safe_allocate( mixfield%df_old(1:d1, 1:d2))
808 safe_allocate( mixfield%zdf(1:d1, 1:d2, 1:d3))
809 safe_allocate( mixfield%zdv(1:d1, 1:d2, 1:d3))
810 safe_allocate(mixfield%zvin_old(1:d1, 1:d2))
811 safe_allocate( mixfield%zf_old(1:d1, 1:d2))
815 if (mixfield%func_type == type_float)
then
816 safe_allocate(mixfield%dvin(1:d1, 1:d2))
817 safe_allocate(mixfield%dvout(1:d1, 1:d2))
818 safe_allocate(mixfield%dvnew(1:d1, 1:d2))
819 safe_allocate(mixfield%dresidual(1:d1, 1:d2))
821 safe_allocate(mixfield%zvin(1:d1, 1:d2))
822 safe_allocate(mixfield%zvout(1:d1, 1:d2))
823 safe_allocate(mixfield%zvnew(1:d1, 1:d2))
824 safe_allocate(mixfield%zresidual(1:d1, 1:d2))
832 type(
mix_t),
intent(inout) :: smix
838 if (smix%scheme /= option__mixingscheme__linear)
then
839 if (mixfield%func_type == type_float)
then
840 safe_deallocate_a(mixfield%ddf)
841 safe_deallocate_a(mixfield%ddv)
842 safe_deallocate_a(mixfield%dvin_old)
843 safe_deallocate_a(mixfield%df_old)
845 safe_deallocate_a(mixfield%zdf)
846 safe_deallocate_a(mixfield%zdv)
847 safe_deallocate_a(mixfield%zvin_old)
848 safe_deallocate_a(mixfield%zf_old)
852 if (mixfield%func_type == type_float)
then
853 safe_deallocate_a(mixfield%dvin)
854 safe_deallocate_a(mixfield%dvout)
855 safe_deallocate_a(mixfield%dvnew)
856 safe_deallocate_a(mixfield%dresidual)
858 safe_deallocate_a(mixfield%zvin)
859 safe_deallocate_a(mixfield%zvout)
860 safe_deallocate_a(mixfield%zvnew)
861 safe_deallocate_a(mixfield%zresidual)
869 integer,
intent(in) :: scheme
871 integer :: d1, d2, d3
879 if (scheme /= option__mixingscheme__linear)
then
880 if (mixfield%func_type == type_float)
then
881 assert(
allocated(mixfield%ddf))
882 mixfield%ddf(1:d1, 1:d2, 1:d3) = m_zero
883 mixfield%ddv(1:d1, 1:d2, 1:d3) = m_zero
884 mixfield%dvin_old(1:d1, 1:d2) = m_zero
885 mixfield%df_old(1:d1, 1:d2) = m_zero
887 assert(
allocated(mixfield%zdf))
888 mixfield%zdf(1:d1, 1:d2, 1:d3) = m_z0
889 mixfield%zdv(1:d1, 1:d2, 1:d3) = m_z0
890 mixfield%zvin_old(1:d1, 1:d2) = m_z0
891 mixfield%zf_old(1:d1, 1:d2) = m_z0
895 if (mixfield%func_type == type_float)
then
896 mixfield%dvin(1:d1, 1:d2) = m_zero
897 mixfield%dvout(1:d1, 1:d2) = m_zero
898 mixfield%dvnew(1:d1, 1:d2) = m_zero
899 mixfield%dresidual(1:d1, 1:d2) = m_zero
901 mixfield%zvin(1:d1, 1:d2) = m_z0
902 mixfield%zvout(1:d1, 1:d2) = m_z0
903 mixfield%zvnew(1:d1, 1:d2) = m_z0
904 mixfield%zresidual(1:d1, 1:d2) = m_z0
919 class(
mix_t),
intent(inout) :: this
927 do i = 1, this%nauxmixfield
928 aux_field => this%auxmixfield(i)%p
929 dims = [aux_field%d1, aux_field%d2]
931 if (aux_field%func_type == type_float)
then
932 call dcompute_residual(this, dims, aux_field%dvin, aux_field%dvout, aux_field%dresidual)
934 call zcompute_residual(this, dims, aux_field%zvin, aux_field%zvout, aux_field%zresidual)
956 type(
mix_t),
intent(inout) :: smix
963 call smix%compute_residuals_aux_field()
965 do i = 1, smix%nauxmixfield
966 field => smix%auxmixfield(i)%p
968 if (field%func_type == type_float)
then
969 call dmixing_linear(field%d1, field%d2, smix%coeff, field%dvin, field%dresidual, field%dvnew)
971 call zmixing_linear(field%d1, field%d2, smix%coeff, field%zvin, field%zresidual, field%zvnew)
984#include "mix_inc.F90"
987#include "complex.F90"
989#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 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, mesh, ierr)
subroutine, public mixfield_clear(scheme, mixfield)
Zero all potential and field attributes of a mixfield instance.
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 zcompute_residual(smix, dims, vin, vout, residual)
Compute the residual of the potential (or density) for SCF mixing.
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.