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>
7: program main
8: #include <petsc/finclude/petscvec.h>
9: use petscvec
10: implicit none
12: PetscErrorCode :: ierr
13: PetscMPIInt :: rank,size
14: PetscInt :: rstart,rend,i,k,N
15: PetscInt, parameter :: numPoints=1000000
16: PetscScalar :: dummy
17: PetscScalar, parameter :: h=1.0/numPoints
18: PetscScalar, pointer, dimension(:) :: xarray
19: PetscScalar :: myResult = 0
20: Vec x,xend
21: character(len=PETSC_MAX_PATH_LEN) :: output
22: PetscInt,parameter :: one = 1
24: PetscCallA(PetscInitialize(ierr))
26: PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD,rank,ierr))
27: PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD,size,ierr))
29: ! Create a parallel vector.
30: ! Here we set up our x vector which will be given values below.
31: ! The xend vector is a dummy vector to find the value of the
32: ! elements at the endpoints for use in the trapezoid rule.
34: PetscCallA(VecCreate(PETSC_COMM_WORLD,x,ierr))
35: PetscCallA(VecSetSizes(x,PETSC_DECIDE,numPoints,ierr))
36: PetscCallA(VecSetFromOptions(x,ierr))
37: PetscCallA(VecGetSize(x,N,ierr))
38: PetscCallA(VecSet(x,myResult,ierr))
39: PetscCallA(VecDuplicate(x,xend,ierr))
40: myResult = 0.5
41: if (rank==0) then
42: i = 0
43: PetscCallA(VecSetValues(xend,one,[i],[myResult],INSERT_VALUES,ierr))
44: endif
46: if (rank == size-1) then
47: i = N-1
48: PetscCallA(VecSetValues(xend,one,[i],[myResult],INSERT_VALUES,ierr))
49: endif
51: ! Assemble vector, using the 2-step process:
52: ! VecAssemblyBegin(), VecAssemblyEnd()
53: ! Computations can be done while messages are in transition
54: ! by placing code between these two statements.
56: PetscCallA(VecAssemblyBegin(xend,ierr))
57: PetscCallA(VecAssemblyEnd(xend,ierr))
59: ! Set the x vector elements.
60: ! i*h will return 0 for i=0 and 1 for i=N-1.
61: ! The function evaluated (2x/(1+x^2)) is defined above.
62: ! Each evaluation is put into the local array of the vector without message passing.
64: PetscCallA(VecGetOwnershipRange(x,rstart,rend,ierr))
65: PetscCallA(VecGetArrayF90(x,xarray,ierr))
66: k = 1
67: do i=rstart,rend-1
68: xarray(k) = real(i)*h
69: xarray(k) = func(xarray(k))
70: k = k+1
71: end do
72: PetscCallA(VecRestoreArrayF90(x,xarray,ierr))
74: ! Evaluates the integral. First the sum of all the points is taken.
75: ! That result is multiplied by the step size for the trapezoid rule.
76: ! Then half the value at each endpoint is subtracted,
77: ! this is part of the composite trapezoid rule.
79: PetscCallA(VecSum(x,myResult,ierr))
80: myResult = myResult*h
81: PetscCallA(VecDot(x,xend,dummy,ierr))
82: myResult = myResult-h*dummy
84: !Return the value of the integral.
86: write(output,'(a,f9.6,a)') 'ln(2) is',real(myResult),'\n' ! PetscScalar might be complex
87: PetscCallA(PetscPrintf(PETSC_COMM_WORLD,trim(output),ierr))
88: PetscCallA(VecDestroy(x,ierr))
89: PetscCallA(VecDestroy(xend,ierr))
91: PetscCallA(PetscFinalize(ierr))
93: contains
95: function func(a)
96: #include <petsc/finclude/petscvec.h>
97: use petscvec
99: implicit none
100: PetscScalar :: func
101: PetscScalar,INTENT(IN) :: a
103: func = 2.0*a/(1.0+a*a)
105: end function func
107: end program
109: !/*TEST
110: !
111: ! test:
112: ! nsize: 1
113: ! output_file: output/ex18_1.out
114: !
115: ! test:
116: ! nsize: 2
117: ! suffix: 2
118: ! output_file: output/ex18_1.out
119: !
120: !TEST*/