Actual source code: ex1f.F90

  1: !    Description: A star forest is a simple tree with one root and zero or more leaves.
  2: !    Many common communication patterns can be expressed as updates of rootdata using leafdata and vice-versa.
  3: !     This example creates a star forest, communicates values using the graph  views the graph, then destroys it.
  4: !
  5: !     This is a copy of ex1.c but currently only tests the broadcast operation

  7:       program main
  8: #include <petsc/finclude/petscvec.h>
  9:       use petscmpi  ! or mpi or mpi_f08
 10:       use petscvec
 11:       implicit none

 13:       PetscErrorCode                ierr
 14:       PetscInt                      i,nroots,nrootsalloc,nleaves,nleavesalloc,mine(6),stride
 15:       type(PetscSFNode)             remote(6)
 16:       PetscMPIInt                   rank,size
 17:       PetscSF                       sf
 18:       PetscInt                      rootdata(6),leafdata(6)

 20: ! used with PetscSFGetGraph()
 21:       type(PetscSFNode), pointer :: gremote(:)
 22:       PetscInt, pointer ::          gmine(:)
 23:       PetscInt                      gnroots,gnleaves;

 25:       PetscInt                      niranks,nranks
 26:       PetscMPIInt, pointer ::       iranks(:), ranks(:)
 27:       PetscInt, pointer ::          ioffset(:),irootloc(:),roffset(:),rmine(:),rremote(:)

 29:       PetscCallA(PetscInitialize(ierr))
 30:       stride = 2
 31:       PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD,rank,ierr))
 32:       PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD,size,ierr))

 34:       if (rank == 0) then
 35:          nroots = 3
 36:       else
 37:          nroots = 2
 38:       endif
 39:       nrootsalloc  = nroots * stride;
 40:       if (rank > 0) then
 41:          nleaves = 3
 42:       else
 43:          nleaves = 2
 44:       endif
 45:       nleavesalloc = nleaves * stride
 46:       if (stride > 1) then
 47:          do i=1,nleaves
 48:             mine(i) = stride * (i-1)
 49:          enddo
 50:       endif

 52: ! Left periodic neighbor
 53:       remote(1)%rank  = modulo(rank+size-1,size)
 54:       remote(1)%index = 1 * stride
 55: ! Right periodic neighbor
 56:       remote(2)%rank  = modulo(rank+1,size)
 57:       remote(2)%index = 0 * stride
 58:       if (rank > 0) then !               All processes reference rank 0, index
 59:          remote(3)%rank  = 0
 60:          remote(3)%index = 2 * stride
 61:       endif

 63: !  Create a star forest for communication
 64:       PetscCallA(PetscSFCreate(PETSC_COMM_WORLD,sf,ierr))
 65:       PetscCallA(PetscSFSetFromOptions(sf,ierr))
 66:       PetscCallA(PetscSFSetGraph(sf,nrootsalloc,nleaves,mine,PETSC_COPY_VALUES,remote,PETSC_COPY_VALUES,ierr))
 67:       PetscCallA(PetscSFSetUp(sf,ierr))

 69: !   View graph, mostly useful for debugging purposes.
 70:       PetscCallA(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO_DETAIL,ierr))
 71:       PetscCallA(PetscSFView(sf,PETSC_VIEWER_STDOUT_WORLD,ierr))
 72:       PetscCallA(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD,ierr))

 74: !   Allocate space for send and receive buffers. This example communicates PetscInt, but other types, including
 75: !     * user-defined structures, could also be used.
 76: !     Set rootdata buffer to be broadcast
 77:       do i=1,nrootsalloc
 78:          rootdata(i) = -1
 79:       enddo
 80:       do i=1,nroots
 81:          rootdata(1 + (i-1)*stride) = 100*(rank+1) + i - 1
 82:       enddo

 84: !     Initialize local buffer, these values are never used.
 85:       do i=1,nleavesalloc
 86:          leafdata(i) = -1
 87:       enddo

 89: !     Broadcast entries from rootdata to leafdata. Computation or other communication can be performed between the begin and end calls.
 90:       PetscCallA(PetscSFBcastBegin(sf,MPIU_INTEGER,rootdata,leafdata,MPI_REPLACE,ierr))
 91:       PetscCallA(PetscSFBcastEnd(sf,MPIU_INTEGER,rootdata,leafdata,MPI_REPLACE,ierr))
 92:       PetscCallA(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,'## Bcast Rootdata\n',ierr))
 93:       PetscCallA(PetscIntView(nrootsalloc,rootdata,PETSC_VIEWER_STDOUT_WORLD,ierr))
 94:       PetscCallA(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,'## Bcast Leafdata\n',ierr))
 95:       PetscCallA(PetscIntView(nleavesalloc,leafdata,PETSC_VIEWER_STDOUT_WORLD,ierr))

 97: !     Reduce entries from leafdata to rootdata. Computation or other communication can be performed between the begin and end calls.
 98:       PetscCallA(PetscSFReduceBegin(sf,MPIU_INTEGER,leafdata,rootdata,MPI_SUM,ierr))
 99:       PetscCallA(PetscSFReduceEnd(sf,MPIU_INTEGER,leafdata,rootdata,MPI_SUM,ierr))
