32 use,
intrinsic :: iso_fortran_env
51 real(real64),
allocatable :: lsize(:)
55 real(real64),
allocatable :: Jlocal(:)
56 real(real64),
allocatable :: Jrange(:)
58 real(real64),
allocatable :: chi_atoms(:,:)
59 real(real64),
allocatable :: csi(:,:)
62 type(root_solver_t) :: rs
74 procedure curv_modine_constructor
78 class(curv_modine_t),
pointer :: modine_p
79 real(real64),
allocatable :: x_p(:)
85 type(namespace_t),
intent(in) :: namespace
86 integer,
intent(in) :: dim
87 integer,
intent(in) :: npos
88 real(real64),
intent(in) :: pos(1:dim,1:npos)
89 real(real64),
intent(in) :: lsize(1:dim)
90 real(real64),
intent(in) :: spacing(1:dim)
91 class(curv_modine_t),
pointer :: modine
98 modine%local_basis = .
true.
99 modine%orthogonal = .
true.
123 safe_allocate(modine%lsize(1:dim))
124 modine%lsize = lsize / modine%Jbar
126 if (modine%xbar <
m_zero .or. modine%xbar >
m_one)
then
127 message(1) =
'The parameter "CurvModineXBar" must lie between 0 and 1.'
131 safe_allocate(modine%Jlocal(1:npos))
132 safe_allocate(modine%Jrange(1:npos))
144 call parse_variable(namespace,
'CurvModineJlocal', 0.25_real64, modine%Jlocal(1))
156 if (modine%Jlocal(1)<
m_zero.or.modine%Jlocal(1)>
m_one)
then
157 message(1) =
'The parameter "CurvModineJlocal" must lie between 0 and 1.'
161 modine%Jlocal(:) = modine%Jlocal(1)
162 modine%Jrange(:) = modine%Jrange(1)
166 solver_type =
root_newton, maxiter = 500, abs_tolerance = 1.0e-10_real64)
171 modine%min_mesh_scaling_product = modine%Jbar**modine%dim
182 safe_allocate(modine%csi(1:modine%dim, 1:modine%npos))
186 safe_allocate(modine%chi_atoms(1:modine%dim, 1:modine%npos))
188 do iatom = 1, modine%npos
189 modine%chi_atoms(:, iatom) = modine%from_cartesian(pos(:, iatom))
191 modine%csi(:,:) = modine%chi_atoms(:,:)
194 do iatom = 1, modine%npos
196 modine%chi_atoms(:, iatom) = nint(modine%chi_atoms(:, iatom) / spacing(:)) * spacing(:)
204 integer :: iatom, idim, index
205 real(real64),
allocatable :: my_csi(:), start_csi(:)
211 safe_allocate(x_p(1:modine%dim*modine%npos))
212 safe_allocate(my_csi(1:modine%dim*modine%npos))
213 safe_allocate(start_csi(1:modine%dim*modine%npos))
215 do iatom = 1, modine%npos
216 do idim = 1, modine%dim
217 index = (iatom-1)*dim + idim
218 x_p(index) = pos(idim, iatom)
219 start_csi(index) = modine%chi_atoms(idim, iatom)
226 message(1) =
"During the construction of the adaptive grid, the Newton-Raphson"
227 message(2) =
"method did not converge."
232 do iatom = 1, modine%npos
233 do idim = 1, modine%dim
234 index = (iatom-1)*modine%dim + idim
235 modine_p%csi(idim, iatom) = my_csi(index)
239 safe_deallocate_a(x_p)
240 safe_deallocate_a(my_csi)
241 safe_deallocate_a(start_csi)
257 this_out%dim = this_in%dim
258 this_out%local_basis = this_in%local_basis
259 safe_allocate_source_a(this_out%lsize, this_in%lsize)
260 this_out%xbar = this_in%xbar
261 this_out%Jbar = this_in%Jbar
262 safe_allocate_source_a(this_out%Jlocal, this_in%Jlocal)
263 safe_allocate_source_a(this_out%Jrange, this_in%Jrange)
264 safe_allocate_source_a(this_out%chi_atoms, this_in%chi_atoms)
265 safe_allocate_source_a(this_out%csi, this_in%csi)
266 this_out%npos = this_in%npos
277 safe_deallocate_a(this%lsize)
278 safe_deallocate_a(this%Jlocal)
279 safe_deallocate_a(this%Jrange)
280 safe_deallocate_a(this%chi_atoms)
281 safe_deallocate_a(this%csi)
289 real(real64),
intent(in) :: chi(:)
290 real(real64) :: xx(1:this%dim)
292 real(real64) :: chi2(this%dim), rr2, dd
300 do iatom = 1, this%npos
301 rr2 = sum((chi2(:) - this%csi(:, iatom))**2)
302 dd =
exp(-rr2/(
m_two*this%Jrange(iatom)**2))
304 xx(:) = xx(:) - this%Jlocal(iatom)*(chi2(:) - this%csi(:, iatom)) * dd
312 real(real64),
intent(in) :: xx(:)
313 real(real64) :: chi(1:this%dim)
320 safe_allocate(x_p(1:this%dim))
325 safe_deallocate_a(x_p)
329 message(1) =
"During the construction of the adaptive grid, the Newton-Raphson"
330 message(2) =
"method did not converge for point:"
331 write(
message(3),
'(3f14.6)') xx(1:this%dim)
340 integer,
optional,
intent(in) :: iunit
341 type(
namespace_t),
optional,
intent(in) :: namespace
345 write(
message(1),
'(a)')
' Curvilinear Method = modine'
354 integer,
intent(in) :: idir
357 message(1) =
'Surface element with modine curvilinear coordinates not implemented'
365 real(real64),
intent(in) :: chi_(:)
366 real(real64),
intent(out) :: chi2(:)
367 real(real64),
optional,
intent(out) :: Jac(:)
369 integer,
parameter :: qq = 3
370 real(real64) :: chibar(this%dim), rr, chi
376 chibar = this%xbar*this%lsize
382 chi2(i) = this%Jbar * chi
383 if (
present(jac)) jac(i) = this%Jbar
385 if (chi > chibar(i))
then
386 rr = (chi - chibar(i))/(this%lsize(i) - chibar(i))
388 chi2(i) = chi2(i) + this%lsize(i)/m_two*(1 - this%Jbar) * rr**qq * &
389 (qq + m_one - (qq - m_one)*rr)
391 if (
present(jac))
then
392 jac(i) = jac(i) + this%lsize(i)/m_two*(m_one - this%Jbar) * rr**(qq - 1)/(this%lsize(i) - chibar(i)) * &
393 (qq*(qq + m_one) - (qq**2 - m_one)*rr)
397 if (neg) chi2(i) = -chi2(i)
406 real(real64),
intent(in) :: chi(:)
407 real(real64),
intent(out) :: xx(:)
408 real(real64),
intent(out) :: jac(:, :)
410 real(real64) :: chi2(this%dim), rr2, dd, j2(this%dim)
411 integer :: iatom, idim, idim2
420 do idim = 1, this%dim
421 jac(idim, idim) = m_one
424 do iatom = 1, this%npos
425 rr2 = sum((chi2(:) - this%csi(:, iatom))**2)
426 dd =
exp(-rr2/(m_two*this%Jrange(iatom)**2))
428 xx(:) = xx(:) - this%Jlocal(iatom)*(chi2(:) - this%csi(:, iatom)) * dd
430 do idim = 1, this%dim
431 jac(idim, idim) = jac(idim, idim) - this%Jlocal(iatom) * dd
432 do idim2 = 1, this%dim
433 jac(idim, idim2) = jac(idim, idim2) + &
434 this%Jlocal(iatom)*(chi2(idim) - this%csi(idim, iatom))*(chi2(idim2) - this%csi(idim2, iatom)) * &
435 m_two/(m_two*this%Jrange(iatom)**2) * dd
440 do idim = 1, this%dim
441 jac(idim, :) = jac(idim, :) * j2(:)
447 pure subroutine getf(yy, ff, jf)
448 real(real64),
intent(in) :: yy(:)
449 real(real64),
intent(out) :: ff(:), jf(:, :)
454 ff(:) = ff(:) -
x_p(:)
459 subroutine getf2(csi, ff, jf)
460 real(real64),
intent(in) :: csi(:)
461 real(real64),
intent(out) :: ff(:), jf(:, :)
463 integer :: i1, j1, i2, j2, index1, index2
464 real(real64) :: rr2, dd, dd2
465 real(real64),
allocatable :: xx(:), chi2(:)
488 rr2 = sum((chi2 -
modine_p%csi(:,i2))**2)
496 ff(index1) = xx(j1) -
x_p(index1)
499 rr2 = sum((chi2 -
modine_p%csi(:,i2))**2)
501 dd2 = -m_two/(m_two*
modine_p%Jrange(i2)**2)*dd
504 jf(index1, index2) =
modine_p%Jlocal(i2) * dd
509 jf(index1, index2) = jf(index1, index2) +
modine_p%Jlocal(i2) * dd2 * &
516 safe_deallocate_a(xx)
517 safe_deallocate_a(chi2)
524 real(real64),
intent(in) :: chi(:)
525 real(real64) :: jacobian(1:this%dim, 1:this%dim)
527 real(real64) :: dummy(this%dim)
536 real(real64),
intent(in) :: chi(:)
537 real(real64) :: jacobian_inverse(1:this%dim, 1:this%dim)
539 real(real64) :: dummy(this%dim)
542 call lalg_inverse(this%dim, jacobian_inverse,
"dir")
subroutine find_atom_points()
double exp(double __x) __attribute__((__nothrow__
This module implements the curvilinear coordinates given in N. A. Modine, G. Zumbach,...
class(curv_modine_t), pointer modine_p
real(real64) function, dimension(1:this%dim) curv_modine_from_cartesian(this, xx)
real(real64) function curv_modine_surface_element(this, idir)
real(real64) function, dimension(1:this%dim, 1:this%dim) curv_modine_jacobian_inverse(this, chi)
pure subroutine curv_modine_jacobian_inv(this, chi, xx, Jac)
real(real64) function, dimension(1:this%dim, 1:this%dim) curv_modine_jacobian(this, chi)
class(curv_modine_t) function, pointer curv_modine_constructor(namespace, dim, npos, pos, lsize, spacing)
subroutine getf2(csi, ff, jf)
pure subroutine getf(yy, ff, jf)
subroutine curv_modine_finalize(this)
real(real64), dimension(:), allocatable x_p
pure subroutine curv_modine_chi2chi2(this, chi_, chi2, Jac)
subroutine, public curv_modine_copy(this_out, this_in)
subroutine curv_modine_write_info(this, iunit, namespace)
real(real64) function, dimension(1:this%dim) curv_modine_to_cartesian(this, chi)
real(real64), parameter, public m_two
real(real64), parameter, public m_zero
real(real64), parameter, public m_half
real(real64), parameter, public m_one
real(real64), parameter, public m_three
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_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
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