Actual source code: ex13f90aux.F90

  1: module ex13f90auxmodule
  2: #include <petsc/finclude/petscdm.h>
  3: #include <petsc/finclude/petscdmda.h>
  4:   use petscdm
  5:   implicit none
  6: contains
  7:   !
  8:   ! A subroutine which returns the boundary conditions.
  9:   !
 10:   subroutine get_boundary_cond(b_x, b_y, b_z)
 11:     DMBoundaryType, intent(inout) :: b_x, b_y, b_z

 13:     ! Here you may set the BC types you want
 14:     b_x = DM_BOUNDARY_GHOSTED
 15:     b_y = DM_BOUNDARY_GHOSTED
 16:     b_z = DM_BOUNDARY_GHOSTED

 18:   end subroutine get_boundary_cond
 19:   !
 20:   ! A function which returns the RHS of the equation we are solving
 21:   !
 22:   function dfdt_vdp(t, dt, ib1, ibn, jb1, jbn, kb1, kbn, imax, jmax, kmax, n, f)
 23:     !
 24:     ! Right-hand side for the van der Pol oscillator.  Very simple system of two
 25:     ! ODEs.  See Iserles, eq (5.2).
 26:     !
 27:     PetscReal, intent(in) :: t, dt
 28:     PetscInt, intent(in) :: ib1, ibn, jb1, jbn, kb1, kbn, imax, jmax, kmax, n
 29:     PetscReal, dimension(n, ib1:ibn, jb1:jbn, kb1:kbn), intent(inout) :: f
 30:     PetscReal, dimension(n, imax, jmax, kmax) :: dfdt_vdp
 31:     PetscReal, parameter :: mu = 1.4, one = 1.0
 32:     !
 33:     dfdt_vdp(1, :, :, :) = f(2, 1, 1, 1)
 34:     dfdt_vdp(2, :, :, :) = mu*(one - f(1, 1, 1, 1)**2)*f(2, 1, 1, 1) - f(1, 1, 1, 1)
 35:   end function dfdt_vdp
 36:   !
 37:   ! The standard Forward Euler time-stepping method.
 38:   !
 39:   recursive subroutine forw_euler(t, dt, ib1, ibn, jb1, jbn, kb1, kbn, imax, jmax, kmax, neq, y, dfdt)
 40:     PetscReal, intent(in) :: t, dt
 41:     PetscInt, intent(in) :: ib1, ibn, jb1, jbn, kb1, kbn, imax, jmax, kmax, neq
 42:     PetscReal, dimension(neq, ib1:ibn, jb1:jbn, kb1:kbn), intent(inout) :: y
 43:     !
 44:     ! Define the right-hand side function
 45:     !
 46:     interface
 47:       function dfdt(t, dt, ib1, ibn, jb1, jbn, kb1, kbn, imax, jmax, kmax, n, f)
 48: #include <petsc/finclude/petscsys.h>
 49:         use petscsys
 50:         PetscReal, intent(in) :: t, dt
 51:         PetscInt, intent(in) :: ib1, ibn, jb1, jbn, kb1, kbn, imax, jmax, kmax, n
 52:         PetscReal, dimension(n, ib1:ibn, jb1:jbn, kb1:kbn), intent(inout) :: f
 53:         PetscReal, dimension(n, imax, jmax, kmax) :: dfdt
 54:       end function dfdt
 55:     end interface
 56:     !--------------------------------------------------------------------------
 57:     !
 58:     y(:, 1:imax, 1:jmax, 1:kmax) = y(:, 1:imax, 1:jmax, 1:kmax) + dt*dfdt(t, dt, ib1, ibn, jb1, jbn, kb1, kbn, imax, jmax, kmax, neq, y)
 59:   end subroutine forw_euler
 60:   !
 61:   ! The following 4 subroutines handle the mapping of coordinates. I'll explain
 62:   ! this in detail:
 63:   !    PETSc gives you local arrays which are indexed using the global indices.
 64:   ! This is probably handy in some cases, but when you are re-writing an
 65:   ! existing serial code and want to use DMDAs, you have tons of loops going
 66:   ! from 1 to imax etc. that you don't want to change.
 67:   !    These subroutines re-map the arrays so that all the local arrays go from
 68:   ! 1 to the (local) imax.
 69:   !
 70:   subroutine petsc_to_local(da, vec, array, f, dof, stw)
 71:     use petscdmda
 72:     DM                                                            :: da
 73:     Vec, intent(in)                                                :: vec
 74:     PetscReal, pointer                                            :: array(:, :, :, :)
 75:     PetscInt, intent(in)                                           :: dof, stw
 76:     PetscReal, intent(inout), dimension(:, 1 - stw:, 1 - stw:, 1 - stw:) :: f
 77:     PetscErrorCode                                                :: ierr
 78:     !
 79:     PetscCall(DMDAVecGetArray(da, vec, array, ierr))
 80:     call transform_petsc_us(array, f, stw)
 81:   end subroutine petsc_to_local
 82:   subroutine transform_petsc_us(array, f, stw)
 83:     !Note: this assumed shape-array is what does the "coordinate transformation"
 84:     PetscInt, intent(in)                                   :: stw
 85:     PetscReal, intent(in), dimension(:, 1 - stw:, 1 - stw:, 1 - stw:)  :: array
 86:     PetscReal, intent(inout), dimension(:, 1 - stw:, 1 - stw:, 1 - stw:) :: f
 87:     f(:, :, :, :) = array(:, :, :, :)
 88:   end subroutine transform_petsc_us
 89:   subroutine local_to_petsc(da, vec, array, f, dof, stw)
 90:     use petscdmda
 91:     DM                                                    :: da
 92:     Vec, intent(inout)                                     :: vec
 93:     PetscReal, pointer                                    :: array(:, :, :, :)
 94:     PetscInt, intent(in)                                    :: dof, stw
 95:     PetscReal, intent(inout), dimension(:, 1 - stw:, 1 - stw:, 1 - stw:)  :: f
 96:     PetscErrorCode                                        :: ierr
 97:     call transform_us_petsc(array, f, stw)
 98:     PetscCall(DMDAVecRestoreArray(da, vec, array, ierr))
 99:   end subroutine local_to_petsc
100:   subroutine transform_us_petsc(array, f, stw)
101:     !Note: this assumed shape-array is what does the "coordinate transformation"
102:     PetscInt, intent(in)                                     :: stw
103:     PetscReal, intent(inout), dimension(:, 1 - stw:, 1 - stw:, 1 - stw:) :: array
104:     PetscReal, intent(in), dimension(:, 1 - stw:, 1 - stw:, 1 - stw:)      :: f
105:     array(:, :, :, :) = f(:, :, :, :)
106:   end subroutine transform_us_petsc
107: end module ex13f90auxmodule