100:       PetscCallA(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,'## Reduce Leafdata\n',ierr))
101:       PetscCallA(PetscIntView(nleavesalloc,leafdata,PETSC_VIEWER_STDOUT_WORLD,ierr))
102:       PetscCallA(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,'## Reduce Rootdata\n',ierr))
103:       PetscCallA(PetscIntView(nrootsalloc,rootdata,PETSC_VIEWER_STDOUT_WORLD,ierr))

105:       PetscCallA(PetscSFGetGraph(sf,gnroots,gnleaves,gmine,gremote,ierr))
106:       PetscCheckA(gnleaves .eq. nleaves,PETSC_COMM_WORLD,PETSC_ERR_PLIB,'nleaves returned from PetscSFGetGraph() does not match that set with PetscSFSetGraph()')
107:       do i=1,nleaves
108:         PetscCheckA(gmine(i) .eq. mine(i),PETSC_COMM_WORLD,PETSC_ERR_PLIB,'Root from PetscSFGetGraph() does not match that set with PetscSFSetGraph()')
109:       enddo
110:       do i=1,nleaves
111:        PetscCheckA(gremote(i)%index .eq. remote(i)%index,PETSC_COMM_WORLD,PETSC_ERR_PLIB,'Leaf from PetscSFGetGraph() does not match that set with PetscSFSetGraph()')
112:       enddo

114:       deallocate(gremote)

116: ! Test PetscSFGet{Leaf,Root}Ranks
117:       PetscCallA(PetscSFGetLeafRanks(sf,niranks,iranks,ioffset,irootloc,ierr))
118:       PetscCallA(PetscSFGetRootRanks(sf,nranks,ranks,roffset,rmine,rremote,ierr))

120: !    Clean storage for star forest.
121:       PetscCallA(PetscSFDestroy(sf,ierr))

123: !  Create a star forest with continuous leaves and hence no buffer
124:       PetscCallA(PetscSFCreate(PETSC_COMM_WORLD,sf,ierr))
125:       PetscCallA(PetscSFSetFromOptions(sf,ierr))
126:       PetscCallA(PetscSFSetGraph(sf,nrootsalloc,nleaves,PETSC_NULL_INTEGER,PETSC_COPY_VALUES,remote,PETSC_COPY_VALUES,ierr))
127:       PetscCallA(PetscSFSetUp(sf,ierr))

129: !   View graph, mostly useful for debugging purposes.
130:       PetscCallA(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO_DETAIL,ierr))
131:       PetscCallA(PetscSFView(sf,PETSC_VIEWER_STDOUT_WORLD,ierr))
132:       PetscCallA(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD,ierr))

134:       PetscCallA(PetscSFGetGraph(sf,gnroots,gnleaves,gmine,gremote,ierr))
135:       PetscCheckA(loc(gmine) .eq. loc(PETSC_NULL_INTEGER),PETSC_COMM_WORLD,PETSC_ERR_PLIB,'Leaves from PetscSFGetGraph() not null as expected')
136:       deallocate(gremote)
137:       PetscCallA(PetscSFDestroy(sf,ierr))
138:       PetscCallA(PetscFinalize(ierr))
139:   end

141: !/*TEST
142: !  build:
143: !    requires: defined(PETSC_HAVE_FORTRAN_TYPE_STAR)
144: !
145: !  test:
146: !    nsize: 3
147: !
148: !TEST*/