42 use,
intrinsic :: iso_fortran_env
117 integer,
parameter :: &
118 DER_BC_ZERO_F = 0, & !< function is zero at the boundaries
122 integer,
parameter,
public :: &
129 integer,
parameter :: &
137 type(boundaries_t) :: boundaries
138 type(mesh_t),
pointer :: mesh => null()
140 integer,
private :: periodic_dim = 0
142 integer :: stencil_type = 0
144 real(real64),
allocatable :: masses(:)
148 real(real64),
private :: lapl_cutoff =
m_zero
150 type(nl_operator_t),
allocatable,
private :: op(:)
152 type(nl_operator_t),
pointer :: lapl => null()
153 type(nl_operator_t),
pointer :: grad(:) => null()
155 integer,
allocatable :: n_ghost(:)
157 integer,
private :: comm_method = 0
159 type(derivatives_t),
pointer :: finer => null()
160 type(derivatives_t),
pointer :: coarser => null()
161 type(transfer_table_t),
pointer :: to_finer => null()
162 type(transfer_table_t),
pointer :: to_coarser => null()
169 type(par_vec_handle_batch_t) :: pv_h
171 type(derivatives_t),
pointer :: der
172 type(nl_operator_t),
pointer :: op
173 type(batch_t),
pointer :: ff
174 type(batch_t),
pointer :: opff
175 logical :: ghost_update
176 logical :: factor_present
177 real(real64) :: factor
180 type(accel_kernel_t) :: kernel_uvw_xyz, kernel_dcurl, kernel_zcurl
186 type(derivatives_t),
target,
intent(inout) :: der
187 type(namespace_t),
intent(in) :: namespace
188 class(space_t),
intent(in) :: space
189 class(coordinate_system_t),
intent(in) :: coord_system
190 integer,
optional,
intent(in) :: order
193 integer :: default_stencil
194 character(len=40) :: flags
199 assert(.not. coord_system%local_basis .or. coord_system%orthogonal)
203 der%periodic_dim = space%periodic_dim
228 default_stencil = der_star
229 if (coord_system%local_basis) default_stencil =
der_starplus
232 call parse_variable(namespace,
'DerivativesStencil', default_stencil, der%stencil_type)
272 if (
present(order))
then
299 safe_allocate(der%masses(1:space%dim))
303 safe_allocate(der%op(1:der%dim + 1))
305 der%lapl => der%op(der%dim + 1)
311 safe_allocate(der%n_ghost(1:der%dim))
314 der%n_ghost(idir) = maxval(abs(der%lapl%stencil%points(idir, :)))
319 nullify(der%to_coarser)
320 nullify(der%to_finer)
324 select type (coord_system)
328 if (der%dim > 3)
then
329 message(1) =
"Calculation of derivatives on the GPU with dimension > 3 are only implemented for Cartesian coordinates."
332 write(flags,
'(A,I1.1)')
' -DDIMENSION=', der%dim
352 assert(
allocated(der%op))
354 do idim = 1, der%dim+1
358 safe_deallocate_a(der%masses)
360 safe_deallocate_a(der%n_ghost)
362 safe_deallocate_a(der%op)
363 nullify(der%lapl, der%grad)
367 nullify(der%to_coarser)
368 nullify(der%to_finer)
379 class(
space_t),
intent(in) :: space
384 assert(
associated(der%lapl))
390 select case (der%stencil_type)
410 real(real64),
intent(out) :: lapl(:)
414 assert(ubound(lapl, dim=1) >= der%mesh%np)
430 character :: dir_label
434 assert(
associated(der%grad))
444 select case (der%stencil_type)
493 subroutine derivatives_build(der, namespace, space, mesh, qvector, regenerate, verbose)
496 class(
space_t),
intent(in) :: space
497 class(
mesh_t),
target,
intent(in) :: mesh
498 real(real64),
optional,
intent(in) :: qvector(:)
500 logical,
optional,
intent(in) :: regenerate
501 logical,
optional,
intent(in) :: verbose
503 integer,
allocatable :: polynomials(:,:)
504 real(real64),
allocatable :: rhs(:,:)
507 character(len=32) :: name
509 integer :: np_zero_bc
517 assert(
allocated(der%op))
519 assert(.not.(der%stencil_type ==
der_variational .and. mesh%use_curvilinear))
526 if (mesh%use_curvilinear) const_w_ = .false.
533 safe_deallocate_a(der%op(i)%w)
535 call nl_operator_build(space, mesh, der%op(i), der%mesh%np, const_w = const_w_, &
536 regenerate=regenerate)
540 assert(np_zero_bc > mesh%np .and. np_zero_bc <= mesh%np_part)
542 select case (der%stencil_type)
545 do i = 1, der%dim + 1
546 safe_allocate(polynomials(1:der%dim, 1:der%op(i)%stencil%size))
547 safe_allocate(rhs(1:der%op(i)%stencil%size, 1))
549 if (i <= der%dim)
then
560 der%op(i:i), name, verbose=verbose)
561 safe_deallocate_a(polynomials)
562 safe_deallocate_a(rhs)
568 safe_allocate(polynomials(1:der%dim, 1:der%op(1)%stencil%size))
569 safe_allocate(rhs(1:der%op(1)%stencil%size, 1:der%dim + 1))
579 der%dim+1, der%op(:), name, verbose=verbose)
581 safe_deallocate_a(polynomials)
582 safe_deallocate_a(rhs)
591 if (mesh%use_curvilinear)
then
594 call messages_write(
'Curvilinear coordinates on GPUs is not implemented')
618 integer,
intent(in) :: stencil_type
619 integer,
intent(in) :: dim
620 integer,
intent(in) :: direction
621 integer,
intent(in) :: order
622 integer,
intent(inout) :: polynomials(:, :)
624 select case (der%stencil_type)
633 integer,
intent(in) :: stencil_type
635 integer,
intent(in) :: dim
636 integer,
intent(in) :: order
637 integer,
intent(inout) :: polynomials(:, :)
639 select case (der%stencil_type)
654 integer,
intent(in) :: polynomials(:,:)
655 real(real64),
intent(out) :: rhs(:)
658 real(real64) ::
f(1:der%dim, 1:der%dim)
659 integer :: powers(0:2)
669 select type (coord => der%mesh%coord_system)
671 f(1:der%dim, 1:der%dim) = matmul(coord%basis%change_of_basis_matrix(1:der%dim, 1:der%dim), &
672 transpose(coord%basis%change_of_basis_matrix(1:der%dim, 1:der%dim)))
677 message(1) =
"Weight computation not implemented for the coordinate system chosen."
683 do j = 1,
size(polynomials, dim=2)
687 if (polynomials(i, j) <= 2)
then
688 powers(polynomials(i, j)) = powers(polynomials(i, j)) + 1
694 if (powers(2) == 1 .and. powers(0) == der%dim - 1)
then
696 if (polynomials(i, j) == 2)
then
703 if (powers(1) == 2 .and. powers(0) == der%dim - 2)
then
705 if (polynomials(i, j) == 1)
then
707 if (polynomials(k, j) == 1)
then
708 rhs(j) =
f(i, k) +
f(k, i)
722 integer,
intent(in) :: polynomials(:,:)
723 integer,
intent(in) :: dir
724 real(real64),
intent(out) :: rhs(:)
733 do j = 1, der%grad(dir)%stencil%size
736 if (k == dir .and. polynomials(k, j) /= 1) this_one = .false.
737 if (k /= dir .and. polynomials(k, j) /= 0) this_one = .false.
739 if (this_one) rhs(j) =
m_one
747 subroutine derivatives_make_discretization(namespace, dim, periodic_dim, mesh, masses, pol, rhs, nderiv, op, name, &
750 integer,
intent(in) :: dim
751 integer,
intent(in) :: periodic_dim
752 type(
mesh_t),
intent(in) :: mesh
753 real(real64),
intent(in) :: masses(:)
754 integer,
intent(in) :: pol(:,:)
755 integer,
intent(in) :: nderiv
756 real(real64),
contiguous,
intent(inout) :: rhs(:,:)
758 character(len=32),
intent(in) :: name
759 logical,
optional,
intent(in) :: verbose
761 integer :: p, p_max, i, j, k, pow_max
762 real(real64) :: x(dim)
763 real(real64),
allocatable :: mat(:,:), sol(:,:), powers(:,:)
764 logical :: transform_to_cartesian
768 safe_allocate(mat(1:op(1)%stencil%size, 1:op(1)%stencil%size))
769 safe_allocate(sol(1:op(1)%stencil%size, 1:nderiv))
772 message(1) =
'Info: Generating weights for finite-difference discretization of ' // trim(name)
776 select type (coord => mesh%coord_system)
778 transform_to_cartesian = .false.
780 transform_to_cartesian = .
true.
782 transform_to_cartesian = .
true.
784 transform_to_cartesian = .
true.
786 message(1) =
"Weight computation not implemented for the coordinate system chosen."
791 pow_max = maxval(pol)
792 safe_allocate(powers(1:dim, 0:pow_max))
797 if (op(1)%const_w) p_max = 1
803 do i = 1, op(1)%stencil%size
804 if (mesh%use_curvilinear)
then
805 x = mesh%x(p + op(1)%ri(i, op(1)%rimap(p)), :) - mesh%x(p, :)
807 x = real(op(1)%stencil%points(:, i), real64) *mesh%spacing
809 if (transform_to_cartesian)
then
810 x = mesh%coord_system%to_cartesian(x)
820 powers(:, k) = x*powers(:, k-1)
825 do j = 2, op(1)%stencil%size
826 mat(j, i) = powers(1, pol(1, j))
828 mat(j, i) = mat(j, i)*powers(k, pol(k, j))
840 op(i)%w(:, p) = sol(:, i)
857 safe_deallocate_a(mat)
858 safe_deallocate_a(sol)
859 safe_deallocate_a(powers)
871 overlap = this%comm_method /= blocking
882 class(
space_t),
intent(in) :: space
883 character(len=32),
intent(in) :: name
884 integer,
intent(in) :: order
886 integer,
allocatable :: polynomials(:,:)
887 real(real64),
allocatable :: rhs(:,:)
892 if (.not. this%mesh%coord_system%orthogonal)
then
898 call nl_operator_build(space, this%mesh, op(1), this%mesh%np, const_w = .not. this%mesh%use_curvilinear)
901 safe_allocate(polynomials(1:this%dim, 1:op(1)%stencil%size))
902 safe_allocate(rhs(1:op(1)%stencil%size, 1))
903 if (.not. this%mesh%coord_system%orthogonal)
then
910 polynomials, rhs, 1, op(1:1), name)
911 safe_deallocate_a(polynomials)
912 safe_deallocate_a(rhs)
933 logical :: mask(1:this%mesh%np)
934 integer :: ip, is, index
938 do ip = 1, this%mesh%np
940 do is = 1, this%lapl%stencil%size
944 if (index > this%mesh%np + this%mesh%pv%np_ghost)
then
958 real(real64) function derivatives_lapl_get_max_eigenvalue(this)
963 push_sub(derivatives_lapl_get_max_eigenvalue)
965 derivatives_lapl_get_max_eigenvalue =
m_zero
966 if ((this%stencil_type == der_star .or. this%stencil_type ==
der_stargeneral) &
967 .and. .not. this%mesh%use_curvilinear)
then
969 do i = 1, this%lapl%stencil%size
970 derivatives_lapl_get_max_eigenvalue = derivatives_lapl_get_max_eigenvalue + &
971 (-1)**maxval(abs(this%lapl%stencil%points(:, i)))*this%lapl%w(i, 1)
973 derivatives_lapl_get_max_eigenvalue = abs(derivatives_lapl_get_max_eigenvalue)
977 derivatives_lapl_get_max_eigenvalue = derivatives_lapl_get_max_eigenvalue + &
978 m_pi**2/this%mesh%spacing(i)**2
982 pop_sub(derivatives_lapl_get_max_eigenvalue)
988#include "derivatives_inc.F90"
991#include "complex.F90"
992#include "derivatives_inc.F90"
subroutine stencil_stars_pol_grad(stencil_type, dim, direction, order, polynomials)
subroutine stencil_stars_pol_lapl(stencil_type, stencil, dim, order, polynomials)
double sqrt(double __x) __attribute__((__nothrow__
subroutine, public accel_kernel_build(this, file_name, kernel_name, flags)
pure logical function, public accel_is_enabled()
This module implements batches of mesh functions.
This module implements common operations on batches of mesh functions.
Module implementing boundary conditions in Octopus.
subroutine, public boundaries_end(this)
subroutine, public boundaries_init(this, namespace, space, mesh, qvector)
initialize the boundary contitions
This module implements the curvilinear coordinates given in E.L. Briggs, D.J. Sullivan,...
This module implements the curvilinear coordinates given in F. Gygi and G. Galli, PRB 52 R2229 (1996)...
This module implements the curvilinear coordinates given in N. A. Modine, G. Zumbach,...
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public dderivatives_test(this, namespace, repetitions, min_blocksize, max_blocksize)
unit test for derivatives
subroutine derivatives_get_stencil_lapl(der, space, coord_system)
subroutine, public dderivatives_batch_grad(der, ffb, opffb, ghost_update, set_bc, to_cartesian, metric, factor)
apply the gradient to a batch of mesh functions
subroutine, public zderivatives_curl(der, ff, op_ff, ghost_update, set_bc)
apply the curl operator to a vector of mesh functions
subroutine, public dderivatives_perform(op, der, ff, op_ff, ghost_update, set_bc, factor)
apply a nl_operator to a mesh function
subroutine, public derivatives_lapl_diag(der, lapl)
Returns the diagonal elements of the Laplacian, needed for preconditioning.
integer, parameter, public der_cube
subroutine, public dderivatives_batch_curl_from_gradient(der, ffb, gradb)
calculate the curl from a batch and its gradient
subroutine, public derivatives_build(der, namespace, space, mesh, qvector, regenerate, verbose)
build the derivatives object:
subroutine get_rhs_grad(der, polynomials, dir, rhs)
subroutine, public zderivatives_batch_curl_from_gradient(der, ffb, gradb)
calculate the curl from a batch and its gradient
subroutine, public zderivatives_batch_div(der, ffb, opffb, ghost_update, set_bc, to_cartesian)
calculate the divergence of a vector of batches
subroutine, public dderivatives_partial(der, ff, op_ff, dir, ghost_update, set_bc)
apply the partial derivative along dir to a mesh function
subroutine, public dderivatives_batch_perform(op, der, ff, opff, ghost_update, set_bc, factor, async)
apply an operator to a bach of mesh functions
subroutine, public zderivatives_div(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the divergence operator to a vector of mesh functions
integer, parameter der_bc_period
boundary is periodic
subroutine, public dderivatives_batch_finish(handle, async)
apply a non-local operator to a batch (2nd part)
subroutine, public dderivatives_curl(der, ff, op_ff, ghost_update, set_bc)
apply the curl operator to a vector of mesh functions
subroutine derivatives_get_stencil_grad(der)
subroutine, public dderivatives_grad(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the gradient to a mesh function
subroutine, public derivatives_init(der, namespace, space, coord_system, order)
subroutine, public derivatives_end(der)
integer, parameter der_bc_zero_df
first derivative of the function is zero
subroutine, public dderivatives_batch_div(der, ffb, opffb, ghost_update, set_bc, to_cartesian)
calculate the divergence of a vector of batches
subroutine, public derivatives_get_lapl(this, namespace, op, space, name, order)
subroutine get_rhs_lapl(der, polynomials, rhs)
subroutine, public zderivatives_batch_perform(op, der, ff, opff, ghost_update, set_bc, factor, async)
apply an operator to a bach of mesh functions
subroutine, public zderivatives_batch_grad(der, ffb, opffb, ghost_update, set_bc, to_cartesian, metric, factor)
apply the gradient to a batch of mesh functions
subroutine, public dderivatives_batch_start(op, der, ff, opff, handle, ghost_update, set_bc, factor)
apply a non-local operator to a batch (1st part)
subroutine, public dderivatives_lapl(der, ff, op_ff, ghost_update, set_bc, factor)
apply the Laplacian to a mesh function
real(real64) function, public derivatives_lapl_get_max_eigenvalue(this)
Get maximum eigenvalue of discrete Laplacian. For the star and star_general stencils,...
logical function derivatives_overlap(this)
subroutine, public dderivatives_batch_curl(der, ffb, ghost_update, set_bc)
apply the curl to a batch of mesh functions
subroutine, public zderivatives_grad(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the gradient to a mesh function
subroutine derivatives_make_discretization(namespace, dim, periodic_dim, mesh, masses, pol, rhs, nderiv, op, name, verbose)
subroutine, public zderivatives_partial(der, ff, op_ff, dir, ghost_update, set_bc)
apply the partial derivative along dir to a mesh function
subroutine, public zderivatives_batch_start(op, der, ff, opff, handle, ghost_update, set_bc, factor)
apply a non-local operator to a batch (1st part)
logical function, dimension(1:this%mesh%np), public derivatives_get_inner_boundary_mask(this)
This function tells whether a point in the grid is contained in a layer of the width of the stencil b...
integer, parameter, public der_starplus
subroutine, public zderivatives_perform(op, der, ff, op_ff, ghost_update, set_bc, factor)
apply a nl_operator to a mesh function
subroutine, public zderivatives_batch_curl(der, ffb, ghost_update, set_bc)
apply the curl to a batch of mesh functions
subroutine, public zderivatives_test(this, namespace, repetitions, min_blocksize, max_blocksize)
unit test for derivatives
integer, parameter, public der_variational
subroutine, public zderivatives_lapl(der, ff, op_ff, ghost_update, set_bc, factor)
apply the Laplacian to a mesh function
subroutine, public zderivatives_batch_finish(handle, async)
apply a non-local operator to a batch (2nd part)
subroutine, public dderivatives_div(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the divergence operator to a vector of mesh functions
integer, parameter non_blocking
integer, parameter, public der_stargeneral
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_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_obsolete_variable(namespace, name, rep)
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)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
This module defines non-local operators.
subroutine, public dnl_operator_operate_diag(op, fo)
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_copy(opo, opi)
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_adjoint(op, opt, mesh, self_adjoint)
opt has to be initialised and built.
integer pure function, public nl_operator_np_zero_bc(op)
integer pure function, public nl_operator_get_index(op, is, ip)
subroutine, public nl_operator_allocate_gpu_buffers(op)
Some general things and nomenclature:
This module defines routines, generating operators for a cubic stencil.
subroutine, public stencil_cube_get_lapl(this, dim, order)
subroutine, public stencil_cube_polynomials_lapl(dim, order, pol)
subroutine, public stencil_cube_get_grad(this, dim, order)
This module defines stencils used in Octopus.
This module defines routines, generating operators for a star stencil.
subroutine, public stencil_star_get_grad(this, dim, dir, order)
subroutine, public stencil_star_get_lapl(this, dim, order)
subroutine, public stencil_star_polynomials_grad(dir, order, pol)
subroutine, public stencil_star_polynomials_lapl(dim, order, pol)
This module defines routines, generating operators for a generalized star stencil.
subroutine, public stencil_stargeneral_get_arms(this, dim, coord_system)
Finds the direction of the arms of the star-general stencil as described in Natan et al....
subroutine, public stencil_stargeneral_pol_lapl(this, dim, order, pol)
subroutine, public stencil_stargeneral_get_lapl(this, dim, order)
This module defines routines, generating operators for a stencil consisting of a star and a cross....
subroutine, public stencil_starplus_pol_grad(dim, dir, order, pol)
subroutine, public stencil_starplus_pol_lapl(dim, order, pol)
subroutine, public stencil_starplus_get_lapl(this, dim, order)
subroutine, public stencil_starplus_get_grad(this, dim, dir, order)
Implements the variational discretization of the Laplacian as proposed by P. Maragakis,...
subroutine, public stencil_variational_coeff_lapl(dim, order, h, lapl, alpha)
This module is intended to contain simple general-purpose utility functions and procedures.
character pure function, public index2axis(idir)
static double f(double w, void *p)
abstract class to describe coordinate systems
handle to transfer data from the start() to finish() calls.
class representing derivatives
Describes mesh distribution to nodes.
data type for non local operators
The class representing the stencil, which is used for non-local mesh operations.