42 use,
intrinsic :: iso_fortran_env
118 integer,
parameter :: &
119 DER_BC_ZERO_F = 0, & !< function is zero at the boundaries
123 integer,
parameter,
public :: &
130 integer,
parameter :: &
138 type(boundaries_t) :: boundaries
139 type(mesh_t),
pointer :: mesh => null()
141 integer,
private :: periodic_dim = 0
143 integer :: stencil_type = 0
146 logical,
private :: stencil_primitive_coordinates
148 class(coordinate_system_t),
private,
pointer :: coord_system
149 logical :: remove_zero_weight_points
151 real(real64),
allocatable :: masses(:)
155 real(real64),
private :: lapl_cutoff =
m_zero
157 type(nl_operator_t),
allocatable,
private :: op(:)
159 type(nl_operator_t),
pointer :: lapl => null()
160 type(nl_operator_t),
pointer :: grad(:) => null()
162 integer,
allocatable :: n_ghost(:)
164 integer,
private :: comm_method = 0
166 type(derivatives_t),
pointer :: finer => null()
167 type(derivatives_t),
pointer :: coarser => null()
168 type(transfer_table_t),
pointer :: to_finer => null()
169 type(transfer_table_t),
pointer :: to_coarser => null()
176 type(par_vec_handle_batch_t) :: pv_h
178 type(derivatives_t),
pointer :: der
179 type(nl_operator_t),
pointer :: op
180 type(batch_t),
pointer :: ff
181 type(batch_t),
pointer :: opff
182 logical :: ghost_update
183 logical :: factor_present
184 real(real64) :: factor
187 type(accel_kernel_t) :: kernel_uvw_xyz, kernel_dcurl, kernel_zcurl
193 type(derivatives_t),
target,
intent(inout) :: der
194 type(namespace_t),
intent(in) :: namespace
195 class(space_t),
intent(in) :: space
196 class(coordinate_system_t),
target,
intent(in) :: coord_system
197 integer,
optional,
intent(in) :: order
200 integer :: default_stencil
201 character(len=40) :: flags
202 logical :: stencil_primitive_coordinates
207 assert(.not. coord_system%local_basis .or. coord_system%orthogonal)
211 der%periodic_dim = space%periodic_dim
212 der%coord_system => coord_system
237 default_stencil = der_star
241 call parse_variable(namespace,
'DerivativesStencil', default_stencil, der%stencil_type)
281 if (
present(order))
then
293 call parse_variable(namespace,
'DerivativesRemoveZeroWeightPoints', .
true., der%remove_zero_weight_points)
334 stencil_primitive_coordinates = .not. coord_system%local_basis
335 call parse_variable(namespace,
'StencilPrimitiveCoordinates', stencil_primitive_coordinates, der%stencil_primitive_coordinates)
338 safe_allocate(der%masses(1:space%dim))
342 safe_allocate(der%op(1:der%dim + 1))
344 der%lapl => der%op(der%dim + 1)
350 safe_allocate(der%n_ghost(1:der%dim))
353 der%n_ghost(idir) = maxval(abs(der%lapl%stencil%points(idir, :)))
358 nullify(der%to_coarser)
359 nullify(der%to_finer)
363 select type (coord_system)
367 if (der%dim > 3)
then
368 message(1) =
"Calculation of derivatives on the GPU with dimension > 3 are only implemented for Cartesian coordinates."
371 write(flags,
'(A,I1.1)')
' -DDIMENSION=', der%dim
391 assert(
allocated(der%op))
393 do idim = 1, der%dim+1
397 safe_deallocate_a(der%masses)
399 safe_deallocate_a(der%n_ghost)
401 safe_deallocate_a(der%op)
402 nullify(der%lapl, der%grad)
406 nullify(der%to_coarser)
407 nullify(der%to_finer)
419 class(
space_t),
intent(in) :: space
421 character(len=80),
optional,
intent(in) :: name
422 integer,
optional,
intent(in) :: order
424 character(len=80) :: name_
436 select case (der%stencil_type)
456 real(real64),
intent(out) :: lapl(:)
460 assert(ubound(lapl, dim=1) >= der%mesh%np)
476 character :: dir_label
480 assert(
associated(der%grad))
490 select case (der%stencil_type)
553 subroutine derivatives_build(der, namespace, space, mesh, qvector, regenerate, verbose)
556 class(
space_t),
intent(in) :: space
557 class(
mesh_t),
target,
intent(in) :: mesh
558 real(real64),
optional,
intent(in) :: qvector(:)
560 logical,
optional,
intent(in) :: regenerate
561 logical,
optional,
intent(in) :: verbose
565 integer :: np_zero_bc
573 assert(
allocated(der%op))
574 assert(der%stencil_type >= der_star .and. der%stencil_type <=
der_stargeneral)
575 assert(.not.(der%stencil_type ==
der_variational .and. mesh%use_curvilinear))
582 if (mesh%use_curvilinear) const_w_ = .false.
589 safe_deallocate_a(der%op(i)%w)
597 call nl_operator_build(space, mesh, der%op(i), der%mesh%np, const_w = const_w_, &
598 regenerate=regenerate)
602 assert(np_zero_bc > mesh%np .and. np_zero_bc <= mesh%np_part)
604 select case (der%stencil_type)
607 do i = 1, der%dim + 1
630 subroutine stencil_pol_grad(stencil_type, dim, direction, order, polynomials)
631 integer,
intent(in) :: stencil_type
632 integer,
intent(in) :: dim
633 integer,
intent(in) :: direction
634 integer,
intent(in) :: order
635 integer,
intent(inout) :: polynomials(:, :)
637 select case (stencil_type)
650 integer,
intent(in) :: stencil_type
652 integer,
intent(in) :: dim
653 integer,
intent(in) :: order
654 integer,
intent(inout) :: polynomials(:, :)
656 select case (stencil_type)
669 subroutine get_rhs_lapl(coord_system, polynomials, chi, rhs, stencil_primitive_coordinates)
671 integer,
intent(in) :: polynomials(:,:)
672 real(real64),
intent(in) :: chi(:)
673 real(real64),
intent(out) :: rhs(:)
674 logical,
intent(in) :: stencil_primitive_coordinates
676 integer :: i, j, k, dim
677 real(real64) :: metric_inverse(1:size(polynomials, dim=1), 1:size(polynomials, dim=1))
678 real(real64) :: hessian_trace(1:size(polynomials, dim=1))
679 integer :: powers(0:2)
683 dim =
size(polynomials, dim=1)
685 if (stencil_primitive_coordinates)
then
687 metric_inverse = coord_system%metric_inverse(chi)
688 hessian_trace = coord_system%trace_hessian(chi)
693 metric_inverse(i, i) =
m_one
700 do j = 1,
size(polynomials, dim=2)
704 if (polynomials(i, j) <= 2)
then
705 powers(polynomials(i, j)) = powers(polynomials(i, j)) + 1
711 if (powers(2) == 1 .and. powers(0) == dim - 1)
then
713 if (polynomials(i, j) == 2)
then
714 rhs(j) =
m_two*metric_inverse(i, i)
720 if (powers(1) == 2 .and. powers(0) == dim - 2)
then
722 if (polynomials(i, j) == 1)
then
724 if (polynomials(k, j) == 1)
then
725 rhs(j) = metric_inverse(i, k) + metric_inverse(k, i)
734 if (powers(1) == 1 .and. powers(0) == dim - 1)
then
736 if (polynomials(i, j) == 1)
then
737 rhs(j) = hessian_trace(i)
748 integer,
intent(in) :: polynomials(:,:)
749 integer,
intent(in) :: dir
750 real(real64),
intent(out) :: rhs(:)
757 dim =
size(polynomials, dim=1)
761 do j = 1,
size(polynomials, dim=2)
764 if (k == dir .and. polynomials(k, j) /= 1) this_one = .false.
765 if (k /= dir .and. polynomials(k, j) /= 0) this_one = .false.
767 if (this_one) rhs(j) =
m_one
776 space, name, verbose, order)
779 integer,
intent(in) :: nderiv
780 integer,
intent(in) :: ideriv
782 type(
space_t),
intent(in) :: space
783 character(len=80),
optional,
intent(in) :: name
784 logical,
optional,
intent(in) :: verbose
785 integer,
optional,
intent(in) :: order
787 integer :: p, p_max, i, j, k, pow_max, order_
788 real(real64) :: x(der%dim)
789 real(real64),
allocatable :: mat(:,:), sol(:,:), powers(:,:)
790 integer,
allocatable :: pol(:,:)
791 real(real64),
allocatable :: rhs(:,:)
792 character(len=80) :: name_
798 safe_allocate(rhs(1:op(1)%stencil%size, nderiv))
799 safe_allocate(pol(1:der%dim, 1:op(1)%stencil%size))
801 if (nderiv == 1)
then
802 if (ideriv <= der%dim)
then
806 call stencil_pol_lapl(der%stencil_type, op(1)%stencil, der%dim, order_, pol)
809 else if (nderiv == der%dim)
then
816 message(1) =
"Error: derivatives_make_discretization can only be called with nderiv = 1 or der%dim."
820 safe_allocate(mat(1:op(1)%stencil%size, 1:op(1)%stencil%size))
821 safe_allocate(sol(1:op(1)%stencil%size, 1:nderiv))
825 message(1) =
'Info: Generating weights for finite-difference discretization of ' // trim(name_)
830 pow_max = maxval(pol)
831 safe_allocate(powers(1:der%dim, 0:pow_max))
836 if (op(1)%const_w) p_max = 1
841 if (nderiv == 1)
then
842 if (ideriv <= der%dim)
then
846 call get_rhs_lapl(der%mesh%coord_system, pol, der%mesh%chi(:, p), rhs(:,1), der%stencil_primitive_coordinates)
848 else if (nderiv == der%dim)
then
859 do i = 1, op(1)%stencil%size
860 if (ideriv <= der%dim)
then
862 x = real(op(1)%stencil%points(:, i), real64)*der%mesh%spacing
865 if (der%stencil_primitive_coordinates)
then
866 x = real(op(1)%stencil%points(:, i), real64)*der%mesh%spacing
868 x = der%mesh%x(p + op(1)%ri(i, op(1)%rimap(p)), :) - der%mesh%x(p, :)
873 x = x*
sqrt(der%masses)
878 powers(:, k) = x*powers(:, k-1)
883 do j = 2, op(1)%stencil%size
884 mat(j, i) = powers(1, pol(1, j))
886 mat(j, i) = mat(j, i)*powers(k, pol(k, j))
898 op(i)%w(:, p) = sol(:, i)
904 if (der%remove_zero_weight_points)
then
918 safe_deallocate_a(mat)
919 safe_deallocate_a(sol)
920 safe_deallocate_a(powers)
921 safe_deallocate_a(pol)
922 safe_deallocate_a(rhs)
929 logical function derivatives_overlap(this)
result(overlap)
932 push_sub(derivatives_overlap)
934 overlap = this%comm_method /= blocking
936 pop_sub(derivatives_overlap)
937 end function derivatives_overlap
945 class(
space_t),
intent(in) :: space
946 character(len=80),
intent(in) :: name
947 integer,
intent(in) :: order
952 call nl_operator_build(space, this%mesh, op(1), this%mesh%np, const_w = .not. this%mesh%use_curvilinear)
974 logical :: mask(1:this%mesh%np)
975 integer :: ip, is, index
979 do ip = 1, this%mesh%np
981 do is = 1, this%lapl%stencil%size
985 if (index > this%mesh%np + this%mesh%pv%np_ghost)
then
999 real(real64) function derivatives_lapl_get_max_eigenvalue(this)
1004 push_sub(derivatives_lapl_get_max_eigenvalue)
1006 derivatives_lapl_get_max_eigenvalue =
m_zero
1007 if ((this%stencil_type == der_star .or. this%stencil_type ==
der_stargeneral) &
1008 .and. .not. this%mesh%use_curvilinear)
then
1010 do i = 1, this%lapl%stencil%size
1011 derivatives_lapl_get_max_eigenvalue = derivatives_lapl_get_max_eigenvalue + &
1012 (-1)**maxval(abs(this%lapl%stencil%points(:, i)))*this%lapl%w(i, 1)
1014 derivatives_lapl_get_max_eigenvalue = abs(derivatives_lapl_get_max_eigenvalue)
1018 derivatives_lapl_get_max_eigenvalue = derivatives_lapl_get_max_eigenvalue + &
1019 m_pi**2/this%mesh%spacing(i)**2
1023 pop_sub(derivatives_lapl_get_max_eigenvalue)
1028 class(coordinate_system_t),
target,
intent(in) :: coord_system
1030 der%coord_system => coord_system
1035#include "derivatives_inc.F90"
1038#include "complex.F90"
1039#include "derivatives_inc.F90"
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, 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
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 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 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_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.
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 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.