Actual source code: ex18f.F90

  1: ! Computes the integral of 2*x/(1+x^2) from x=0..1
  2: ! This is equal to the ln(2).

  4: ! Contributed by Mike McCourt <mccomic@iit.edu> and Nathan Johnston <johnnat@iit.edu>
  5: ! Fortran translation by Arko Bhattacharjee <a.bhattacharjee@mpie.de>
  6: #include <petsc/finclude/petscvec.h>
  7: program main
  8:   use petscvec
  9:   implicit none

 11:   PetscErrorCode :: ierr
 12:   PetscMPIInt :: rank, size
 13:   PetscInt   ::  rstart, rend, i, k, N
 14:   PetscInt, parameter   ::   numPoints = 1000000
 15:   PetscScalar  ::  dummy
 16:   PetscScalar, parameter  :: h = 1.0/numPoints
 17:   PetscScalar, pointer, dimension(:)  :: xarray
 18:   PetscScalar :: myResult = 0
 19:   Vec x, xend
 20:   character(len=PETSC_MAX_PATH_LEN) :: output
 21:   PetscInt, parameter :: one = 1

 23:   PetscCallA(PetscInitialize(ierr))

 25:   PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD, rank, ierr))
 26:   PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD, size, ierr))

 28:   ! Create a parallel vector.
 29:   ! Here we set up our x vector which will be given values below.
 30:   ! The xend vector is a dummy vector to find the value of the
 31:   ! elements at the endpoints for use in the trapezoid rule.

 33:   PetscCallA(VecCreate(PETSC_COMM_WORLD, x, ierr))
 34:   PetscCallA(VecSetSizes(x, PETSC_DECIDE, numPoints, ierr))
 35:   PetscCallA(VecSetFromOptions(x, ierr))
 36:   PetscCallA(VecGetSize(x, N, ierr))
 37:   PetscCallA(VecSet(x, myResult, ierr))
 38:   PetscCallA(VecDuplicate(x, xend, ierr))
 39:   myResult = 0.5
 40:   if (rank == 0) then
 41:     i = 0
 42:     PetscCallA(VecSetValues(xend, one, [i], [myResult], INSERT_VALUES, ierr))
 43:   end if

 45:   if (rank == size - 1) then
 46:     i = N - 1
 47:     PetscCallA(VecSetValues(xend, one, [i], [myResult], INSERT_VALUES, ierr))
 48:   end if

 50:   ! Assemble vector, using the 2-step process:
 51:   ! VecAssemblyBegin(), VecAssemblyEnd()
 52:   ! Computations can be done while messages are in transition
 53:   ! by placing code between these two statements.

 55:   PetscCallA(VecAssemblyBegin(xend, ierr))
 56:   PetscCallA(VecAssemblyEnd(xend, ierr))

 58:   ! Set the x vector elements.
 59:   ! i*h will return 0 for i=0 and 1 for i=N-1.
 60:   ! The function evaluated (2x/(1+x^2)) is defined above.
 61:   ! Each evaluation is put into the local array of the vector without message passing.

 63:   PetscCallA(VecGetOwnershipRange(x, rstart, rend, ierr))
 64:   PetscCallA(VecGetArray(x, xarray, ierr))
 65:   k = 1
 66:   do i = rstart, rend - 1
 67:     xarray(k) = real(i)*h
 68:     xarray(k) = func(xarray(k))
 69:     k = k + 1
 70:   end do
 71:   PetscCallA(VecRestoreArray(x, xarray, ierr))

 73:   ! Evaluates the integral.  First the sum of all the points is taken.
 74:   ! That result is multiplied by the step size for the trapezoid rule.
 75:   ! Then half the value at each endpoint is subtracted,
 76:   ! this is part of the composite trapezoid rule.

 78:   PetscCallA(VecSum(x, myResult, ierr))
 79:   myResult = myResult*h
 80:   PetscCallA(VecDot(x, xend, dummy, ierr))
 81:   myResult = myResult - h*dummy

 83:   !Return the value of the integral.

 85:   write (output, '(a,f9.6,a)') 'ln(2) is', real(myResult), '\n'           ! PetscScalar might be complex
 86:   PetscCallA(PetscPrintf(PETSC_COMM_WORLD, trim(output), ierr))
 87:   PetscCallA(VecDestroy(x, ierr))
 88:   PetscCallA(VecDestroy(xend, ierr))

 90:   PetscCallA(PetscFinalize(ierr))

 92: contains

 94:   function func(a)
 95:     use petscvec

 97:     implicit none
 98:     PetscScalar :: func
 99:     PetscScalar, intent(IN) :: a

101:     func = 2.0*a/(1.0 + a*a)

103:   end function func

105: end program

107: !/*TEST
108: !
109: !     test:
110: !       nsize: 1
111: !       output_file: output/ex18_1.out
112: !
113: !     test:
114: !       nsize: 2
115: !       suffix: 2
116: !       output_file: output/ex18_1.out
117: !
118: !TEST*/