28 use,
intrinsic :: iso_fortran_env
50 integer,
public,
parameter :: &
59 integer,
public :: level = constrain_none
60 real(real64) :: lambda =
m_zero
61 real(real64),
allocatable :: constrain(:,:)
62 real(real64),
allocatable,
public :: pot(:,:)
63 real(real64),
public :: energy
69 real(real64),
parameter :: tol_mag_norm = 1.0e-6_real64
76 type(magnetic_constrain_t),
intent(inout) :: this
77 type(namespace_t),
intent(in) :: namespace
78 class(mesh_t),
intent(in) :: mesh
79 type(states_elec_dim_t),
intent(in) :: std
80 integer,
intent(in) :: natoms
81 real(real64),
intent(in) :: min_dist
84 real(real64) :: rmin, norm
109 call parse_variable(namespace,
'MagneticConstrain', constrain_none, this%level)
111 if (this%level == constrain_none)
then
125 call parse_variable(namespace,
'MagneticConstrainStrength', 0.01_real64, this%lambda)
130 if (
parse_block(namespace,
'AtomsMagnetDirection', blk) < 0)
then
131 message(1) =
"AtomsMagnetDirection block is not defined."
132 message(2) =
"Magnetic constrained DFT cannot be used without it."
137 message(1) =
"AtomsMagnetDirection block has the wrong number of rows."
142 message(1) =
"Magnetic constrains can only be used for spin-polized and spinor calculations."
146 safe_allocate(this%constrain(1:3, natoms))
151 this%constrain(1:2, ia) =
m_zero
155 if (abs(this%constrain(idir, ia)) < tol_mag_norm) this%constrain(idir, ia) =
m_zero
161 norm = norm2(this%constrain(1:3, ia))
162 if (norm > tol_mag_norm)
then
163 this%constrain(1:3, ia) = this%constrain(1:3, ia) / norm
170 safe_allocate(this%pot(1:mesh%np, 1:std%nspin))
174 call parse_variable(namespace,
'LocalMagneticMomentsSphereRadius', min(
m_half*rmin, 100.0_real64), &
187 safe_deallocate_a(this%constrain)
188 safe_deallocate_a(this%pot)
201 this_out%level = this_in%level
208 if (this_in%level /= constrain_none)
then
209 this_out%lambda = this_in%lambda
210 this_out%energy = this_in%energy
211 this_out%lmm_r = this_in%lmm_r
212 else if (
allocated(this_in%pot) .or.
allocated(this_in%constrain))
then
213 this_out%energy = this_in%energy
216 if (
allocated(this_in%constrain))
then
217 safe_allocate(this_out%constrain(1:
size(this_in%constrain, dim=1), 1:
size(this_in%constrain, dim=2)))
218 this_out%constrain = this_in%constrain
221 if (
allocated(this_in%pot))
then
222 safe_allocate(this_out%pot(1:
size(this_in%pot, dim=1), 1:
size(this_in%pot, dim=2)))
223 this_out%pot = this_in%pot
233 class(
mesh_t),
intent(in) :: mesh
235 class(
space_t),
intent(in) :: space
237 real(real64),
intent(in) :: pos(:,:)
238 real(real64),
intent(in) :: rho(:,:)
240 integer :: ia, idir, ip
241 real(real64) :: bb(3), b2, lmm(3), dotp, norm, xx, max_r
242 real(real64),
allocatable :: md(:,:), mdf(:), mask(:)
247 real(real64),
parameter :: tol_sinc = 0.01_real64
249 if (this%level == constrain_none)
return
258 safe_allocate(md(1:mesh%np, 1:max(space%dim, 3)))
261 natoms =
size(pos, dim=2)
264 call submesh_init(sphere, space, mesh, latt, pos(:, ia), this%lmm_r)
270 max_r = maxval(sphere%r)
271 safe_allocate(mask(1:sphere%np))
275 xx = sphere%r(ip) *
m_pi / max_r
276 if(xx < tol_sinc)
then
279 mask(ip) =
sin(xx)/xx
287 safe_allocate(mdf(1:sphere%np))
288 do idir = 1, max(space%dim, 3)
291 mdf(ip) = md(sphere%map(ip), idir) * mask(ip)
295 safe_deallocate_a(mdf)
299 select case(this%level)
302 if (norm > tol_mag_norm)
then
303 dotp = dot_product(lmm, this%constrain(1:3, ia))
304 this%energy = this%energy + this%lambda * (norm - dotp)
305 bb = lmm/norm - this%constrain(:,ia)
311 this%energy = this%energy + this%lambda * sum((lmm - this%constrain(:,ia))**2)
312 bb =
m_two * (lmm - this%constrain(:,ia))
314 bb = bb * this%lambda
317 select case(std%ispin)
319 b2 = norm2(bb(1:max(space%dim, 3)))
321 this%pot(sphere%map(ip), 1) = this%pot(sphere%map(ip), 1) + b2 * mask(ip)
322 this%pot(sphere%map(ip), 2) = this%pot(sphere%map(ip), 2) - b2 * mask(ip)
327 this%pot(sphere%map(ip), 1) = this%pot(sphere%map(ip), 1) + bb(3) * mask(ip)
328 this%pot(sphere%map(ip), 2) = this%pot(sphere%map(ip), 2) - bb(3) * mask(ip)
329 this%pot(sphere%map(ip), 3) = this%pot(sphere%map(ip), 3) + bb(1) * mask(ip)
330 this%pot(sphere%map(ip), 4) = this%pot(sphere%map(ip), 4) - bb(2) * mask(ip)
335 safe_deallocate_a(mask)
339 safe_deallocate_a(md)
Prints out to iunit a message in the form: ["InputVariable" = value] where "InputVariable" is given b...
double sin(double __x) __attribute__((__nothrow__
integer, parameter, public unpolarized
Parameters...
integer, parameter, public spinors
integer, parameter, public spin_polarized
real(real64), parameter, public m_two
real(real64), parameter, public m_zero
real(real64), parameter, public m_pi
some mathematical constants
real(real64), parameter, public m_half
real(real64), parameter, public m_one
This modules implements the routines for doing constrain DFT for noncollinear magnetism.
subroutine, public magnetic_constrain_copy(this_out, this_in)
Deep-copy magnetic constrain data.
subroutine, public magnetic_constrain_end(this)
Releases memory of the magnetic constrain.
subroutine, public magnetic_constrain_update(this, mesh, std, space, latt, pos, rho)
Recomputes the magnetic contraining potential.
integer, parameter, public constrain_full
integer, parameter, public constrain_dir
subroutine, public magnetic_constrain_init(this, namespace, mesh, std, natoms, min_dist)
Initilializes the magnetic_constrain_t object.
subroutine, public magnetic_density(mesh, std, rho, md)
This module defines the meshes, which are used in Octopus.
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_experimental(name, namespace)
integer function, public parse_block(namespace, name, blk, check_varinfo_)
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
This module handles spin dimensions of the states and the k-point distribution.
real(real64) function, public dsm_integrate(mesh, sm, ff, reduce)
subroutine, public submesh_end(this)
subroutine, public submesh_init(this, space, mesh, latt, center, rc)
Datatype containing the magnetic constrain information.
Describes mesh distribution to nodes.
class for organizing spins and k-points
A submesh is a type of mesh, used for the projectors in the pseudopotentials It contains points on a ...