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 this%constrain(1:3, ia) = this%constrain(1:3, ia) / norm
168 safe_allocate(this%pot(1:mesh%np, 1:std%nspin))
172 call parse_variable(namespace,
'LocalMagneticMomentsSphereRadius', min(
m_half*rmin, 100.0_real64), &
185 safe_deallocate_a(this%constrain)
186 safe_deallocate_a(this%pot)
199 this_out%level = this_in%level
206 if (this_in%level /= constrain_none)
then
207 this_out%lambda = this_in%lambda
208 this_out%energy = this_in%energy
209 this_out%lmm_r = this_in%lmm_r
210 else if (
allocated(this_in%pot) .or.
allocated(this_in%constrain))
then
211 this_out%energy = this_in%energy
214 if (
allocated(this_in%constrain))
then
215 safe_allocate(this_out%constrain(1:
size(this_in%constrain, dim=1), 1:
size(this_in%constrain, dim=2)))
216 this_out%constrain = this_in%constrain
219 if (
allocated(this_in%pot))
then
220 safe_allocate(this_out%pot(1:
size(this_in%pot, dim=1), 1:
size(this_in%pot, dim=2)))
221 this_out%pot = this_in%pot
231 class(
mesh_t),
intent(in) :: mesh
233 class(
space_t),
intent(in) :: space
235 real(real64),
intent(in) :: pos(:,:)
236 real(real64),
intent(in) :: rho(:,:)
238 integer :: ia, idir, ip
239 real(real64) :: bb(3), b2, lmm(3), dotp, norm, xx, max_r
240 real(real64),
allocatable :: md(:,:), mdf(:), mask(:)
245 real(real64),
parameter :: tol_sinc = 0.01_real64
247 if (this%level == constrain_none)
return
256 safe_allocate(md(1:mesh%np, 1:max(space%dim, 3)))
259 natoms =
size(pos, dim=2)
262 call submesh_init(sphere, space, mesh, latt, pos(:, ia), this%lmm_r)
268 max_r = maxval(sphere%r)
269 safe_allocate(mask(1:sphere%np))
273 xx = sphere%r(ip) *
m_pi / max_r
274 if(xx < tol_sinc)
then
277 mask(ip) =
sin(xx)/xx
285 safe_allocate(mdf(1:sphere%np))
286 do idir = 1, max(space%dim, 3)
289 mdf(ip) = md(sphere%map(ip), idir) * mask(ip)
293 safe_deallocate_a(mdf)
297 select case(this%level)
300 if (norm > tol_mag_norm)
then
301 dotp = dot_product(lmm, this%constrain(1:3, ia))
302 this%energy = this%energy + this%lambda * (norm - dotp)
303 bb = lmm/norm - this%constrain(:,ia)
308 this%energy = this%energy + this%lambda * sum((lmm - this%constrain(:,ia))**2)
309 bb =
m_two * (lmm - this%constrain(:,ia))
311 bb = bb * this%lambda
314 select case(std%ispin)
316 b2 = norm2(bb(1:max(space%dim, 3)))
318 this%pot(sphere%map(ip), 1) = this%pot(sphere%map(ip), 1) + b2 * mask(ip)
319 this%pot(sphere%map(ip), 2) = this%pot(sphere%map(ip), 2) - b2 * mask(ip)
324 this%pot(sphere%map(ip), 1) = this%pot(sphere%map(ip), 1) + bb(3) * mask(ip)
325 this%pot(sphere%map(ip), 2) = this%pot(sphere%map(ip), 2) - bb(3) * mask(ip)
326 this%pot(sphere%map(ip), 3) = this%pot(sphere%map(ip), 3) + bb(1) * mask(ip)
327 this%pot(sphere%map(ip), 4) = this%pot(sphere%map(ip), 4) - bb(2) * mask(ip)
332 safe_deallocate_a(mask)
336 safe_deallocate_a(md)
337 safe_deallocate_a(mdf)
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 ...