Exercise_2/0000755€í4H€L¨x 0000000000011462037107014644 5ustar tcluneNDC\domain usersExercise_2/2-A/0000755€í4H€L¨x 0000000000011462041100015147 5ustar tcluneNDC\domain usersExercise_2/2-A/driver.F900000644€í4H€L¨x 0000000153111462030443016732 0ustar tcluneNDC\domain usersprogram main use pFUnit use testHalo_mod implicit none type (TestSuite_type) :: suite type (TestResult_type) :: result character(len=100) :: summary_statement call pFUnit_init() ! Build suite from test procedures: suite = TestSuite('Halo tests') call add(suite, MpiTestCase('testFillHaloInterior', testFillHaloInterior, numProcesses=1)) call add(suite, MpiTestCase('testFillHaloInterior', testFillHaloInterior, numProcesses=2)) call add(suite, MpiTestCase('testFillHaloInterior', testFillHaloInterior, numProcesses=3)) ! Run the tests and accumulate the results in "result" result = newTestResult(mode=MODE_USE_STDOUT) call Run(suite, result) if (amRoot()) then summary_statement=Summary(result) print*,' ' print*,trim(summary_statement) end if call pFUnit_finalize() end program main Exercise_2/2-A/GNUmakefile0000644€í4H€L¨x 0000000154711462030030017230 0ustar tcluneNDC\domain users# Check for the PFUNIT environment variable ifndef PFUNIT $(error The environment variable "PFUNIT" must be given a value which is the \ path for the installation of pFUnit.) endif # What is the name of the F90 compiler F90 ?= ifort MPIF90 ?= mpif90 PFUNIT_LIBDIR ?=$(PFUNIT)/lib PFUNIT_INCDIR ?=$(PFUNIT)/include PFUNIT_MODDIR ?=$(PFUNIT)/mod PFUNIT_BINDIR ?=$(PFUNIT)/bin F90FLAGS +=-I$(PFUNIT_MODDIR) LDFLAGS +=-L$(PFUNIT_LIBDIR) -lpfunit F90_SRC = $(wildcard *.F90) F90_OBJ = $(F90_SRC:.F90=.o) EXECUTABLE = halo.x COMMAND = mpirun -np 5 ./$(EXECUTABLE) # Targets .PHONY: all tests tests all: $(EXECUTABLE) $(COMMAND) $(EXECUTABLE): $(F90_OBJ) $(MPIF90) -o $@ $(F90_OBJ) $(LDFLAGS) %.o:%.F90 $(MPIF90) -c $(F90FLAGS) $< clean: $(RM) $(F90_OBJ) $(RM) *.mod distclean: clean $(RM) $(EXECUTABLE) testHalo_mod.o : Halo_mod.o driver.o : testHalo_mod.o Exercise_2/2-A/Halo_mod.F900000644€í4H€L¨x 0000000010111462030065017151 0ustar tcluneNDC\domain usersmodule Halo_mod implicit none private end module Halo_mod Exercise_2/2-A/testHalo_mod.F900000644€í4H€L¨x 0000000152211462040721020061 0ustar tcluneNDC\domain usersmodule testHalo_mod use pFUnit use Halo_mod implicit none private public :: testFillHaloInterior include 'mpif.h' contains subroutine testFillHaloInterior(info) type (TestInfo_type) :: info integer :: comm integer, parameter :: NX_LOC = 4 integer, parameter :: NY_LOC = 4 real :: array(NX_LOC,0:NY_LOC+1) real :: interiorValue real, parameter :: HALO_VALUE = -9999. ! Initialize array with known values for ! the interior and the halo regions. array(1:NX_LOC,0) = HALO_VALUE array(1:NX_LOC,NY_LOC + 1) = HALO_VALUE interiorValue = processRank(info) array(1:NX_LOC,1:NY_LOC) = interiorValue call fillHalo(array, mpiCommunicator(info)) call assertEqual(interiorValue, array(1:NX_LOC,1:NY_LOC)) end subroutine testFillHaloInterior end module testHalo_mod Exercise_2/2-B/0000755€í4H€L¨x 0000000000011462041100015150 5ustar tcluneNDC\domain usersExercise_2/2-B/driver.F900000644€í4H€L¨x 0000000153111462030524016733 0ustar tcluneNDC\domain usersprogram main use pFUnit use testHalo_mod implicit none type (TestSuite_type) :: suite type (TestResult_type) :: result character(len=100) :: summary_statement call pFUnit_init() ! Build suite from test procedures: suite = TestSuite('Halo tests') call add(suite, MpiTestCase('testFillHaloInterior', testFillHaloInterior, numProcesses=1)) call add(suite, MpiTestCase('testFillHaloInterior', testFillHaloInterior, numProcesses=2)) call add(suite, MpiTestCase('testFillHaloInterior', testFillHaloInterior, numProcesses=3)) ! Run the tests and accumulate the results in "result" result = newTestResult(mode=MODE_USE_STDOUT) call Run(suite, result) if (amRoot()) then summary_statement=Summary(result) print*,' ' print*,trim(summary_statement) end if call pFUnit_finalize() end program main Exercise_2/2-B/GNUmakefile0000644€í4H€L¨x 0000000154711462030524017241 0ustar tcluneNDC\domain users# Check for the PFUNIT environment variable ifndef PFUNIT $(error The environment variable "PFUNIT" must be given a value which is the \ path for the installation of pFUnit.) endif # What is the name of the F90 compiler F90 ?= ifort MPIF90 ?= mpif90 PFUNIT_LIBDIR ?=$(PFUNIT)/lib PFUNIT_INCDIR ?=$(PFUNIT)/include PFUNIT_MODDIR ?=$(PFUNIT)/mod PFUNIT_BINDIR ?=$(PFUNIT)/bin F90FLAGS +=-I$(PFUNIT_MODDIR) LDFLAGS +=-L$(PFUNIT_LIBDIR) -lpfunit F90_SRC = $(wildcard *.F90) F90_OBJ = $(F90_SRC:.F90=.o) EXECUTABLE = halo.x COMMAND = mpirun -np 5 ./$(EXECUTABLE) # Targets .PHONY: all tests tests all: $(EXECUTABLE) $(COMMAND) $(EXECUTABLE): $(F90_OBJ) $(MPIF90) -o $@ $(F90_OBJ) $(LDFLAGS) %.o:%.F90 $(MPIF90) -c $(F90FLAGS) $< clean: $(RM) $(F90_OBJ) $(RM) *.mod distclean: clean $(RM) $(EXECUTABLE) testHalo_mod.o : Halo_mod.o driver.o : testHalo_mod.o Exercise_2/2-B/Halo_mod.F900000644€í4H€L¨x 0000000037311462030616017167 0ustar tcluneNDC\domain usersmodule Halo_mod implicit none private public :: fillHalo contains subroutine fillHalo(array, comm) real, intent(in) :: array(:,0:) integer, intent(in) :: comm ! mpi communicator end subroutine fillHalo end module Halo_mod Exercise_2/2-B/testHalo_mod.F900000644€í4H€L¨x 0000000152211462040746020071 0ustar tcluneNDC\domain usersmodule testHalo_mod use pFUnit use Halo_mod implicit none private public :: testFillHaloInterior include 'mpif.h' contains subroutine testFillHaloInterior(info) type (TestInfo_type) :: info integer :: comm integer, parameter :: NX_LOC = 4 integer, parameter :: NY_LOC = 4 real :: array(NX_LOC,0:NY_LOC+1) real :: interiorValue real, parameter :: HALO_VALUE = -9999. ! Initialize array with known values for ! the interior and the halo regions. array(1:NX_LOC,0) = HALO_VALUE array(1:NX_LOC,NY_LOC + 1) = HALO_VALUE interiorValue = processRank(info) array(1:NX_LOC,1:NY_LOC) = interiorValue call fillHalo(array, mpiCommunicator(info)) call assertEqual(interiorValue, array(1:NX_LOC,1:NY_LOC)) end subroutine testFillHaloInterior end module testHalo_mod Exercise_2/2-C/0000755€í4H€L¨x 0000000000011462041100015151 5ustar tcluneNDC\domain usersExercise_2/2-C/driver.F900000644€í4H€L¨x 0000000174211462036644016751 0ustar tcluneNDC\domain usersprogram main use pFUnit use testHalo_mod implicit none type (TestSuite_type) :: suite type (TestResult_type) :: result character(len=100) :: summary_statement call pFUnit_init() ! Build suite from test procedures: suite = TestSuite('Halo tests') call add(suite, MpiTestCase('testFillHaloInterior', testFillHaloInterior, numProcesses=1)) call add(suite, MpiTestCase('testFillHaloInterior', testFillHaloInterior, numProcesses=2)) call add(suite, MpiTestCase('testFillHaloInterior', testFillHaloInterior, numProcesses=3)) call add(suite, TestCase1Step('testGetPESouth', testGetPESouth)) call add(suite, TestCase1Step('testGetPESouth', testGetPENorth)) ! Run the tests and accumulate the results in "result" result = newTestResult(mode=MODE_USE_STDOUT) call Run(suite, result) if (amRoot()) then summary_statement=Summary(result) print*,' ' print*,trim(summary_statement) end if call pFUnit_finalize() end program main Exercise_2/2-C/GNUmakefile0000644€í4H€L¨x 0000000154711462031145017242 0ustar tcluneNDC\domain users# Check for the PFUNIT environment variable ifndef PFUNIT $(error The environment variable "PFUNIT" must be given a value which is the \ path for the installation of pFUnit.) endif # What is the name of the F90 compiler F90 ?= ifort MPIF90 ?= mpif90 PFUNIT_LIBDIR ?=$(PFUNIT)/lib PFUNIT_INCDIR ?=$(PFUNIT)/include PFUNIT_MODDIR ?=$(PFUNIT)/mod PFUNIT_BINDIR ?=$(PFUNIT)/bin F90FLAGS +=-I$(PFUNIT_MODDIR) LDFLAGS +=-L$(PFUNIT_LIBDIR) -lpfunit F90_SRC = $(wildcard *.F90) F90_OBJ = $(F90_SRC:.F90=.o) EXECUTABLE = halo.x COMMAND = mpirun -np 5 ./$(EXECUTABLE) # Targets .PHONY: all tests tests all: $(EXECUTABLE) $(COMMAND) $(EXECUTABLE): $(F90_OBJ) $(MPIF90) -o $@ $(F90_OBJ) $(LDFLAGS) %.o:%.F90 $(MPIF90) -c $(F90FLAGS) $< clean: $(RM) $(F90_OBJ) $(RM) *.mod distclean: clean $(RM) $(EXECUTABLE) testHalo_mod.o : Halo_mod.o driver.o : testHalo_mod.o Exercise_2/2-C/Halo_mod.F900000644€í4H€L¨x 0000000150611462037330017167 0ustar tcluneNDC\domain usersmodule Halo_mod implicit none private public :: fillHalo public :: getPESouth public :: getPENorth include 'mpif.h' contains subroutine fillHalo(array, comm) real, intent(in) :: array(:,0:) integer, intent(in) :: comm ! mpi communicator end subroutine fillHalo integer function getPESouth(rank, npes) result(PEsouth) integer, intent(in) :: rank integer, intent(in) :: npes if (rank > 0) then PEsouth = rank - 1 else PEsouth = MPI_PROC_NULL end if end function getPESouth integer function getPENorth(rank, npes) result(PEnorth) integer, intent(in) :: rank integer, intent(in) :: npes if (rank < npes - 1) then PEnorth = rank + 1 else PEnorth = MPI_PROC_NULL end if end function getPENorth end module Halo_mod Exercise_2/2-C/testHalo_mod.F900000644€í4H€L¨x 0000000323011462041000020050 0ustar tcluneNDC\domain usersmodule testHalo_mod use pFUnit use Halo_mod implicit none private public :: testFillHaloInterior public :: testGetPESouth public :: testGetPENorth include 'mpif.h' contains subroutine testFillHaloInterior(info) type (TestInfo_type) :: info integer :: comm integer, parameter :: NX_LOC = 4 integer, parameter :: NY_LOC = 4 real :: array(NX_LOC,0:NY_LOC+1) real :: interiorValue real, parameter :: HALO_VALUE = -9999. ! Initialize array with known values for ! the interior and the halo regions. array(1:NX_LOC,0) = HALO_VALUE array(1:NX_LOC,NY_LOC + 1) = HALO_VALUE interiorValue = processRank(info) array(1:NX_LOC,1:NY_LOC) = interiorValue call fillHalo(array, mpiCommunicator(info)) call assertEqual(interiorValue, array(1:NX_LOC,1:NY_LOC)) end subroutine testFillHaloInterior subroutine testGetPESouth() call assertEqual(MPI_PROC_NULL, getPESouth(0, 1)) call assertEqual(MPI_PROC_NULL, getPESouth(0, 2)) call assertEqual(MPI_PROC_NULL, getPESouth(0, 3)) call assertEqual(0, getPESouth(1, 2)) call assertEqual(0, getPESouth(1, 3)) call assertEqual(1, getPESouth(2, 3)) call assertEqual(2, getPESouth(3, 4)) end subroutine testGetPESouth subroutine testGetPENorth() call assertEqual(MPI_PROC_NULL, getPENorth(0, 1)) call assertEqual(MPI_PROC_NULL, getPENorth(1, 2)) call assertEqual(MPI_PROC_NULL, getPENorth(2, 3)) call assertEqual(1, getPENorth(0, 2)) call assertEqual(2, getPENorth(1, 3)) call assertEqual(2, getPENorth(1, 3)) call assertEqual(3, getPENorth(2, 4)) end subroutine testGetPENorth end module testHalo_mod Exercise_2/2-D/0000755€í4H€L¨x 0000000000011462041063015162 5ustar tcluneNDC\domain usersExercise_2/2-D/driver.F900000644€í4H€L¨x 0000000305411462037675016755 0ustar tcluneNDC\domain usersprogram main use pFUnit use testHalo_mod implicit none type (TestSuite_type) :: suite type (TestResult_type) :: result character(len=100) :: summary_statement call pFUnit_init() ! Build suite from test procedures: suite = TestSuite('Halo tests') call add(suite, MpiTestCase('testFillHaloInterior', testFillHaloInterior, numProcesses=1)) call add(suite, MpiTestCase('testFillHaloInterior', testFillHaloInterior, numProcesses=2)) call add(suite, MpiTestCase('testFillHaloInterior', testFillHaloInterior, numProcesses=3)) call add(suite, TestCase1Step('testGetPESouth', testGetPESouth)) call add(suite, TestCase1Step('testGetPESouth', testGetPENorth)) call add(suite, MpiTestCase('testFillHaloSouthPole', testFillHaloSouthPole, numProcesses=1)) call add(suite, MpiTestCase('testFillHaloSouthPole', testFillHaloSouthPole, numProcesses=3)) call add(suite, MpiTestCase('testFillHaloSouthOther', testFillHaloSouthOther, numProcesses=1)) call add(suite, MpiTestCase('testFillHaloSouthOther', testFillHaloSouthOther, numProcesses=3)) call add(suite, MpiTestCase('testFillHaloNorthOther', testFillHaloNorthOther, numProcesses=1)) call add(suite, MpiTestCase('testFillHaloNorthOther', testFillHaloNorthOther, numProcesses=3)) ! Run the tests and accumulate the results in "result" result = newTestResult(mode=MODE_USE_STDOUT) call Run(suite, result) if (amRoot()) then summary_statement=Summary(result) print*,' ' print*,trim(summary_statement) end if call pFUnit_finalize() end program main Exercise_2/2-D/GNUmakefile0000644€í4H€L¨x 0000000154711462034002017236 0ustar tcluneNDC\domain users# Check for the PFUNIT environment variable ifndef PFUNIT $(error The environment variable "PFUNIT" must be given a value which is the \ path for the installation of pFUnit.) endif # What is the name of the F90 compiler F90 ?= ifort MPIF90 ?= mpif90 PFUNIT_LIBDIR ?=$(PFUNIT)/lib PFUNIT_INCDIR ?=$(PFUNIT)/include PFUNIT_MODDIR ?=$(PFUNIT)/mod PFUNIT_BINDIR ?=$(PFUNIT)/bin F90FLAGS +=-I$(PFUNIT_MODDIR) LDFLAGS +=-L$(PFUNIT_LIBDIR) -lpfunit F90_SRC = $(wildcard *.F90) F90_OBJ = $(F90_SRC:.F90=.o) EXECUTABLE = halo.x COMMAND = mpirun -np 5 ./$(EXECUTABLE) # Targets .PHONY: all tests tests all: $(EXECUTABLE) $(COMMAND) $(EXECUTABLE): $(F90_OBJ) $(MPIF90) -o $@ $(F90_OBJ) $(LDFLAGS) %.o:%.F90 $(MPIF90) -c $(F90FLAGS) $< clean: $(RM) $(F90_OBJ) $(RM) *.mod distclean: clean $(RM) $(EXECUTABLE) testHalo_mod.o : Halo_mod.o driver.o : testHalo_mod.o Exercise_2/2-D/Halo_mod.F900000644€í4H€L¨x 0000000315411462041047017171 0ustar tcluneNDC\domain usersmodule Halo_mod implicit none private public :: fillHalo public :: getPESouth public :: getPENorth include 'mpif.h' contains subroutine fillHalo(array, comm) real, intent(in) :: array(:,0:) integer, intent(in) :: comm ! mpi communicator integer :: rank, npes, ier integer :: status(MPI_STATUS_SIZE) integer, parameter :: SOUTH_TAG = 10 ! arbitrary integer, parameter :: NORTH_TAG = 11 ! arbitrary integer :: peSouth, peNorth integer :: nx, ny nx = size(array,1) ny = ubound(array,2) - 1 call mpi_comm_rank(comm, rank, ier) call mpi_comm_size(comm, npes, ier) peSouth = getPESouth(rank, npes) peNorth = getPENorth(rank, npes) ! Southern halo call mpi_sendrecv(array(:, ny), nx, MPI_REAL, peNorth, SOUTH_TAG, & & array(:,0), nx, MPI_REAL, peSouth, SOUTH_TAG, & & comm, status, ier) ! Northern halo call mpi_sendrecv(array(:, 1), nx, MPI_REAL, peSouth, NORTH_TAG, & & array(:,ny+1), nx, MPI_REAL, peNorth, NORTH_TAG, & & comm, status, ier) end subroutine fillHalo integer function getPESouth(rank, npes) result(PEsouth) integer, intent(in) :: rank integer, intent(in) :: npes if (rank > 0) then PEsouth = rank - 1 else PEsouth = MPI_PROC_NULL end if end function getPESouth integer function getPENorth(rank, npes) result(PEnorth) integer, intent(in) :: rank integer, intent(in) :: npes if (rank < npes - 1) then PEnorth = rank + 1 else PEnorth = MPI_PROC_NULL end if end function getPENorth end module Halo_mod Exercise_2/2-D/testHalo_mod.F900000644€í4H€L¨x 0000001133011462040673020070 0ustar tcluneNDC\domain usersmodule testHalo_mod use pFUnit use Halo_mod implicit none private public :: testFillHaloInterior public :: testGetPESouth public :: testGetPENorth public :: testFillHaloSouthPole public :: testFillHaloSouthOther public :: testFillHaloNorthPole public :: testFillHaloNorthOther include 'mpif.h' contains subroutine testFillHaloInterior(info) type (TestInfo_type) :: info integer :: comm integer, parameter :: NX_LOC = 4 integer, parameter :: NY_LOC = 4 real :: array(NX_LOC,0:NY_LOC+1) real :: interiorValue real, parameter :: HALO_VALUE = -9999. ! Initialize array with known values for ! the interior and the halo regions. array(1:NX_LOC,0) = HALO_VALUE array(1:NX_LOC,NY_LOC + 1) = HALO_VALUE interiorValue = processRank(info) array(1:NX_LOC,1:NY_LOC) = interiorValue call fillHalo(array, mpiCommunicator(info)) call assertEqual(interiorValue, array(1:NX_LOC,1:NY_LOC)) end subroutine testFillHaloInterior subroutine testGetPESouth() call assertEqual(MPI_PROC_NULL, getPESouth(0, 1)) call assertEqual(MPI_PROC_NULL, getPESouth(0, 2)) call assertEqual(MPI_PROC_NULL, getPESouth(0, 3)) call assertEqual(0, getPESouth(1, 2)) call assertEqual(0, getPESouth(1, 3)) call assertEqual(1, getPESouth(2, 3)) call assertEqual(2, getPESouth(3, 4)) end subroutine testGetPESouth subroutine testGetPENorth() call assertEqual(MPI_PROC_NULL, getPENorth(0, 1)) call assertEqual(MPI_PROC_NULL, getPENorth(1, 2)) call assertEqual(MPI_PROC_NULL, getPENorth(2, 3)) call assertEqual(1, getPENorth(0, 2)) call assertEqual(2, getPENorth(1, 3)) call assertEqual(2, getPENorth(1, 3)) call assertEqual(3, getPENorth(2, 4)) end subroutine testGetPENorth subroutine testFillHaloSouthPole(info) type (TestInfo_type) :: info integer :: comm integer :: rank integer, parameter :: NX_LOC = 4 integer, parameter :: NY_LOC = 4 real :: array(NX_LOC,0:NY_LOC+1) real, parameter :: INTERIOR_VALUE = 1. real, parameter :: HALO_VALUE = -9999. ! Initialize array with known values for ! the interior and the halo regions. array(1:NX_LOC,0) = HALO_VALUE array(1:NX_LOC,NY_LOC + 1) = HALO_VALUE array(1:NX_LOC,1:NY_LOC) = INTERIOR_VALUE call fillHalo(array, mpiCommunicator(info)) rank = processRank(info) if (rank == 0) call assertEqual(HALO_VALUE, array(1:NX_LOC,0)) ! southern halo end subroutine testFillHaloSouthPole subroutine testFillHaloSouthOther(info) type (TestInfo_type) :: info integer :: comm integer :: rank integer, parameter :: NX_LOC = 4 integer, parameter :: NY_LOC = 4 real :: array(NX_LOC,0:NY_LOC+1) real, parameter :: INTERIOR_VALUE = 1. real, parameter :: HALO_VALUE = -9999. rank = processRank(info) ! Initialize array with known values for ! the interior and the halo regions. array(1:NX_LOC,0) = HALO_VALUE array(1:NX_LOC,NY_LOC + 1) = HALO_VALUE array(1:NX_LOC,1:NY_LOC) = rank call fillHalo(array, mpiCommunicator(info)) if (rank > 0) call assertEqual(rank - 1, array(1:NX_LOC,0)) ! southern halo end subroutine testFillHaloSouthOther subroutine testFillHaloNorthPole(info) type (TestInfo_type) :: info integer :: comm integer :: rank, npes integer, parameter :: NX_LOC = 4 integer, parameter :: NY_LOC = 4 real :: array(NX_LOC,0:NY_LOC+1) real, parameter :: INTERIOR_VALUE = 1. real, parameter :: HALO_VALUE = -9999. ! Initialize array with known values for ! the interior and the halo regions. array(1:NX_LOC,0) = HALO_VALUE array(1:NX_LOC,NY_LOC + 1) = HALO_VALUE array(1:NX_LOC,1:NY_LOC) = INTERIOR_VALUE call fillHalo(array, mpiCommunicator(info)) rank = processRank(info) npes = numProcesses(info) if (rank == npes-1) call assertEqual(HALO_VALUE, array(1:NX_LOC,NY_LOC+1)) ! norther halo end subroutine testFillHaloNorthPole subroutine testFillHaloNorthOther(info) type (TestInfo_type) :: info integer :: comm integer :: rank, npes integer, parameter :: NX_LOC = 4 integer, parameter :: NY_LOC = 4 real :: array(NX_LOC,0:NY_LOC+1) real, parameter :: INTERIOR_VALUE = 1. real, parameter :: HALO_VALUE = -9999. rank = processRank(info) npes = numProcesses(info) ! Initialize array with known values for ! the interior and the halo regions. array(1:NX_LOC,0) = HALO_VALUE array(1:NX_LOC,NY_LOC + 1) = HALO_VALUE array(1:NX_LOC,1:NY_LOC) = rank call fillHalo(array, mpiCommunicator(info)) if (rank < npes-1) call assertEqual(rank + 1, array(1:NX_LOC,NY_LOC+1)) ! northern halo end subroutine testFillHaloNorthOther end module testHalo_mod Exercise_2/README0000644€í4H€L¨x 0000001066311462037107015532 0ustar tcluneNDC\domain usersExercise 2: MPI Halo Fill In this exercise you will develop a set of routines which will fill the halo cells of a subdomain from boundary information in neigboring domains. To keep things simple, we will work with 2D arrays and a 1-dimensional decomposition in the North/South direction (2nd dimension). Thus, we only need to concern ourselves with halos in the North/South direction, and can use the fact that this direction is not periodic. If you have not used MPI, you can either partner with someone else in the class, or spend the time looking at the solutions, or even getting a jump on the next exercise. ========== Step 2-A: ========== There are several different reasonable approaches to begin this effort. We have decided to first develop tests to ensure that filling the halos does not affect the interior of a subdomain. Although such a test leads to relatively little functionality, it is a _very_ important precaution against common mistakes during the real implementation. Change directory into ./Exercise_2/2-A. A test called "testFillHaloInterior()" is already in place, but the code fails to compile because the fillHalo() procedure has not yet been created. Note that the driver will call this test multiple times for varying numbers of processors. After studying the test to understand what is does, you are to create a public fillHalo() subroutine in Halo_mod.F90 that enables the code to compile and passes the test. Note, the implementation does not actually do anything at this stage - we've established our desired interface and guarded against accidentally altering the interior with later changes. ========== Step 2-B: ========== (If you had trouble with 2-A, you can switch to 2-B for this exercise, otherwise you can continue on in the same subdirectory.) We now take a step sideways to create some helper functions that compute the rank of the neighbors to the north and south: getPESouth() and getPENorth(). Note that the southernmost domain should return MPI_PROC_NULL for its southern neigbor and similarly for the northern neigbbor of the northernmost domain. We have chosen to use an interface where these two routines take in 2 integer arguments: rank and total number of processes. (There are other sensible approaches, but this choice is more amenable to testing.) NOTE: For this step, the test procedure can be a _serial_ (i.e. not MPI) test. Communication with other processors is not required because we are passing all of the topology information as arguments. i) Create a test procedure testGetPESouth() that checks that getPESouth() returns MPI_PROC_NULL when NPES=1. ii) Implement a new procedure getPESouth() which passes the test. iii) Iteratively extend testGetPESouth() with additional asserts for rank and NPES. After each assert check extend the implementation of getPESouth() to pass the test. Remember, 0 <= rank < npes. After you are satisfied with getPESouth() do the same with getPENorth(). (Feel free to take bigger steps, since the code will be quite similar.) ========== Step 2-C: ========== With our 2 helper functions in place, we are now ready to add some stronger tests on the actions for haloFill() itself. Let's start with tests for the contents of the southern halo. Although it is sometimes desirable to write tests that only work correctly on a specific number of processes, it is usually preferable to make your tests more robust when possible. i) Create a test for halofill() that ensures that the souther halo on process 0 is not modified. Add it to the driver for 1, 2, and 3 processes. Check that it passses. ii) Create a new test that initializes the interior on _every_ process to be the same value as the rank of that process. This makes it easy to "know" the results of the halo fill. Assert that the southern halo on each rank is equal to rank - 1 (except on rank = 0). Check that this test fails for process counts > 1. Extend the implementation to pass the test usingn mpi_sendrecv(). (A TDD purist could still get this test to pass without MPI, but any similar test with different values would force at least some communication among processors.) iii) There are numerous additional things that could be verified. Try to think of additional tests that could be created to enhance confidence. (Do not implement due to time constraints.) Now, repeat steps (i) and (ii) for the northern halo. An example solution is shown in 2-D.