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)
265 if (
present(order))
then
292 safe_allocate(der%masses(1:space%dim))
296 safe_allocate(der%op(1:der%dim + 1))
298 der%lapl => der%op(der%dim + 1)
304 safe_allocate(der%n_ghost(1:der%dim))
307 der%n_ghost(idir) = maxval(abs(der%lapl%stencil%points(idir, :)))
312 nullify(der%to_coarser)
313 nullify(der%to_finer)
317 select type (coord_system)
321 if (der%dim > 3)
then
322 message(1) =
"Calculation of derivatives on the GPU with dimension > 3 are only implemented for Cartesian coordinates."
325 write(flags,
'(A,I1.1)')
' -DDIMENSION=', der%dim
345 assert(
allocated(der%op))
347 do idim = 1, der%dim+1
351 safe_deallocate_a(der%masses)
353 safe_deallocate_a(der%n_ghost)
355 safe_deallocate_a(der%op)
356 nullify(der%lapl, der%grad)
360 nullify(der%to_coarser)
361 nullify(der%to_finer)
372 class(
space_t),
intent(in) :: space
377 assert(
associated(der%lapl))
383 select case (der%stencil_type)
403 real(real64),
intent(out) :: lapl(:)
407 assert(ubound(lapl, dim=1) >= der%mesh%np)
423 character :: dir_label
427 assert(
associated(der%grad))
437 select case (der%stencil_type)
486 subroutine derivatives_build(der, namespace, space, mesh, qvector, regenerate, verbose)
489 class(
space_t),
intent(in) :: space
490 class(
mesh_t),
target,
intent(in) :: mesh
491 real(real64),
optional,
intent(in) :: qvector(:)
493 logical,
optional,
intent(in) :: regenerate
494 logical,
optional,
intent(in) :: verbose
496 integer,
allocatable :: polynomials(:,:)
497 real(real64),
allocatable :: rhs(:,:)
500 character(len=32) :: name
502 integer :: np_zero_bc
510 assert(
allocated(der%op))
512 assert(.not.(der%stencil_type ==
der_variational .and. mesh%use_curvilinear))
519 if (mesh%use_curvilinear) const_w_ = .false.
526 safe_deallocate_a(der%op(i)%w)
528 call nl_operator_build(space, mesh, der%op(i), der%mesh%np, const_w = const_w_, &
529 regenerate=regenerate)
533 assert(np_zero_bc > mesh%np .and. np_zero_bc <= mesh%np_part)
535 select case (der%stencil_type)
538 do i = 1, der%dim + 1
539 safe_allocate(polynomials(1:der%dim, 1:der%op(i)%stencil%size))
540 safe_allocate(rhs(1:der%op(i)%stencil%size, 1))
542 if (i <= der%dim)
then
553 der%op(i:i), name, verbose=verbose)
554 safe_deallocate_a(polynomials)
555 safe_deallocate_a(rhs)
561 safe_allocate(polynomials(1:der%dim, 1:der%op(1)%stencil%size))
562 safe_allocate(rhs(1:der%op(1)%stencil%size, 1:der%dim + 1))
572 der%dim+1, der%op(:), name, verbose=verbose)
574 safe_deallocate_a(polynomials)
575 safe_deallocate_a(rhs)
584 if (mesh%use_curvilinear)
then
587 call messages_write(
'Curvilinear coordinates on GPUs is not implemented')
611 integer,
intent(in) :: stencil_type
612 integer,
intent(in) :: dim
613 integer,
intent(in) :: direction
614 integer,
intent(in) :: order
615 integer,
intent(inout) :: polynomials(:, :)
617 select case (der%stencil_type)
626 integer,
intent(in) :: stencil_type
628 integer,
intent(in) :: dim
629 integer,
intent(in) :: order
630 integer,
intent(inout) :: polynomials(:, :)
632 select case (der%stencil_type)
647 integer,
intent(in) :: polynomials(:,:)
648 real(real64),
intent(out) :: rhs(:)
651 real(real64) :: f(1:der%dim, 1:der%dim)
652 integer :: powers(0:2)
662 select type (coord => der%mesh%coord_system)
664 f(1:der%dim, 1:der%dim) = matmul(coord%basis%change_of_basis_matrix(1:der%dim, 1:der%dim), &
665 transpose(coord%basis%change_of_basis_matrix(1:der%dim, 1:der%dim)))
670 message(1) =
"Weight computation not implemented for the coordinate system chosen."
676 do j = 1,
size(polynomials, dim=2)
680 if (polynomials(i, j) <= 2)
then
681 powers(polynomials(i, j)) = powers(polynomials(i, j)) + 1
687 if (powers(2) == 1 .and. powers(0) == der%dim - 1)
then
689 if (polynomials(i, j) == 2)
then
690 rhs(j) =
m_two*f(i, i)
696 if (powers(1) == 2 .and. powers(0) == der%dim - 2)
then
698 if (polynomials(i, j) == 1)
then
700 if (polynomials(k, j) == 1)
then
701 rhs(j) = f(i, k) + f(k, i)
715 integer,
intent(in) :: polynomials(:,:)
716 integer,
intent(in) :: dir
717 real(real64),
intent(out) :: rhs(:)
726 do j = 1, der%grad(dir)%stencil%size
729 if (k == dir .and. polynomials(k, j) /= 1) this_one = .false.
730 if (k /= dir .and. polynomials(k, j) /= 0) this_one = .false.
732 if (this_one) rhs(j) =
m_one
740 subroutine derivatives_make_discretization(namespace, dim, periodic_dim, mesh, masses, pol, rhs, nderiv, op, name, &
743 integer,
intent(in) :: dim
744 integer,
intent(in) :: periodic_dim
745 type(
mesh_t),
intent(in) :: mesh
746 real(real64),
intent(in) :: masses(:)
747 integer,
intent(in) :: pol(:,:)
748 integer,
intent(in) :: nderiv
749 real(real64),
contiguous,
intent(inout) :: rhs(:,:)
751 character(len=32),
intent(in) :: name
752 logical,
optional,
intent(in) :: verbose
754 integer :: p, p_max, i, j, k, pow_max
755 real(real64) :: x(dim)
756 real(real64),
allocatable :: mat(:,:), sol(:,:), powers(:,:)
757 logical :: transform_to_cartesian
761 safe_allocate(mat(1:op(1)%stencil%size, 1:op(1)%stencil%size))
762 safe_allocate(sol(1:op(1)%stencil%size, 1:nderiv))
765 message(1) =
'Info: Generating weights for finite-difference discretization of ' // trim(name)
769 select type (coord => mesh%coord_system)
771 transform_to_cartesian = .false.
773 transform_to_cartesian = .
true.
775 transform_to_cartesian = .
true.
777 transform_to_cartesian = .
true.
779 message(1) =
"Weight computation not implemented for the coordinate system chosen."
784 pow_max = maxval(pol)
785 safe_allocate(powers(1:dim, 0:pow_max))
790 if (op(1)%const_w) p_max = 1
796 do i = 1, op(1)%stencil%size
797 if (mesh%use_curvilinear)
then
798 x = mesh%x(p + op(1)%ri(i, op(1)%rimap(p)), :) - mesh%x(p, :)
800 x = real(op(1)%stencil%points(:, i), real64) *mesh%spacing
802 if (transform_to_cartesian)
then
803 x = mesh%coord_system%to_cartesian(x)
813 powers(:, k) = x*powers(:, k-1)
818 do j = 2, op(1)%stencil%size
819 mat(j, i) = powers(1, pol(1, j))
821 mat(j, i) = mat(j, i)*powers(k, pol(k, j))
833 op(i)%w(:, p) = sol(:, i)
850 safe_deallocate_a(mat)
851 safe_deallocate_a(sol)
852 safe_deallocate_a(powers)
864 overlap = this%comm_method /= blocking
875 class(
space_t),
intent(in) :: space
876 character(len=32),
intent(in) :: name
877 integer,
intent(in) :: order
879 integer,
allocatable :: polynomials(:,:)
880 real(real64),
allocatable :: rhs(:,:)
885 if (.not. this%mesh%coord_system%orthogonal)
then
891 call nl_operator_build(space, this%mesh, op(1), this%mesh%np, const_w = .not. this%mesh%use_curvilinear)
894 safe_allocate(polynomials(1:this%dim, 1:op(1)%stencil%size))
895 safe_allocate(rhs(1:op(1)%stencil%size, 1))
896 if (.not. this%mesh%coord_system%orthogonal)
then
903 polynomials, rhs, 1, op(1:1), name)
904 safe_deallocate_a(polynomials)
905 safe_deallocate_a(rhs)
926 logical :: mask(1:this%mesh%np)
927 integer :: ip, is, index
931 do ip = 1, this%mesh%np
933 do is = 1, this%lapl%stencil%size
937 if (index > this%mesh%np + this%mesh%pv%np_ghost)
then
951 real(real64) function derivatives_lapl_get_max_eigenvalue(this)
956 push_sub(derivatives_lapl_get_max_eigenvalue)
958 derivatives_lapl_get_max_eigenvalue =
m_zero
959 if ((this%stencil_type == der_star .or. this%stencil_type ==
der_stargeneral) &
960 .and. .not. this%mesh%use_curvilinear)
then
962 do i = 1, this%lapl%stencil%size
963 derivatives_lapl_get_max_eigenvalue = derivatives_lapl_get_max_eigenvalue + &
964 (-1)**maxval(abs(this%lapl%stencil%points(:, i)))*this%lapl%w(i, 1)
966 derivatives_lapl_get_max_eigenvalue = abs(derivatives_lapl_get_max_eigenvalue)
970 derivatives_lapl_get_max_eigenvalue = derivatives_lapl_get_max_eigenvalue + &
971 m_pi**2/this%mesh%spacing(i)**2
975 pop_sub(derivatives_lapl_get_max_eigenvalue)
981#include "derivatives_inc.F90"
984#include "complex.F90"
985#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)
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
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)
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)
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.