![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001
00002 program MigrateMesh
00003 implicit none
00004
00005 #include "moab/MOABConfig.h"
00006 #ifdef MOAB_HAVE_MPI
00007 # include "mpif.h"
00008 #else
00009 # error "enable parallel build"
00010 #endif
00011
00012 !#define NONOVERLAP
00013
00014 ! init the parallel partition
00015 integer ierr, sz, rank, i
00016 integer newComm
00017 integer gcomm, comm1, comm2
00018 integer pid1, pid2 ! this is for physics ids
00019 integer compid1, compid2 ! component ids are unique over all pes, and established in
00020 ! advance;
00021 integer nghlay ! number of ghost layers for loading
00022 integer groupTasks(9) ! run on at most 9 processes
00023 integer startG1, startG2, endG1, endG2 ! start and end for group tasks, for creation
00024 integer sizeG1, sizeG2 ! size of the group that gets created
00025 character*10 appname
00026 character*132 readopts
00027 character*132 filename
00028 character*132 outfile
00029 character*132 wopts
00030 integer allgroup, group1, group2 ! Corresponding to MPI_Group in C
00031 integer tagcomm1, tagcomm2
00032 integer iMOAB_InitializeFortran, iMOAB_RegisterFortranApplication
00033 integer iMOAB_LoadMesh, iMOAB_SendMesh, iMOAB_ReceiveMesh, iMOAB_WriteMesh
00034 integer iMOAB_FreeSenderBuffers
00035 integer iMOAB_DeregisterApplication, iMOAB_Finalize
00036 integer repart_scheme , context_id
00037
00038 call MPI_INIT(ierr)
00039 call MPI_Comm_dup(MPI_COMM_WORLD, gcomm, ierr)
00040 call MPI_COMM_SIZE(gcomm, sz, ierr)
00041 call MPI_COMM_RANK(gcomm, rank, ierr)
00042 if (rank .eq. 0) print *, "size:", sz
00043 call errorout(ierr, 'cannot get rank' )
00044 if ( (0 .eq. rank) .and. (sz>9) ) then
00045 print *, "size is " , sz, ". run on at most 9 tasks "
00046 call exit(1)
00047 endif
00048 ! create 2 overlapping groups, for generality
00049 ! create communicators for each group;
00050 ! one group will represent the sender, the other group the receiver
00051 ! about one third of tasks will be on group 1 only, and one fourth will be on group 2 only
00052 ! about (1-1./3 -1./4) will be overlapping, these tasks will be common to both groups
00053 ! the mesh will be read on the sender comm, will be sent to receiver comm
00054
00055 ! create new MPI groups for processors 1/3*sz, 1/3*sz+1, ..., sz-1 (group 1) and 0, 1, .., 3/4*sz-1 (group 2)
00056
00057
00058 call MPI_COMM_GROUP (gcomm, allgroup, ierr)
00059 call errorout(ierr, 'cannot get world group' )
00060 ! first group, sz/3 to sz-1
00061 startG1 = sz/2
00062 endG1 = sz-1
00063 sizeG1 = endG1 - startG1 + 1
00064 ! used for new API in iMOAB, for tag migrate, release buffers
00065 context_id = -1
00066
00067 do i=1, sizeG1
00068 groupTasks (i) = startG1+i-1
00069 end do
00070
00071 call MPI_Group_incl(allgroup, sizeG1, groupTasks, group1, ierr)
00072 call errorout(ierr, 'cannot create group 1' )
00073
00074 ! second group, 0, 1, 3/4*sz
00075 startG2 = 0
00076 endG2 = 3*sz/4 -1
00077 if (endG2 <0) endG2 = 0 ! so it will work even for 1 task
00078 #ifdef NONOVERLAP
00079 endG2 = startG1-1
00080 #endif
00081 sizeG2 = endG2 - startG2 + 1
00082 do i=1, sizeG2
00083 groupTasks(i) = startG2+i-1
00084 enddo
00085
00086 call MPI_Group_incl(allgroup, sizeG2, groupTasks, group2, ierr)
00087 call errorout(ierr, 'cannot create group 2' )
00088
00089 if ( (0 .eq. rank) ) then
00090 print *, "group 1 tasks: ", (i, i=startG1, endG1)
00091 print *, "group 2 tasks: ", (i, i=startG2, endG2)
00092 endif
00093 ! now create both communicators
00094 ! when we are not on tasks in the communicator, the MPI_Comm created will be null
00095 tagcomm1 = 1
00096 call MPI_Comm_create_group(gcomm, group1, tagcomm1, comm1, ierr)
00097 call errorout(ierr, 'cannot create communicator 1' )
00098
00099 tagcomm2 = 2
00100 call MPI_Comm_create_group(gcomm, group2, tagcomm2, comm2, ierr)
00101 call errorout(ierr, 'cannot create communicator 2' )
00102
00103
00104 ierr = iMOAB_InitializeFortran()
00105
00106 repart_scheme = 0 ! this is for trivial partitioning
00107 #ifdef MOAB_HAVE_ZOLTAN
00108 repart_scheme = 1 ! use the graph partitioner in that case
00109 #endif
00110 ! give some dummy values to component ids, just to differentiate between them
00111 ! the par comm graph is unique between components
00112 compid1 = 4
00113 compid2 = 7
00114 call errorout(ierr, 'did not initialize fortran' )
00115 if (rank == 0) print *, "initialize iMOAB fortran applications"
00116
00117 if (comm1 /= MPI_COMM_NULL) then
00118 appname='phis1'//CHAR(0)
00119 ierr = iMOAB_RegisterFortranApplication(trim(appname), comm1, compid1, pid1)
00120 print *, ' register ', appname, " on rank ", rank, " pid1 ", pid1
00121 endif
00122 if (comm2 /= MPI_COMM_NULL) then
00123 appname = 'phis2'//CHAR(0)
00124 ierr = iMOAB_RegisterFortranApplication(trim(appname), comm2, compid2, pid2)
00125 print *, ' register ', appname, " on rank ", rank, " pid2 ", pid2
00126 endif
00127
00128
00129 if (comm1 /= MPI_COMM_NULL) then
00130 filename = 'spherecube.h5m'//CHAR(0)
00131 readopts = 'PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS'//CHAR(0)
00132 if (rank .eq. sz-2 ) print *, "loading " , trim(filename) , " with options " , trim(readopts)
00133 nghlay = 0
00134
00135 ierr = iMOAB_LoadMesh(pid1, trim(filename), trim(readopts), nghlay)
00136 if (rank .eq. sz-1 ) print *, "loaded in parallel ", trim(filename), " error: ", ierr
00137 ierr = iMOAB_SendMesh(pid1, gcomm, group2, compid2, repart_scheme); ! send to component 2
00138 call errorout(ierr, 'cannot send elements' )
00139 endif
00140
00141 if (comm2 /= MPI_COMM_NULL) then
00142 ierr = iMOAB_ReceiveMesh(pid2, gcomm, group1, compid1); ! receive from component 1
00143 call errorout(ierr, 'cannot receive elements' )
00144 endif
00145
00146 ! we can now free the sender buffers
00147 if (comm1 /= MPI_COMM_NULL) then
00148
00149 ierr = iMOAB_FreeSenderBuffers(pid1, context_id)
00150 endif
00151 call MPI_Barrier(gcomm, ierr)
00152 call errorout(ierr, 'cannot stop at barrier' )
00153
00154 if (comm2 /= MPI_COMM_NULL) then
00155 outfile = 'receivedMesh.h5m'//CHAR(0)
00156 wopts = 'PARALLEL=WRITE_PART;'//CHAR(0)
00157 ! write out the mesh file to disk
00158 ierr = iMOAB_WriteMesh(pid2, trim(outfile), trim(wopts))
00159 call errorout(ierr, 'cannot write received mesh' )
00160 endif
00161
00162
00163 if (comm2 /= MPI_COMM_NULL) then
00164 ierr = iMOAB_DeregisterApplication(pid2)
00165 call errorout(ierr, 'cannot deregister app 2 receiver' )
00166 endif
00167 if (comm1 /= MPI_COMM_NULL) then
00168 ierr = iMOAB_DeregisterApplication(pid1)
00169 call errorout(ierr, 'cannot deregister app 1 sender' )
00170 endif
00171
00172 ierr = iMOAB_Finalize()
00173 call errorout(ierr, 'did not finalize iMOAB' )
00174
00175 if (MPI_COMM_NULL /= comm1) call MPI_Comm_free(comm1, ierr)
00176 call errorout(ierr, 'did not free comm1' )
00177
00178 if (MPI_COMM_NULL /= comm2) call MPI_Comm_free(comm2, ierr)
00179 call errorout(ierr, 'did not free comm2' )
00180
00181 call MPI_Group_free(allgroup, ierr)
00182 call MPI_Group_free(group1, ierr)
00183 call MPI_Group_free(group2, ierr)
00184 call MPI_Comm_free(gcomm, ierr)
00185
00186 call MPI_Finalize(ierr)
00187 call errorout(ierr, 'did not finalize MPI' )
00188 contains
00189 SUBROUTINE errorout(ierr, message)
00190 integer ierr
00191 character*(*) message
00192 if (ierr.ne.0) then
00193 print *, message
00194 call exit (1)
00195 end if
00196 end
00197
00198 end program MigrateMesh