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
104 logical :: mix_spin_density_matrix
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) :: residual_coeff
130 integer,
public :: ns
131 integer,
public :: ns_restart
138 type(mixfield_t) :: mixfield
139 integer :: nauxmixfield
140 type(mixfield_ptr_t) :: auxmixfield(MAX_AUXMIXFIELD)
146 real(real64) :: kerker_factor
147 logical :: precondition
148 type(nl_operator_t) :: preconditioner
151 logical :: mix_spin_density_matrix
153 procedure :: compute_residuals_aux_field
172 subroutine mix_init(smix, namespace, space, der, d1, d2, def_, func_type_, prefix_)
173 type(mix_t),
intent(out) :: smix
174 type(namespace_t),
intent(in) :: namespace
175 class(space_t),
intent(in) :: space
177 integer,
intent(in) :: d1
178 integer,
intent(in) :: d2
179 integer,
optional,
intent(in) :: def_
180 type(
type_t),
optional,
intent(in) :: func_type_
181 character(len=*),
optional,
intent(in) :: prefix_
184 character(len=32) :: prefix
186 real(real64) :: coeff
192 def = option__mixingscheme__broyden
193 if (
present(def_)) def = def_
194 if (
present(func_type_))
then
195 func_type = func_type_
200 if (
present(prefix_)) prefix = prefix_
241 call parse_variable(namespace, trim(prefix)+
'MixingPreconditioner', .false., smix%precondition)
242 if (der%dim /= 3) smix%precondition = .false.
253 call parse_variable(namespace, trim(prefix)+
'Mixing', 0.3_real64, coeff)
257 safe_allocate(smix%coeff(1:d2))
271 call parse_variable(namespace, trim(prefix)+
'MixingSpinDensityMatrix', .false., smix%mix_spin_density_matrix)
281 call parse_variable(namespace, trim(prefix)+
'MixingMagnetization', 1.5_real64, coeff)
283 if (.not. smix%mix_spin_density_matrix) smix%coeff(2:d2) = coeff
285 smix%mix_spin_density_matrix = .
true.
296 call parse_variable(namespace, trim(prefix)+
'MixingResidual', 0.05_real64, smix%residual_coeff)
297 if (smix%residual_coeff <=
m_zero .or. smix%residual_coeff >
m_one)
then
298 call messages_input_error(namespace,
'MixingResidual',
'Value should be positive and smaller than one.')
310 if (smix%scheme /= option__mixingscheme__linear)
then
311 call parse_variable(namespace, trim(prefix)//
'MixNumberSteps', 4, smix%ns)
326 if (smix%scheme /= option__mixingscheme__linear)
then
327 call parse_variable(namespace, trim(prefix)//
'MixingRestart', 20, smix%ns_restart)
333 write(
message(1),
'(A,I4,A,I4,A)')
"Info: Mixing uses ", smix%ns,
" steps and restarts after ", &
334 smix%ns_restart,
" steps."
347 call parse_variable(namespace, trim(prefix)//
'MixInterval', 1, smix%interval)
348 if (smix%interval < 1)
call messages_input_error(namespace,
'MixInterval',
'MixInterval must be larger or equal than 1')
363 call parse_variable(namespace, trim(prefix)+
'MixingKerker', .false., smix%kerker)
376 call parse_variable(namespace, trim(prefix)+
'MixingKerkerFactor', 1._real64, smix%kerker_factor)
378 smix%nauxmixfield = 0
379 do ii = 1,max_auxmixfield
380 nullify(smix%auxmixfield(ii)%p)
383 call mixfield_init(smix, smix%mixfield, d1, d2, smix%ns, func_type)
393 integer :: ns, maxp, ip, is
394 real(real64),
parameter :: weight = 50.0_real64
401 assert(.not. der%mesh%use_curvilinear)
406 call nl_operator_build(space, der%mesh, smix%preconditioner, der%mesh%np, const_w = .not. der%mesh%use_curvilinear)
408 ns = smix%preconditioner%stencil%size
410 if (smix%preconditioner%const_w)
then
419 select case (sum(abs(smix%preconditioner%stencil%points(1:der%dim, is))))
421 smix%preconditioner%w(is, ip) =
m_one + weight/8.0_real64
423 smix%preconditioner%w(is, ip) = weight/16.0_real64
425 smix%preconditioner%w(is, ip) = weight/32.0_real64
427 smix%preconditioner%w(is, ip) = weight/64.0_real64
446 type(
mix_t),
intent(inout) :: smix
461 type(
mix_t),
intent(inout) :: smix
471 smix%nauxmixfield = 0
472 do ii = 1,max_auxmixfield
473 nullify(smix%auxmixfield(ii)%p)
476 safe_deallocate_a(smix%coeff)
483 subroutine mix_dump(namespace, restart, smix, space, mesh, ierr)
487 class(
space_t),
intent(in) :: space
488 class(
mesh_t),
intent(in) :: mesh
489 integer,
intent(out) :: ierr
491 integer :: iunit, id2, id3, err, err2(4)
492 character(len=40) :: lines(7)
493 character(len=80) :: filename
499 if (restart%skip())
then
504 message(1) =
"Debug: Writing mixing restart."
508 assert(mesh%np == smix%mixfield%d1)
511 iunit = restart%open(
'mixing')
512 if(restart%do_i_write())
then
513 write(lines(1),
'(a11,i1)')
'scheme= ', smix%scheme
515 write(lines(2),
'(a11,i10)')
'd1= ', mesh%np_global
516 write(lines(3),
'(a11,i10)')
'd2= ', smix%mixfield%d2
517 write(lines(4),
'(a11,i10)')
'd3= ', smix%mixfield%d3
518 write(lines(5),
'(a11,i10)')
'iter= ', smix%iter
519 write(lines(6),
'(a11,i10)')
'ns= ', smix%ns
520 write(lines(7),
'(a11,i10)')
'last_ipos= ', smix%last_ipos
521 call restart%write(iunit, lines, 7, err)
524 call restart%close(iunit)
529 if (smix%scheme /= option__mixingscheme__linear)
then
530 do id2 = 1, smix%mixfield%d2
531 do id3 = 1, smix%mixfield%d3
533 write(filename,
'(a3,i2.2,i2.2)')
'df_', id2, id3
534 if (smix%mixfield%func_type ==
type_float)
then
535 call restart%write_mesh_function(space, filename, mesh, smix%mixfield%ddf(1:mesh%np, id2, id3), err)
537 call restart%write_mesh_function(space, filename, mesh, smix%mixfield%zdf(1:mesh%np, id2, id3), err)
539 err2(1) = err2(1) + err
541 write(filename,
'(a3,i2.2,i2.2)')
'dv_', id2, id3
542 if (smix%mixfield%func_type ==
type_float)
then
543 call restart%write_mesh_function(space, filename, mesh, smix%mixfield%ddv(1:mesh%np, id2, id3), err)
545 call restart%write_mesh_function(space, filename, mesh, smix%mixfield%zdv(1:mesh%np, id2, id3), err)
547 err2(2) = err2(2) + err
551 write(filename,
'(a6,i2.2)')
'f_old_', id2
552 if (smix%mixfield%func_type ==
type_float)
then
553 call restart%write_mesh_function(space, filename, mesh, smix%mixfield%df_old(1:mesh%np, id2), err)
555 call restart%write_mesh_function(space, filename, mesh, smix%mixfield%zf_old(1:mesh%np, id2), err)
557 err2(3) = err2(3) + err
559 write(filename,
'(a8,i2.2)')
'vin_old_', id2
560 if (smix%mixfield%func_type ==
type_float)
then
561 call restart%write_mesh_function(space, filename, mesh, smix%mixfield%dvin_old(1:mesh%np, id2), err)
563 call restart%write_mesh_function(space, filename, mesh, smix%mixfield%zvin_old(1:mesh%np, id2), err)
565 err2(4) = err2(4) + err
569 if (err2(1) /= 0) ierr = ierr + 2
570 if (err2(2) /= 0) ierr = ierr + 4
571 if (err2(3) /= 0) ierr = ierr + 8
572 if (err2(4) /= 0) ierr = ierr + 16
575 message(1) =
"Debug: Writing mixing restart done."
583 subroutine mix_load(namespace, restart, smix, space, mesh, ierr)
586 type(
mix_t),
intent(inout) :: smix
587 class(
space_t),
intent(in) :: space
588 class(
mesh_t),
intent(in) :: mesh
589 integer,
intent(out) :: ierr
591 integer :: iunit, err, err2(4)
592 integer :: scheme, d1, d2, d3, ns
594 character(len=11) :: str
595 character(len=80) :: filename
596 character(len=256) :: lines(7)
602 if (restart%skip())
then
608 message(1) =
"Debug: Reading mixing restart."
612 iunit = restart%open(
'mixing')
613 call restart%read(iunit, lines, 7, err)
617 read(lines(1), *) str, scheme
618 read(lines(2), *) str, d1
619 read(lines(3), *) str, d2
620 read(lines(4), *) str, d3
621 read(lines(5), *) str, smix%iter
622 read(lines(6), *) str, ns
623 read(lines(7), *) str, smix%last_ipos
625 call restart%close(iunit)
630 if (scheme /= smix%scheme .or. ns /= smix%ns)
then
631 message(1) =
"The mixing scheme from the restart data is not the same as the one used in the current calculation."
637 if (mesh%np_global /= d1 .or. mesh%np /= smix%mixfield%d1 .or. d2 /= smix%mixfield%d2)
then
638 message(1) =
"The dimensions of the arrays from the mixing restart data"
639 message(2) =
"are not the same as the ones used in this calculation."
649 if (smix%scheme /= option__mixingscheme__linear)
then
651 do id2 = 1, smix%mixfield%d2
652 do id3 = 1, smix%mixfield%d3
654 write(filename,
'(a3,i2.2,i2.2)')
'df_', id2, id3
655 if (smix%mixfield%func_type ==
type_float)
then
656 call restart%read_mesh_function(space, filename, mesh, smix%mixfield%ddf(1:mesh%np, id2, id3), err)
658 call restart%read_mesh_function(space, filename, mesh, smix%mixfield%zdf(1:mesh%np, id2, id3), err)
660 if (err /= 0) err2(1) = err2(1) + 1
662 write(filename,
'(a3,i2.2,i2.2)')
'dv_', id2, id3
663 if (smix%mixfield%func_type ==
type_float)
then
664 call restart%read_mesh_function(space, filename, mesh, smix%mixfield%ddv(1:mesh%np, id2, id3), err)
666 call restart%read_mesh_function(space, filename, mesh, smix%mixfield%zdv(1:mesh%np, id2, id3), err)
668 if (err /= 0) err2(2) = err2(2) + 1
672 write(filename,
'(a6,i2.2)')
'f_old_', id2
673 if (smix%mixfield%func_type ==
type_float)
then
674 call restart%read_mesh_function(space, filename, mesh, smix%mixfield%df_old(1:mesh%np, id2), err)
676 call restart%read_mesh_function(space, filename, mesh, smix%mixfield%zf_old(1:mesh%np, id2), err)
678 if (err /= 0) err2(3) = err2(3) + 1
680 write(filename,
'(a8,i2.2)')
'vin_old_', id2
681 if (smix%mixfield%func_type ==
type_float)
then
682 call restart%read_mesh_function(space, filename, mesh, smix%mixfield%dvin_old(1:mesh%np, id2), err)
684 call restart%read_mesh_function(space, filename, mesh, smix%mixfield%zvin_old(1:mesh%np, id2), err)
686 if (err /= 0) err2(4) = err2(4) + 1
690 if (err2(1) /= 0) ierr = ierr + 8
691 if (err2(2) /= 0) ierr = ierr + 16
692 if (err2(3) /= 0) ierr = ierr + 32
693 if (err2(4) /= 0) ierr = ierr + 64
702 message(1) =
"Debug: Reading mixing restart done."
709 type(
mix_t),
intent(in) :: this
711 coefficient = this%coeff(1)
714 integer pure function
mix_scheme(this) result(scheme)
715 type(
mix_t),
intent(in) :: this
720 integer pure function
mix_d3(this)
721 type(
mix_t),
intent(in) :: this
727 type(
mix_t),
target,
intent(in) :: this
728 type(
mixfield_t),
pointer,
intent(out) :: mixfield
730 mixfield => this%mixfield
734 subroutine mixing(namespace, smix)
735 type(namespace_t),
intent(in) :: namespace
736 type(
mix_t),
intent(inout) :: smix
740 if (smix%mixfield%func_type == type_float)
then
741 call dmixing(namespace, smix, smix%mixfield%dvin, smix%mixfield%dvout, smix%mixfield%dvnew)
743 call zmixing(namespace, smix, smix%mixfield%zvin, smix%mixfield%zvout, smix%mixfield%zvnew)
750 type(namespace_t),
intent(in) :: namespace
751 type(
mix_t),
intent(inout) :: smix
752 type(
mixfield_t),
target,
intent(in) :: mixfield
756 smix%nauxmixfield = smix%nauxmixfield + 1
757 smix%auxmixfield(smix%nauxmixfield)%p => mixfield
759 if (smix%scheme == option__mixingscheme__diis)
then
760 message(1) =
'Mixing scheme DIIS is not implemented for auxiliary mixing fields'
761 call messages_fatal(1, namespace=namespace)
768 subroutine mixfield_init(smix, mixfield, d1, d2, d3, func_type)
769 type(
mix_t),
intent(in) :: smix
771 integer,
intent(in) :: d1, d2, d3
772 type(type_t),
intent(in) :: func_type
780 mixfield%func_type = func_type
782 mixfield%mix_spin_density_matrix = smix%mix_spin_density_matrix
784 if (smix%scheme /= option__mixingscheme__linear)
then
785 if (mixfield%func_type == type_float)
then
786 safe_allocate( mixfield%ddf(1:d1, 1:d2, 1:d3))
787 safe_allocate( mixfield%ddv(1:d1, 1:d2, 1:d3))
788 safe_allocate(mixfield%dvin_old(1:d1, 1:d2))
789 safe_allocate( mixfield%df_old(1:d1, 1:d2))
791 safe_allocate( mixfield%zdf(1:d1, 1:d2, 1:d3))
792 safe_allocate( mixfield%zdv(1:d1, 1:d2, 1:d3))
793 safe_allocate(mixfield%zvin_old(1:d1, 1:d2))
794 safe_allocate( mixfield%zf_old(1:d1, 1:d2))
798 if (mixfield%func_type == type_float)
then
799 safe_allocate(mixfield%dvin(1:d1, 1:d2))
800 safe_allocate(mixfield%dvout(1:d1, 1:d2))
801 safe_allocate(mixfield%dvnew(1:d1, 1:d2))
802 safe_allocate(mixfield%dresidual(1:d1, 1:d2))
804 safe_allocate(mixfield%zvin(1:d1, 1:d2))
805 safe_allocate(mixfield%zvout(1:d1, 1:d2))
806 safe_allocate(mixfield%zvnew(1:d1, 1:d2))
807 safe_allocate(mixfield%zresidual(1:d1, 1:d2))
821 if (smix%scheme /= option__mixingscheme__linear)
then
822 if (mixfield%func_type == type_float)
then
823 safe_deallocate_a(mixfield%ddf)
824 safe_deallocate_a(mixfield%ddv)
825 safe_deallocate_a(mixfield%dvin_old)
826 safe_deallocate_a(mixfield%df_old)
828 safe_deallocate_a(mixfield%zdf)
829 safe_deallocate_a(mixfield%zdv)
830 safe_deallocate_a(mixfield%zvin_old)
831 safe_deallocate_a(mixfield%zf_old)
835 if (mixfield%func_type == type_float)
then
836 safe_deallocate_a(mixfield%dvin)
837 safe_deallocate_a(mixfield%dvout)
838 safe_deallocate_a(mixfield%dvnew)
839 safe_deallocate_a(mixfield%dresidual)
841 safe_deallocate_a(mixfield%zvin)
842 safe_deallocate_a(mixfield%zvout)
843 safe_deallocate_a(mixfield%zvnew)
844 safe_deallocate_a(mixfield%zresidual)
852 integer,
intent(in) :: scheme
854 integer :: d1, d2, d3
862 if (scheme /= option__mixingscheme__linear)
then
863 if (mixfield%func_type == type_float)
then
864 assert(
allocated(mixfield%ddf))
865 mixfield%ddf(1:d1, 1:d2, 1:d3) = m_zero
866 mixfield%ddv(1:d1, 1:d2, 1:d3) = m_zero
867 mixfield%dvin_old(1:d1, 1:d2) = m_zero
868 mixfield%df_old(1:d1, 1:d2) = m_zero
870 assert(
allocated(mixfield%zdf))
871 mixfield%zdf(1:d1, 1:d2, 1:d3) = m_z0
872 mixfield%zdv(1:d1, 1:d2, 1:d3) = m_z0
873 mixfield%zvin_old(1:d1, 1:d2) = m_z0
874 mixfield%zf_old(1:d1, 1:d2) = m_z0
878 if (mixfield%func_type == type_float)
then
879 mixfield%dvin(1:d1, 1:d2) = m_zero
880 mixfield%dvout(1:d1, 1:d2) = m_zero
881 mixfield%dvnew(1:d1, 1:d2) = m_zero
882 mixfield%dresidual(1:d1, 1:d2) = m_zero
884 mixfield%zvin(1:d1, 1:d2) = m_z0
885 mixfield%zvout(1:d1, 1:d2) = m_z0
886 mixfield%zvnew(1:d1, 1:d2) = m_z0
887 mixfield%zresidual(1:d1, 1:d2) = m_z0
902 class(
mix_t),
intent(inout) :: this
910 do i = 1, this%nauxmixfield
911 aux_field => this%auxmixfield(i)%p
912 dims = [aux_field%d1, aux_field%d2]
914 if (aux_field%func_type == type_float)
then
915 call dcompute_residual(this, dims, aux_field%dvin, aux_field%dvout, aux_field%dresidual)
917 call zcompute_residual(this, dims, aux_field%zvin, aux_field%zvout, aux_field%zresidual)
939 type(
mix_t),
intent(inout) :: smix
946 call smix%compute_residuals_aux_field()
948 do i = 1, smix%nauxmixfield
949 field => smix%auxmixfield(i)%p
951 if (field%func_type == type_float)
then
952 call dmixing_linear(field%d1, field%d2, smix%coeff, field%dvin, field%dresidual, field%dvnew)
954 call zmixing_linear(field%d1, field%d2, smix%coeff, field%zvin, field%zresidual, field%zvnew)
967#include "mix_inc.F90"
970#include "complex.F90"
972#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, 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 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, 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)
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.