42 use,
intrinsic :: iso_fortran_env
107 integer,
parameter :: &
108 DER_BC_ZERO_F = 0, & !< function is zero at the boundaries
112 integer,
parameter,
public :: &
119 integer,
parameter :: &
127 type(boundaries_t) :: boundaries
128 type(mesh_t),
pointer :: mesh => null()
130 integer :: periodic_dim = 0
132 integer :: stencil_type = 0
135 logical,
private :: stencil_primitive_coordinates
137 class(coordinate_system_t),
private,
pointer :: coord_system
138 logical :: remove_zero_weight_points
140 real(real64),
allocatable :: masses(:)
144 real(real64),
private :: lapl_cutoff =
m_zero
146 type(nl_operator_t),
allocatable,
private :: op(:)
148 type(nl_operator_t),
pointer :: lapl => null()
149 type(nl_operator_t),
pointer :: grad(:) => null()
151 integer,
allocatable :: n_ghost(:)
153 integer,
private :: comm_method = 0
155 type(derivatives_t),
pointer :: finer => null()
156 type(derivatives_t),
pointer :: coarser => null()
157 type(transfer_table_t),
pointer :: to_finer => null()
158 type(transfer_table_t),
pointer :: to_coarser => null()
165 type(par_vec_handle_batch_t) :: pv_h
167 type(derivatives_t),
pointer :: der
168 type(nl_operator_t),
pointer :: op
169 type(batch_t),
pointer :: ff
170 type(batch_t),
pointer :: opff
171 logical :: ghost_update
172 logical :: factor_present
173 real(real64) :: factor
176 type(accel_kernel_t) :: kernel_uvw_xyz, kernel_dcurl, kernel_zcurl
182 type(derivatives_t),
target,
intent(inout) :: der
183 type(namespace_t),
intent(in) :: namespace
184 class(space_t),
intent(in) :: space
185 class(coordinate_system_t),
target,
intent(in) :: coord_system
186 integer,
optional,
intent(in) :: order
189 integer :: default_stencil
190 logical :: stencil_primitive_coordinates
191 character(len=128) :: kernel_name
196 assert(.not. coord_system%local_basis .or. coord_system%orthogonal)
200 der%periodic_dim = space%periodic_dim
201 der%coord_system => coord_system
226 default_stencil = der_star
230 call parse_variable(namespace,
'DerivativesStencil', default_stencil, der%stencil_type)
240 if (.not. coord_system%orthogonal .and. &
243 'stencil_star and stencil_variational cannot be used for non-orthogonal cells. Use stencil_stargeneral.')
277 if (
present(order))
then
289 call parse_variable(namespace,
'DerivativesRemoveZeroWeightPoints', .
true., der%remove_zero_weight_points)
330 stencil_primitive_coordinates = .not. coord_system%local_basis
331 call parse_variable(namespace,
'StencilPrimitiveCoordinates', stencil_primitive_coordinates, der%stencil_primitive_coordinates)
334 safe_allocate(der%masses(1:space%dim))
338 safe_allocate(der%op(1:der%dim + 1))
340 der%lapl => der%op(der%dim + 1)
346 safe_allocate(der%n_ghost(1:der%dim))
349 der%n_ghost(idir) = maxval(abs(der%lapl%stencil%points(idir, :)))
354 nullify(der%to_coarser)
355 nullify(der%to_finer)
359 select type (coord_system)
363 if (der%dim > 3)
then
364 message(1) =
"Calculation of derivatives on the GPU with dimension > 3 are only implemented for Cartesian coordinates."
368 write(kernel_name,
'(a,i1,a)')
'uvw_to_xyz<double, Dim::D', der%dim, &
369 repeat(
', double*, int, double*, int', der%dim)//
'>'
389 assert(
allocated(der%op))
391 do idim = 1, der%dim+1
395 safe_deallocate_a(der%masses)
397 safe_deallocate_a(der%n_ghost)
399 safe_deallocate_a(der%op)
400 nullify(der%lapl, der%grad)
404 nullify(der%to_coarser)
405 nullify(der%to_finer)
417 class(
space_t),
intent(in) :: space
419 character(len=80),
optional,
intent(in) :: name
420 integer,
optional,
intent(in) :: order
422 character(len=80) :: name_
434 select case (der%stencil_type)
454 real(real64),
contiguous,
intent(out) :: lapl(:)
458 assert(ubound(lapl, dim=1) >= der%mesh%np)
474 character :: dir_label
478 assert(
associated(der%grad))
488 select case (der%stencil_type)
551 subroutine derivatives_build(der, namespace, space, mesh, qvector, regenerate, verbose)
554 class(
space_t),
intent(in) :: space
555 class(
mesh_t),
target,
intent(in) :: mesh
556 real(real64),
contiguous,
optional,
intent(in) :: qvector(:)
558 logical,
optional,
intent(in) :: regenerate
559 logical,
optional,
intent(in) :: verbose
563 integer :: np_zero_bc
571 assert(
allocated(der%op))
572 assert(der%stencil_type >= der_star .and. der%stencil_type <=
der_stargeneral)
573 assert(.not.(der%stencil_type ==
der_variational .and. mesh%use_curvilinear))
580 if (mesh%use_curvilinear) const_w_ = .false.
587 safe_deallocate_a(der%op(i)%w)
595 call nl_operator_build(space, mesh, der%op(i), der%mesh%np, const_w = const_w_, &
596 regenerate=regenerate)
600 assert(np_zero_bc > mesh%np .and. np_zero_bc <= mesh%np_part)
602 select case (der%stencil_type)
605 do i = 1, der%dim + 1
636 subroutine stencil_pol_grad(stencil_type, dim, direction, order, polynomials)
637 integer,
intent(in) :: stencil_type
638 integer,
intent(in) :: dim
639 integer,
intent(in) :: direction
640 integer,
intent(in) :: order
641 integer,
contiguous,
intent(inout) :: polynomials(:, :)
643 select case (stencil_type)
656 integer,
intent(in) :: stencil_type
658 integer,
intent(in) :: dim
659 integer,
intent(in) :: order
660 integer,
contiguous,
intent(inout) :: polynomials(:, :)
662 select case (stencil_type)
677 subroutine get_rhs_lapl(coord_system, polynomials, chi, rhs, stencil_primitive_coordinates)
679 integer,
contiguous,
intent(in) :: polynomials(:,:)
680 real(real64),
contiguous,
intent(in) :: chi(:)
681 real(real64),
contiguous,
intent(out) :: rhs(:)
682 logical,
intent(in) :: stencil_primitive_coordinates
684 integer :: i, j, k, dim
685 real(real64) :: metric_inverse(1:size(polynomials, dim=1), 1:size(polynomials, dim=1))
686 real(real64) :: hessian_trace(1:size(polynomials, dim=1))
687 integer :: powers(0:2)
691 dim =
size(polynomials, dim=1)
693 if (stencil_primitive_coordinates)
then
695 metric_inverse = coord_system%metric_inverse(chi)
696 hessian_trace = coord_system%trace_hessian(chi)
701 metric_inverse(i, i) =
m_one
708 do j = 1,
size(polynomials, dim=2)
712 if (polynomials(i, j) <= 2)
then
713 powers(polynomials(i, j)) = powers(polynomials(i, j)) + 1
719 if (powers(2) == 1 .and. powers(0) == dim - 1)
then
721 if (polynomials(i, j) == 2)
then
722 rhs(j) =
m_two*metric_inverse(i, i)
728 if (powers(1) == 2 .and. powers(0) == dim - 2)
then
730 if (polynomials(i, j) == 1)
then
732 if (polynomials(k, j) == 1)
then
733 rhs(j) = metric_inverse(i, k) + metric_inverse(k, i)
742 if (powers(1) == 1 .and. powers(0) == dim - 1)
then
744 if (polynomials(i, j) == 1)
then
745 rhs(j) = hessian_trace(i)
756 integer,
contiguous,
intent(in) :: polynomials(:,:)
757 integer,
intent(in) :: dir
758 real(real64),
contiguous,
intent(out) :: rhs(:)
765 dim =
size(polynomials, dim=1)
769 do j = 1,
size(polynomials, dim=2)
772 if (k == dir .and. polynomials(k, j) /= 1) this_one = .false.
773 if (k /= dir .and. polynomials(k, j) /= 0) this_one = .false.
775 if (this_one) rhs(j) =
m_one
784 space, name, verbose, order)
787 integer,
intent(in) :: nderiv
788 integer,
intent(in) :: ideriv
790 type(
space_t),
intent(in) :: space
791 character(len=80),
optional,
intent(in) :: name
792 logical,
optional,
intent(in) :: verbose
793 integer,
optional,
intent(in) :: order
795 integer :: p, p_max, i, j, k, pow_max, order_
796 real(real64) :: x(der%dim)
797 real(real64),
allocatable :: mat(:,:), sol(:,:), powers(:,:)
798 integer,
allocatable :: pol(:,:)
799 real(real64),
allocatable :: rhs(:,:)
800 character(len=80) :: name_
806 safe_allocate(rhs(1:op(1)%stencil%size, nderiv))
807 safe_allocate(pol(1:der%dim, 1:op(1)%stencil%size))
809 if (nderiv == 1)
then
810 if (ideriv <= der%dim)
then
814 call stencil_pol_lapl(der%stencil_type, op(1)%stencil, der%dim, order_, pol)
817 else if (nderiv == der%dim)
then
824 message(1) =
"Error: derivatives_make_discretization can only be called with nderiv = 1 or der%dim."
828 safe_allocate(mat(1:op(1)%stencil%size, 1:op(1)%stencil%size))
829 safe_allocate(sol(1:op(1)%stencil%size, 1:nderiv))
833 message(1) =
'Info: Generating weights for finite-difference discretization of ' // trim(name_)
838 pow_max = maxval(pol)
839 safe_allocate(powers(1:der%dim, 0:pow_max))
844 if (op(1)%const_w) p_max = 1
849 if (nderiv == 1)
then
850 if (ideriv <= der%dim)
then
854 call get_rhs_lapl(der%mesh%coord_system, pol, der%mesh%chi(:, p), rhs(:,1), der%stencil_primitive_coordinates)
856 else if (nderiv == der%dim)
then
867 do i = 1, op(1)%stencil%size
868 if (ideriv <= der%dim)
then
870 x = real(op(1)%stencil%points(:, i), real64)*der%mesh%spacing
873 if (der%stencil_primitive_coordinates)
then
874 x = real(op(1)%stencil%points(:, i), real64)*der%mesh%spacing
876 x = der%mesh%x(:, p + op(1)%ri(i, op(1)%rimap(p))) - der%mesh%x(:, p)
881 x = x*
sqrt(der%masses)
886 powers(:, k) = x*powers(:, k-1)
891 do j = 2, op(1)%stencil%size
892 mat(j, i) = powers(1, pol(1, j))
894 mat(j, i) = mat(j, i)*powers(k, pol(k, j))
906 op(i)%w(:, p) = sol(:, i)
909 op(i)%w(op(i)%stencil%center, p) =
m_zero
916 if (der%remove_zero_weight_points)
then
920 if (op(i)%const_w)
then
933 safe_deallocate_a(mat)
934 safe_deallocate_a(sol)
935 safe_deallocate_a(powers)
936 safe_deallocate_a(pol)
937 safe_deallocate_a(rhs)
944 logical function derivatives_overlap(this)
result(overlap)
947 push_sub(derivatives_overlap)
949 overlap = this%comm_method /= blocking
951 pop_sub(derivatives_overlap)
952 end function derivatives_overlap
960 class(
space_t),
intent(in) :: space
961 character(len=80),
intent(in) :: name
962 integer,
intent(in) :: order
967 call nl_operator_build(space, this%mesh, op(1), this%mesh%np, const_w = .not. this%mesh%use_curvilinear)
989 logical :: mask(1:this%mesh%np)
990 integer :: ip, is, index
994 do ip = 1, this%mesh%np
996 do is = 1, this%lapl%stencil%size
1000 if (index > this%mesh%np + this%mesh%pv%np_ghost)
then
1014 real(real64) function derivatives_lapl_get_max_eigenvalue(this)
1019 push_sub(derivatives_lapl_get_max_eigenvalue)
1021 derivatives_lapl_get_max_eigenvalue =
m_zero
1022 if ((this%stencil_type == der_star .or. this%stencil_type ==
der_stargeneral) &
1023 .and. .not. this%mesh%use_curvilinear)
then
1025 do i = 1, this%lapl%stencil%size
1026 derivatives_lapl_get_max_eigenvalue = derivatives_lapl_get_max_eigenvalue + &
1027 (-1)**maxval(abs(this%lapl%stencil%points(:, i)))*this%lapl%w(i, 1)
1029 derivatives_lapl_get_max_eigenvalue = abs(derivatives_lapl_get_max_eigenvalue)
1033 derivatives_lapl_get_max_eigenvalue = derivatives_lapl_get_max_eigenvalue + &
1034 m_pi**2/this%mesh%spacing(i)**2
1038 pop_sub(derivatives_lapl_get_max_eigenvalue)
1043 class(coordinate_system_t),
target,
intent(in) :: coord_system
1045 der%coord_system => coord_system
1050#include "derivatives_inc.F90"
1053#include "complex.F90"
1054#include "derivatives_inc.F90"
double sqrt(double __x) __attribute__((__nothrow__
subroutine, public accel_kernel_start_call(this, file_name, kernel_name, flags)
subroutine, public accel_kernel_build(this, file_name, kernel_name, flags)
Compile the program that contains a given kernel.
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 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 derivatives_make_discretization(namespace, der, nderiv, ideriv, op, space, name, verbose, order)
subroutine, public derivatives_build(der, namespace, space, mesh, qvector, regenerate, verbose)
build the derivatives object:
subroutine, public dderivatives_batch_grad(der, ffb, opffb, ghost_update, set_bc, to_cartesian, factor)
apply the gradient to a batch of mesh functions
subroutine stencil_pol_grad(stencil_type, dim, direction, order, polynomials)
subroutine stencil_pol_lapl(stencil_type, stencil, dim, order, polynomials)
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 get_rhs_lapl(coord_system, polynomials, chi, rhs, stencil_primitive_coordinates)
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 derivatives_get_stencil_lapl(der, lapl, space, coord_system, name, order)
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 zderivatives_batch_grad(der, ffb, opffb, ghost_update, set_bc, to_cartesian, factor)
apply the gradient to a batch of mesh functions
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, 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 dderivatives_batch_start(op, der, ff, opff, handle, ghost_update, set_bc, factor)
apply a non-local operator to a batch (1st part)
subroutine get_rhs_grad(polynomials, dir, rhs)
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,...
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, 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
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 derivates_set_coordinates_system(der, coord_system)
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 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, symm)
initialize an instance of a non-local operator by setting the label
subroutine, public nl_operator_build_symmetric_weights(op, max_size)
Builds (or rebuild) the necessary arrays for symmetric and antisymmetric stencils.
subroutine, public nl_operator_update_gpu_buffers(op)
subroutine, public nl_operator_output_weights(this)
subroutine, public nl_operator_end(op)
subroutine, public nl_operator_remove_zero_weight_points(op, space, mesh)
Removes the zero-weight points for constant weight stencils.
integer, parameter, public op_symmetric
subroutine, public nl_operator_build(space, mesh, op, np, const_w, regenerate)
Creates the nonlocal operators for the stencils used for finite differences.
integer pure function, public nl_operator_np_zero_bc(op)
integer, parameter, public op_antisymmetric
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.