Derivatives

Octopus use finite differences to evaluate derivatives, such as the Laplacian (kinetic energy). The derivative at a point of the mesh is a weighted sum over neighboring points. For instance, the general form for the Laplacian is: $$ \nabla^2f(n_xh,,n_yh) = \sum_i^n\sum_j^n\frac{c_{ij}}h,f(n_xh + ih,,n_yh+jh) $$ The coefficients $(c_{ij})$ depend on the mesh and number of points used and define the stencil.

The derivatives object contains operators for the gradient and the Laplacian, as well as information about the order and the stencil type, and information about boundaries:

  type derivatives_t
    ! Components are public by default
    type(boundaries_t)    :: boundaries       !< boundary conditions
    type(mesh_t), pointer :: mesh => NULL()   !< pointer to the underlying mesh
    integer               :: dim = 0          !< dimensionality of the space (space%dim)
    integer, private      :: periodic_dim = 0 !< Number of periodic dimensions of the space (space%periodic_dim)
    integer               :: order = 0        !< order of the discretization (value depends on stencil)
    integer               :: stencil_type = 0 !< type of discretization

    real(real64), allocatable    :: masses(:)        !< we can have different weights (masses) per space direction

    !> If the so-called variational discretization is used, this controls a
    !! possible filter on the Laplacian.
    real(real64), private :: lapl_cutoff = M_ZERO

    type(nl_operator_t), allocatable, private :: op(:)  !< op(1:conf%dim) => gradient
    !!                                                     op(conf%dim+1) => Laplacian
    type(nl_operator_t), pointer :: lapl => NULL()      !< these are just shortcuts for op
    type(nl_operator_t), pointer :: grad(:) => NULL()

    integer, allocatable         :: n_ghost(:)   !< ghost points to add in each dimension
!#if defined(HAVE_MPI)
    integer, private             :: comm_method = 0
!#endif
    type(derivatives_t),    pointer :: finer  => NULL()
    type(derivatives_t),    pointer :: coarser => NULL()
    type(transfer_table_t), pointer :: to_finer => NULL()
    type(transfer_table_t), pointer :: to_coarser => NULL()
  end type derivatives_t

The derivative operators themselves are represented as non-local operators:

  type nl_operator_t
    private
    type(stencil_t),   public :: stencil
    type(mesh_t), pointer     :: mesh => NULL()  !< pointer to the underlying mesh
    integer,      allocatable :: nn(:)           !< the size of the stencil at each point (for curvilinear coordinates)
    integer,           public :: np = 0          !< number of points in mesh
    ! When running in parallel mode, the next three arrays are unique on each node.
    real(real64),   allocatable, public :: w(:,:)        !< weights. Unique on each parallel process.

    logical,          public :: const_w = .true.   !< are the weights independent of index i

    type(accel_mem_t), public :: buff_weights      !< buffer with constant weights
    type(accel_mem_t), public :: buff_half_weights !< buffer with weights multiplied by -1/2

    character(len=40) :: label

    !> the compressed index of grid points
    integer, public :: nri = 0
    integer, allocatable, public :: ri(:,:)
    integer, allocatable, public :: rimap(:)
    integer, allocatable, public :: rimap_inv(:)

    integer                   :: ninner = 0
    integer                   :: nouter = 0

    type(nl_operator_index_t) :: inner
    type(nl_operator_index_t) :: outer

    type(accel_kernel_t) :: kernel
    type(accel_mem_t) :: buff_imin
    type(accel_mem_t) :: buff_imax
    type(accel_mem_t) :: buff_ri
    type(accel_mem_t) :: buff_map
    type(accel_mem_t) :: buff_all
    type(accel_mem_t) :: buff_inner
    type(accel_mem_t) :: buff_outer
    type(accel_mem_t) :: buff_stencil
    type(accel_mem_t) :: buff_ip_to_xyz
    type(accel_mem_t) :: buff_xyz_to_ip

    ! For multigrid solvers
    type(nl_operator_t), public, pointer :: coarser => NULL()

  end type nl_operator_t
  type stencil_t
    ! Components are public by default
    integer, private     :: dim           !< spatial dimension
    integer              :: center        !< index to the central point of the stencil
    integer              :: size          !< size (number of points)
    integer, allocatable :: points(:, :)  !< list of points in spatial index notation (1:dim, 1:size)

    ! The stargeneral arms
    type(stargeneral_arms_t) :: stargeneral
  end type stencil_t
  type stargeneral_arms_t
    ! Components are public by default
    integer          :: arms(1:3,1:3) = reshape([0,0,0,0,0,0,0,0,0], (/3, 3/))
    integer          :: narms = 0
  end type stargeneral_arms_t