28 use,
intrinsic :: iso_fortran_env
48 real(real64),
public :: A
49 real(real64),
public :: alpha
50 real(real64),
public :: beta
51 real(real64),
allocatable :: pos(:, :)
53 type(root_solver_t) :: rs
64 procedure curv_gygi_constructor
68 class(curv_gygi_t),
pointer :: gygi_p
70 real(real64),
allocatable :: chi_p(:)
76 type(namespace_t),
intent(in) :: namespace
77 integer,
intent(in) :: dim
78 integer,
intent(in) :: npos
79 real(real64),
intent(in) :: pos(1:dim,1:npos)
80 class(curv_gygi_t),
pointer :: gygi
87 gygi%local_basis = .
true.
88 gygi%orthogonal = .
true.
91 safe_allocate(gygi%pos(1:dim, 1:gygi%npos))
135 gygi%min_mesh_scaling_product = (
m_one / (
m_one + gygi%A))**gygi%dim
150 this_out%A = this_in%A
151 this_out%alpha = this_in%alpha
152 this_out%beta = this_in%beta
153 safe_allocate_source_a(this_out%pos, this_in%pos)
154 this_out%npos = this_in%npos
165 safe_deallocate_a(this%pos)
173 real(real64),
intent(in) :: chi(:)
174 real(real64) :: xx(1:this%dim)
183 safe_allocate(chi_p(1:this%dim))
197 safe_deallocate_a(chi_p)
200 message(1) =
"During the construction of the adaptive grid, the Newton-Raphson"
201 message(2) =
"method did not converge for point:"
202 write(
message(3),
'(9f14.6)') xx(1:this%dim)
203 message(4) =
"Try varying the Gygi parameters -- usually reducing CurvGygiA or"
204 message(5) =
"CurvGygiAlpha (or both) solves the problem."
213 real(real64),
intent(in) :: xx(:)
214 real(real64) :: chi(1:this%dim)
217 real(real64) :: r, ar, th, ex
221 chi(1:this%dim) = xx(1:this%dim)
223 r = max(norm2(xx(1:this%dim) - this%pos(1:this%dim, ia)), 1e-6_real64)
224 ar = this%A*this%alpha/r
225 th =
tanh(r/this%alpha)
226 ex =
exp(-(r/this%beta)**2)
228 chi(i) = chi(i) + (xx(i) - this%pos(i, ia)) * this%a * ar * th * ex
237 real(real64),
intent(in) :: xx(:)
238 real(real64),
intent(in) :: chi(:)
240 real(real64) :: dummy(this%dim)
241 real(real64) :: jac(1:this%dim, 1:this%dim)
253 integer,
optional,
intent(in) :: iunit
254 type(namespace_t),
optional,
intent(in) :: namespace
258 write(message(1),
'(a)')
' Curvilinear Method = gygi'
259 write(message(2),
'(a)')
' Gygi Parameters:'
260 write(message(3),
'(4x,a,f6.3)')
'A = ', this%a
261 write(message(4),
'(4x,3a,f6.3)')
'alpha [', trim(units_abbrev(units_out%length)),
'] = ', &
262 units_from_atomic(units_out%length, this%alpha)
263 write(message(5),
'(4x,3a,f6.3)')
'beta [', trim(units_abbrev(units_out%length)),
'] = ', &
264 units_from_atomic(units_out%length, this%beta)
265 call messages_info(5, iunit=iunit, namespace=namespace)
273 integer,
intent(in) :: idir
276 message(1) =
'Surface element with gygi curvilinear coordinates not implemented'
277 call messages_fatal(1)
284 real(real64),
intent(in) :: xx(:)
285 real(real64),
intent(out) :: chi(:)
286 real(real64),
intent(out) :: jac(:, :)
287 integer,
optional,
intent(in) :: natoms
289 integer :: i, ix, iy, natoms_
290 real(real64) :: r, f_alpha, df_alpha
291 real(real64) :: th, ex, ar
295 jac(1:this%dim, 1:this%dim) = diagonal_matrix(this%dim, m_one)
296 chi(1:this%dim) = xx(1:this%dim)
299 if (
present(natoms)) natoms_ = natoms
302 r = max(norm2(xx(1:this%dim) - this%pos(1:this%dim, i)), 1e-6_real64)
304 ar = this%A*this%alpha/r
305 th =
tanh(r/this%alpha)
306 ex =
exp(-(r/this%beta)**2)
308 f_alpha = ar * th * ex
309 df_alpha = ar*(-th*ex/r + ex/(this%alpha*
cosh(r/this%alpha)**2) - th*m_two*r*ex/this%beta**2)
312 chi(ix) = chi(ix) + f_alpha*(xx(ix) - this%pos(ix, i))
314 jac(ix, ix) = jac(ix, ix) + f_alpha
316 jac(ix, iy) = jac(ix, iy) + (xx(ix) - this%pos(ix, i))*(xx(iy) - this%pos(iy, i))/r*df_alpha
324 pure subroutine getf(y, f, jf)
325 real(real64),
intent(in) :: y(:)
326 real(real64),
intent(out) :: f(:), jf(:, :)
Note that lalg_determinant and lalg_inverse are just wrappers over the same routine.
double exp(double __x) __attribute__((__nothrow__
double tanh(double __x) __attribute__((__nothrow__
double cosh(double __x) __attribute__((__nothrow__
This module implements the curvilinear coordinates given in F. Gygi and G. Galli, PRB 52 R2229 (1996)...
subroutine curv_gygi_write_info(this, iunit, namespace)
real(real64), dimension(:), allocatable chi_p
pure subroutine getf(y, f, jf)
real(real64) function curv_gygi_det_jac(this, xx, chi)
pure subroutine curv_gygi_jacobian(this, xx, chi, jac, natoms)
pure real(real64) function, dimension(1:this%dim) curv_gygi_from_cartesian(this, xx)
subroutine, public curv_gygi_copy(this_out, this_in)
real(real64) function, dimension(1:this%dim) curv_gygi_to_cartesian(this, chi)
real(real64) function curv_gygi_surface_element(this, idir)
class(curv_gygi_t) function, pointer curv_gygi_constructor(namespace, dim, npos, pos)
class(curv_gygi_t), pointer gygi_p
subroutine curv_gygi_finalize(this)
real(real64), parameter, public m_two
real(real64), parameter, public m_zero
real(real64), parameter, public m_four
real(real64), parameter, public m_half
real(real64), parameter, public m_one
This module is intended to contain "only mathematical" functions and procedures.
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_input_error(namespace, var, details, row, column)
integer, parameter, public root_newton
subroutine, public root_solver_init(rs, namespace, dimensionality, solver_type, maxiter, rel_tolerance, abs_tolerance)
subroutine, public droot_solver_run(rs, func, root, success, startval)
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
This module defines the unit system, used for input and output.
type(unit_system_t), public units_inp
the units systems for reading and writing
abstract class to describe coordinate systems