2 ! Author(s)/Contact(s):
7 ! Parameters: <Specify typical arguments passed>
9 ! <list file names and briefly describe the data they include>
11 ! <list file names and briefly describe the information they include>
14 ! <list exit condition or error codes returned >
15 ! If appropriate, descriptive troubleshooting instructions or
16 ! likely causes for failures could be mentioned here with the
17 ! appropriate error code
19 ! User controllable options: <if applicable>
21 ! This is used as a coupler with the WRF model.
22 MODULE MODULE_mpp_ReachLS
24 use module_mpp_land, only: io_id, my_id, mpp_status, mpp_land_max_int1, mpp_land_sync, HYDRO_COMM_WORLD
31 real,allocatable, dimension(:) :: sv
32 real,allocatable, dimension(:) :: rv
33 real,allocatable, dimension(:) :: rvId
34 real,allocatable, dimension(:) :: snId
35 end TYPE Grid2ReachMap
37 interface ReachLS_decomp
38 module procedure ReachLS_decompReal
39 module procedure ReachLS_decompReal8
40 module procedure ReachLS_decompInt
41 module procedure ReachLS_decompInt8
42 module procedure ReachLS_decompChar
45 interface ReachLS_write_io
46 module procedure ReachLS_wReal
47 module procedure ReachLS_wReal2
48 module procedure ReachLS_wReal8
49 module procedure ReachLS_wInt
50 module procedure ReachLS_wInt2
51 module procedure ReachLS_wInt8
52 module procedure ReachLS_wChar
56 module procedure gbcastReal
57 module procedure gbcastInt
58 module procedure gbcastReal2
59 module procedure gbcastInt8
63 module procedure updateLinkV8_mem
64 module procedure updateLinkV4_mem
70 integer,allocatable,dimension(:) :: sDataRec ! sending data size
71 integer,allocatable,dimension(:) :: rDataRec ! receiving data size
72 integer,allocatable,dimension(:) :: linkls_s ! receiving data size
73 integer,allocatable,dimension(:) :: linkls_e ! receiving data size
74 integer,allocatable,dimension(:) :: ToInd ! size of toInd
77 integer, allocatable, dimension(:) :: LLINKIDINDX, aLinksl
78 integer :: LLINKLEN, gNlinksl, tmpnlinksl, l_nlinksl, max_nlinkSL
83 subroutine updateLinkV8_mem(LinkV, outV)
86 real, dimension(:) :: outV
87 real*8, dimension(:) :: LinkV
88 real, allocatable, dimension(:) :: gLinkV_r4
89 real*8, allocatable,dimension(:) :: tmpBuf, gLinkV_r8
90 integer :: ierr, i, tag, k,m,lsize
91 integer, allocatable,dimension(:) :: lindex
92 if(my_id .eq. io_id) then
93 allocate(gLinkV_r4(gnlinksl))
94 allocate(gLinkV_r8(gnlinksl))
98 gLinkV_r8(LLINKIDINDX(i)) = LinkV(i)
102 if(my_id .ne. IO_id) then
105 call mpi_send(LLINKLEN,1,MPI_INTEGER, IO_id, &
106 tag,HYDRO_COMM_WORLD,ierr)
107 if(LLINKLEN .gt. 0) then
109 call mpi_send(LLINKIDINDX,LLINKLEN,MPI_INTEGER, IO_id, &
110 tag,HYDRO_COMM_WORLD,ierr)
112 call mpi_send(LinkV,LLINKLEN,MPI_DOUBLE_PRECISION, IO_id, &
113 tag,HYDRO_COMM_WORLD,ierr)
116 do i = 0, numprocs - 1
117 if(i .ne. IO_id) then
119 call mpi_recv(lsize,1,MPI_INTEGER, i, &
120 tag,HYDRO_COMM_WORLD,mpp_status,ierr)
121 if(lsize .gt. 0) then
122 allocate(lindex(lsize) )
123 allocate(tmpBuf(lsize) )
125 call mpi_recv(lindex,lsize,MPI_INTEGER, i, &
126 tag,HYDRO_COMM_WORLD,mpp_status,ierr)
128 call mpi_recv(tmpBuf,lsize,&
129 MPI_DOUBLE_PRECISION,i,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
131 gLinkV_r8(lindex(k)) = gLinkV_r8(lindex(k)) + tmpBuf(k)
133 if(allocated(lindex)) deallocate(lindex)
134 if(allocated(tmpBuf)) deallocate(tmpBuf)
138 gLinkV_r4 = gLinkV_r8
139 if(allocated(gLinkV_r8)) deallocate(gLinkV_r8)
142 call ReachLS_decompReal(gLinkV_r4,outV)
144 if(my_id .eq. io_id) then
145 if(allocated(gLinkV_r4)) deallocate(gLinkV_r4)
147 end subroutine updateLinkV8_mem
149 subroutine updateLinkV4_mem(LinkV, outV)
150 ! for big memory data
152 real, dimension(:) :: outV
153 real, dimension(:) :: LinkV
154 real, allocatable, dimension(:) :: gLinkV_r4
155 real, allocatable,dimension(:) :: tmpBuf
156 integer :: ierr, i, tag, k,m,lsize
157 integer, allocatable,dimension(:) :: lindex
158 if(my_id .eq. io_id) then
159 allocate(gLinkV_r4(gnlinksl))
162 gLinkV_r4(LLINKIDINDX(i)) = LinkV(i)
166 if(my_id .ne. IO_id) then
169 call mpi_send(LLINKLEN,1,MPI_INTEGER, IO_id, &
170 tag,HYDRO_COMM_WORLD,ierr)
171 if(LLINKLEN .gt. 0) then
173 call mpi_send(LLINKIDINDX,LLINKLEN,MPI_INTEGER, IO_id, &
174 tag,HYDRO_COMM_WORLD,ierr)
176 call mpi_send(LinkV,LLINKLEN,MPI_REAL, IO_id, &
177 tag,HYDRO_COMM_WORLD,ierr)
180 do i = 0, numprocs - 1
181 if(i .ne. IO_id) then
183 call mpi_recv(lsize,1,MPI_INTEGER, i, &
184 tag,HYDRO_COMM_WORLD,mpp_status,ierr)
185 if(lsize .gt. 0) then
186 allocate(lindex(lsize) )
187 allocate(tmpBuf(lsize) )
189 call mpi_recv(lindex,lsize,MPI_INTEGER, i, &
190 tag,HYDRO_COMM_WORLD,mpp_status,ierr)
192 call mpi_recv(tmpBuf,lsize,&
193 MPI_REAL,i,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
195 gLinkV_r4(lindex(k)) = gLinkV_r4(lindex(k)) + tmpBuf(k)
197 if(allocated(lindex)) deallocate(lindex)
198 if(allocated(tmpBuf)) deallocate(tmpBuf)
204 call ReachLS_decompReal(gLinkV_r4,outV)
206 if(my_id .eq. io_id) then
207 if(allocated(gLinkV_r4)) deallocate(gLinkV_r4)
209 end subroutine updateLinkV4_mem
212 subroutine updateLinkV8(LinkV, outV)
214 real, dimension(:) :: outV
215 real*8, dimension(:) :: LinkV
216 real*8, dimension(gNlinksl) :: gLinkV,gLinkV_r
217 real, dimension(gNlinksl) :: gLinkV_r4
218 integer :: ierr, i, tag
222 gLinkV(LLINKIDINDX(i)) = LinkV(i)
225 if(my_id .ne. IO_id) then
227 call mpi_send(gLinkV,gnlinksl,MPI_DOUBLE_PRECISION, IO_id, &
228 tag,HYDRO_COMM_WORLD,ierr)
231 do i = 0, numprocs - 1
232 if(i .ne. IO_id) then
234 call mpi_recv(gLinkV,gnlinksl,&
235 MPI_DOUBLE_PRECISION,i,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
236 gLinkV_r = gLinkV_r + gLinkV
242 call ReachLS_decompReal(gLinkV_r4,outV)
243 end subroutine updateLinkV8
245 subroutine updateLinkV4(LinkV, outV)
247 real, dimension(:) :: outV
248 real, dimension(:) :: LinkV
249 real, dimension(gNlinksl) :: gLinkV,gLinkV_r
250 real, dimension(gNlinksl) :: gLinkV_r4
251 integer :: ierr, i, tag
255 gLinkV(LLINKIDINDX(i)) = LinkV(i)
258 if(my_id .ne. IO_id) then
260 call mpi_send(gLinkV,gnlinksl,MPI_REAL, IO_id, &
261 tag,HYDRO_COMM_WORLD,ierr)
264 do i = 0, numprocs - 1
265 if(i .ne. IO_id) then
267 call mpi_recv(gLinkV,gnlinksl,&
268 MPI_REAL,i,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
269 gLinkV_r = gLinkV_r + gLinkV
274 call ReachLS_decompReal(gLinkV_r4,outV)
275 end subroutine updateLinkV4
277 subroutine gbcastReal(inV, outV)
279 real, dimension(:) :: outV
280 real, dimension(:) :: inV
282 call ReachLS_write_io(inV,outV)
283 call mpi_bcast(outV(1:gnlinksl),gnlinksl,MPI_REAL, &
284 IO_id,HYDRO_COMM_WORLD,ierr)
285 end subroutine gbcastReal
287 subroutine gbcastReal2_old(index,size1,inV, insize, outV)
289 integer :: size1, insize
290 integer,dimension(:) :: index
291 real, dimension(:) :: outV
292 real, dimension(:) :: inV
293 real, dimension(max_nlinkSL) :: tmpV
294 integer :: ierr, k, i, m, j, bsize
296 do i = 0, numprocs -1
297 bsize = linkls_e(i+1) - linkls_s(i+1) + 1
298 if(linkls_e(i+1) .gt. 0) then
299 if(my_id .eq. i) tmpV(1:bsize) = inV(1:bsize)
300 call mpi_bcast(tmpV(1:bsize),bsize,MPI_REAL, &
301 i,HYDRO_COMM_WORLD,ierr)
304 if(index(j) .eq. (linkls_s(i+1) + k -1) ) then
314 end subroutine gbcastReal2_old
316 subroutine gbcastReal2(index,size1,inV, insize, outV)
318 integer :: size1, insize
319 integer,dimension(:) :: index
320 real, dimension(:) :: outV
321 real, dimension(:) :: inV
322 ! real, dimension(max_nlinkSL) :: tmpV
323 real, dimension(gnlinksl) :: gbuf
324 integer :: ierr, k, i, m, j, bsize
326 call ReachLS_write_io(inV,gbuf)
327 call mpi_bcast(gbuf,gnlinksl,MPI_REAL, &
328 IO_id,HYDRO_COMM_WORLD,ierr)
330 outV(j) = gbuf(index(j))
332 end subroutine gbcastReal2
337 subroutine gbcastInt(inV, outV)
339 integer, dimension(:) :: outV
340 integer, dimension(:) :: inV
342 call ReachLS_write_io(inV,outV)
343 call mpi_bcast(outV(1:gnlinksl),gnlinksl,MPI_INTEGER, &
344 IO_id,HYDRO_COMM_WORLD,ierr)
345 end subroutine gbcastInt
347 subroutine gbcastInt8(inV, outV)
349 integer(kind=int64), dimension(:) :: outV
350 integer(kind=int64), dimension(:) :: inV
352 call ReachLS_write_io(inV,outV)
353 call mpi_bcast(outV(1:gnlinksl),gnlinksl,MPI_INTEGER8, &
354 IO_id,HYDRO_COMM_WORLD,ierr)
355 end subroutine gbcastInt8
357 subroutine getLocalIndx(glinksl,LINKID, LLINKID)
359 integer(kind=int64), dimension(:) :: LINKID, LLINKID
360 integer :: i,k, glinksl, ierr
361 integer(kind=int64) :: gLinkId(glinksl)
363 LLINKLEN = size(LLINKID,1)
364 allocate(LLINKIDINDX(LLINKLEN))
368 call ReachLS_write_io(LINKID,gLinkId)
370 call mpi_bcast(gLinkId(1:glinksl),glinksl,MPI_INTEGER8, &
371 IO_id,HYDRO_COMM_WORLD,ierr)
373 ! The following loops are replaced by a hashtable-based algorithm
376 ! if(LLINKID(i) .eq. gLinkId(k)) then
385 type(hash_t) :: hash_table
386 integer(kind=int64) :: val,it
389 call hash_table%set_all_idx(LLINKID,LLINKLEN)
391 call hash_table%get(gLinkId(it), val, found)
392 if(found .eqv. .true.) then
393 llinkidindx(val) = it
396 call hash_table%clear()
400 end subroutine getLocalIndx
402 subroutine ReachLS_ini(glinksl,nlinksl,linklsS, linklsE)
404 integer, intent(in) :: glinksl
405 integer, intent(out) :: nlinksl, linklsS, linklsE
406 integer :: i, ii, ierr
408 ! get my_id and numprocs
409 call MPI_COMM_RANK( HYDRO_COMM_WORLD, my_id, ierr )
410 call MPI_COMM_SIZE( HYDRO_COMM_WORLD, numprocs, ierr )
413 nlinksl = glinksl / numprocs
414 allocate(linkls_s(numprocs))
415 allocate(linkls_e(numprocs))
416 allocate(aLinksl(numprocs))
417 allocate(ToInd(numprocs))
422 linkls_e(1) = nlinksl
425 do i = 2, mod(glinksl, numprocs)+1
426 aLinksl(i) = aLinksl(i) + 1
429 linkls_s(i) = linkls_e(i-1)+1
430 linkls_e(i) = linkls_s(i) + aLinksl(i)-1
433 nlinksl = aLinksl(my_id+1)
435 linklsS = linkls_s(my_id+1)
436 linklsE = linkls_e(my_id+1)
437 tmpnlinksl = aLinksl(my_id+1)
440 max_nlinksl = l_nlinksl
441 call mpp_land_max_int1(max_nlinksl)
444 end subroutine ReachLS_ini
446 subroutine MapGrid2ReachIni(in2d)
448 integer, intent(in),dimension(:,:) :: in2d
449 integer :: ix, jx, i,j,n,ntotal, ierr
450 integer, dimension(numprocs) :: tmpS
452 allocate(sDataRec(numprocs))
453 allocate(rDataRec(numprocs))
462 if(in2d(i,j) .gt. 0) then
464 if((in2d(i,j) .ge. linkls_s(n)) .and. (in2d(i,j) .le. linkls_e(n)) ) then
465 sDataRec(n) = sDataRec(n) + 1
473 if(my_id .eq. n-1) then
476 call mpi_bcast(tmpS,numprocs,MPI_INTEGER, &
477 n-1,HYDRO_COMM_WORLD,ierr)
478 rDataRec(n) = tmpS(n)
481 end subroutine MapGrid2ReachIni
484 subroutine ReachLS_decompReal(inV,outV)
486 real,INTENT(in),dimension(:) :: inV
487 real,INTENT(out),dimension(:) :: outV
488 integer :: i, ierr, tag
490 if(my_id .eq. io_id) then
492 if(i-1 .eq. io_id) then
493 if(alinksl(i) .gt. 0) then
494 outV(1:(linkls_e(i)-linkls_s(i)+1) ) = inV(linkls_s(i):linkls_e(i))
497 if(aLinksl(i) .gt. 0) then
498 call mpi_send(inV(linkls_s(i):linkls_e(i)), &
500 MPI_REAL, i-1 ,tag,HYDRO_COMM_WORLD,ierr)
505 if(aLinksl(my_id+1) .gt. 0) then
506 call mpi_recv(outV(1:(linkls_e(my_id+1)-linkls_s(my_id+1)+1) ), & !! this one has +1!
508 MPI_REAL, io_id,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
512 END subroutine ReachLS_decompReal
514 subroutine ReachLS_decompReal8(inV,outV)
516 real*8,intent(in),dimension(:) :: inV
517 real*8,intent(out),dimension(:) :: outV
518 integer :: i, ierr, tag
520 if(my_id .eq. io_id) then
522 if(i-1 .eq. io_id) then
523 if(alinksl(i) .gt. 0) then
524 outV(1:(linkls_e(i)-linkls_s(i)+1) ) = inV(linkls_s(i):linkls_e(i))
527 if(aLinksl(i) .gt. 0) then
528 call mpi_send(inV(linkls_s(i):linkls_e(i)), &
530 MPI_REAL8, i-1 ,tag,HYDRO_COMM_WORLD,ierr)
535 if(aLinksl(my_id+1) .gt. 0) then
536 call mpi_recv(outV(1:(linkls_e(my_id+1)-linkls_s(my_id+1)+1) ), & !! this one has +1!
538 MPI_REAL8, io_id,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
542 end subroutine ReachLS_decompReal8
544 subroutine ReachLS_decompInt(inV,outV)
546 integer,INTENT(in),dimension(:) :: inV
547 integer,INTENT(out),dimension(:) :: outV
548 integer :: i, ierr, tag
550 if(my_id .eq. io_id) then
552 if(i-1 .eq. io_id) then
553 if(alinksl(i) .gt. 0) then
554 outV(1:linkls_e(i)-linkls_s(i)+1) = inV(linkls_s(i):linkls_e(i))
557 if(aLinksl(i) .gt. 0) then
558 call mpi_send(inV(linkls_s(i):linkls_e(i)), &
560 MPI_INTEGER, i-1,tag,HYDRO_COMM_WORLD,ierr)
565 if(aLinksl(my_id+1) .gt. 0) then
566 call mpi_recv(outV(1:linkls_e(my_id+1)-linkls_s(my_id+1)+1), &
568 MPI_INTEGER, io_id,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
574 END subroutine ReachLS_decompInt
576 subroutine ReachLS_decompInt8(inV,outV)
578 integer(kind=int64), INTENT(in), dimension(:) :: inV
579 integer(kind=int64), INTENT(out), dimension(:) :: outV
580 integer :: i, ierr, tag
582 if(my_id .eq. io_id) then
584 if(i-1 .eq. io_id) then
585 if(alinksl(i) .gt. 0) then
586 outV(1:linkls_e(i)-linkls_s(i)+1) = inV(linkls_s(i):linkls_e(i))
589 if(aLinksl(i) .gt. 0) then
590 call mpi_send(inV(linkls_s(i):linkls_e(i)), &
592 MPI_INTEGER8, i-1,tag,HYDRO_COMM_WORLD,ierr)
597 if(aLinksl(my_id+1) .gt. 0) then
598 call mpi_recv(outV(1:linkls_e(my_id+1)-linkls_s(my_id+1)+1), &
600 MPI_INTEGER8, io_id,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
606 END subroutine ReachLS_decompInt8
609 subroutine ReachLS_decompChar(inV,outV)
611 character(len=*),intent(in), dimension(:) :: inV
612 character(len=*),intent(out),dimension(:) :: outV
613 integer :: i, ierr, tag
617 if(my_id .eq. io_id) then
619 if(i-1 .eq. io_id) then
620 if(alinksl(i) .gt. 0) then
621 outV(1:(linkls_e(i)-linkls_s(i)+1)) = inV(linkls_s(i):linkls_e(i))
624 if(aLinksl(i) .gt. 0) then
625 ! The mpi_send takes what you give it and THEN treats each caracter as an array element.
626 call mpi_send(inV(linkls_s(i):linkls_e(i)), &
628 MPI_CHARACTER, i-1, tag, HYDRO_COMM_WORLD, ierr)
633 if(aLinksl(my_id+1) .gt. 0) then
634 ! The mpi_recv treats each caracter as an array element.
635 call mpi_recv(outV(1 : (linkls_e(my_id+1)-linkls_s(my_id+1)+1) ), & !jlm should have +1
636 strLen*alinksl(my_id+1), &
637 MPI_CHARACTER, io_id, tag, HYDRO_COMM_WORLD, mpp_status,ierr )
641 end subroutine ReachLS_decompChar
644 subroutine ReachLS_wReal(inV,outV)
646 real,INTENT(in),dimension(:) :: inV
647 real,INTENT(out),dimension(:) :: outV
648 integer :: i, ierr, tag, ss , mm
650 if(my_id .eq. io_id) then
653 if(i-1 .eq. io_id) then
654 if(alinksl(i) .gt. 0) then
655 outV(linkls_s(i):linkls_e(i)) = inV(1:linkls_e(i)-linkls_s(i)+1)
658 if(aLinksl(i) .gt. 0) then
660 call mpi_recv(outV(linkls_s(i):linkls_e(i)), &
662 MPI_REAL,i-1,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
667 if(aLinksl(my_id+1) .gt. 0) then
670 call mpi_send(inV(1:aLinksl(my_id+1) ), &
672 MPI_REAL,io_id,tag,HYDRO_COMM_WORLD,ierr)
676 END subroutine ReachLS_wReal
678 subroutine ReachLS_wReal8(inV,outV)
680 real*8,intent(in),dimension(:) :: inV
681 real*8,intent(out),dimension(:) :: outV
682 integer :: i, ierr, tag, ss , mm
684 if(my_id .eq. io_id) then
687 if(i-1 .eq. io_id) then
688 if(alinksl(i) .gt. 0) then
689 outV(linkls_s(i):linkls_e(i)) = inV(1:linkls_e(i)-linkls_s(i)+1)
692 if(aLinksl(i) .gt. 0) then
694 call mpi_recv(outV(linkls_s(i):linkls_e(i)), &
696 MPI_REAL8,i-1,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
701 if(aLinksl(my_id+1) .gt. 0) then
704 call mpi_send(inV(1:aLinksl(my_id+1) ), &
706 MPI_REAL8,io_id,tag,HYDRO_COMM_WORLD,ierr)
710 END subroutine ReachLS_wReal8
713 subroutine ReachLS_wInt(inV,outV)
715 integer,INTENT(in),dimension(:) :: inV
716 integer,INTENT(out),dimension(:) :: outV
717 integer :: i, ierr, tag
719 if(my_id .eq. io_id) then
721 if(i-1 .eq. io_id) then
722 if(alinksl(i) .gt. 0) then
723 outV(linkls_s(i):linkls_e(i)) = inV(1:linkls_e(i)-linkls_s(i)+1)
726 if(aLinksl(i) .gt. 0) then
728 call mpi_recv(outV(linkls_s(i):linkls_e(i)), &
730 MPI_INTEGER,i-1,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
735 if(aLinksl(my_id+1) .gt. 0) then
737 call mpi_send(inV(1:aLinksl(my_id+1) ), &
739 MPI_INTEGER,io_id,tag,HYDRO_COMM_WORLD,ierr)
743 END subroutine ReachLS_wInt
745 subroutine ReachLS_wInt8(inV,outV)
747 integer(kind=int64), intent(in), dimension(:) :: inV
748 integer(kind=int64), intent(out), dimension(:) :: outV
749 integer :: i, ierr, tag
751 if(my_id .eq. io_id) then
753 if(i-1 .eq. io_id) then
754 if(alinksl(i) .gt. 0) then
755 outV(linkls_s(i):linkls_e(i)) = inV(1:linkls_e(i)-linkls_s(i)+1)
758 if(aLinksl(i) .gt. 0) then
760 call mpi_recv(outV(linkls_s(i):linkls_e(i)), &
762 MPI_INTEGER8,i-1,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
767 if(aLinksl(my_id+1) .gt. 0) then
769 call mpi_send(inV(1:aLinksl(my_id+1) ), &
771 MPI_INTEGER8,io_id,tag,HYDRO_COMM_WORLD,ierr)
775 END subroutine ReachLS_wInt8
777 subroutine ReachLS_wInt2(inV,outV,len,glen)
780 integer,INTENT(in),dimension(len) :: inV
781 integer,INTENT(out),dimension(glen) :: outV
782 integer :: i, ierr, tag
784 if(my_id .eq. io_id) then
786 if(i-1 .eq. io_id) then
787 if(alinksl(i) .gt. 0) then
788 outV(linkls_s(i):linkls_e(i)) = inV(1:linkls_e(i)-linkls_s(i)+1)
791 if(aLinksl(i) .gt. 0) then
793 call mpi_recv(outV(linkls_s(i):linkls_e(i)), &
795 MPI_INTEGER,i-1,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
800 if(aLinksl(my_id+1) .gt. 0) then
802 call mpi_send(inV(1:aLinksl(my_id+1) ), &
804 MPI_INTEGER,io_id,tag,HYDRO_COMM_WORLD,ierr)
808 END subroutine ReachLS_wInt2
810 subroutine ReachLS_wReal2(inV,outV,len,glen)
813 real,INTENT(in),dimension(len) :: inV
814 real,INTENT(out),dimension(glen) :: outV
815 integer :: i, ierr, tag
817 if(my_id .eq. io_id) then
819 if(i-1 .eq. io_id) then
820 if(alinksl(i) .gt. 0) then
821 outV(linkls_s(i):linkls_e(i)) = inV(1:linkls_e(i)-linkls_s(i)+1)
824 if(aLinksl(i) .gt. 0) then
826 call mpi_recv(outV(linkls_s(i):linkls_e(i)), &
828 MPI_REAL,i-1,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
833 if(aLinksl(my_id+1) .gt. 0) then
835 call mpi_send(inV(1:aLinksl(my_id+1) ), &
837 MPI_REAL,io_id,tag,HYDRO_COMM_WORLD,ierr)
841 END subroutine ReachLS_wReal2
843 subroutine ReachLS_wChar(inV,outV)
845 character(len=*), intent(in), dimension(:) :: inV
846 character(len=*) ,intent(out),dimension(:) :: outV
847 integer :: i, ierr, tag
850 if(my_id .eq. io_id) then
852 if(i-1 .eq. io_id) then
853 if(alinksl(i) .gt. 0) then
854 outV(linkls_s(i):linkls_e(i)) = inV(1:linkls_e(i)-linkls_s(i)+1)
857 if(aLinksl(i) .gt. 0) then
859 ! ? seems asymmetric with ReachLS_decompChar
860 call mpi_recv(outV( linkls_s(i) : linkls_e(i) ), &
861 ! call mpi_recv(outV( ((linkls_s(i)-1)+1) : (linkls_e(i)) ), &
863 MPI_CHARACTER, i-1, tag, HYDRO_COMM_WORLD, mpp_status, ierr )
868 if(aLinksl(my_id+1) .gt. 0) then
870 ! The mpi_send takes what you give it and THEN treats each caracter as an array element.
871 call mpi_send(inV(1:aLinksl(my_id+1)), &
873 MPI_CHARACTER, io_id, tag, HYDRO_COMM_WORLD, ierr)
877 end subroutine ReachLS_wChar
880 subroutine getFromInd(linkid,to,ind,indLen)
881 integer,dimension(:) :: linkid, to
882 integer, allocatable, dimension(:) ::ind
883 integer :: k, m, kk, mm,indLen
884 integer, dimension(gnlinksl) :: glinkid
885 call ReachLS_write_io(linkid,glinkid)
890 if(glinkid(k) .eq. to(m) ) then
901 if(glinkid(k) .eq. to(m) ) then
911 end subroutine getFromInd
913 subroutine getToInd(from,to,ind,indLen,gToNodeOut)
916 integer(kind=int64),dimension(:) :: from, to
917 integer, allocatable, dimension(:) ::ind
918 integer(kind=int64), allocatable, dimension(:,:) :: gToNodeOut
919 integer :: k, m, kk, mm,indLen, i, ierr
920 integer(kind=int64), dimension(gnlinksl) :: gto
921 integer :: maxNum, num
923 call gBcastValue(to, gto)
931 ! The following loops are replaced by a hashtable-based algorithm
935 ! if(gto(k) .eq. from(m) ) then
940 ! if(num .gt. maxNum) maxNum = num
944 type(hash_t) :: hash_table
945 integer(kind=int64) :: val,it
946 integer(kind=int64), allocatable :: num_a(:)
953 call hash_table%set_all_idx(from, mm)
955 call hash_table%get(gto(it), val, found)
956 if(found .eqv. .true.) then
958 num_a(val) = num_a(val) + 1
961 maxNum = maxval(num_a)
965 allocate(gToNodeOut(mm,maxNum+1))
973 ! The following loops are replaced by a hashtable-based algorithm
977 ! if(gto(k) .eq. from(m) ) then
979 ! !yw ind(kk) = gto(k)
981 ! !! gToNodeOut(m,num+1) = gto(k)
982 ! gToNodeOut(m,num+1) = kk
983 ! gToNodeOut(m,1) = num
990 call hash_table%get(gto(it), val, found)
991 if(found .eqv. .true.) then
994 gToNodeOut(val,num_a(val)+1) = kk
995 gToNodeOut(val,1) = num_a(val)
996 num_a(val) = num_a(val) + 1
1001 call hash_table%clear()
1006 do i = 0, numprocs - 1
1007 call mpi_bcast(ToInd(i+1),1,MPI_INTEGER8, &
1008 i,HYDRO_COMM_WORLD,ierr)
1011 end subroutine getToInd
1013 subroutine com_decomp1dInt(inV,gsize,outV,lsize)
1014 ! output outV and lsize
1016 integer,INTENT(in),dimension(:) :: inV
1017 integer,allocatable,dimension(:) :: outV
1018 integer :: i, ierr, tag, imod, ncomsize
1019 integer :: lsize, ssize,start, gsize, end
1021 ncomsize = gsize/numprocs
1022 imod = mod(gsize,numprocs)
1025 if(my_id .eq. io_id) then
1029 if(i-1 .lt. imod) then
1030 ssize = ncomsize + 1
1036 end = start + ssize - 1
1038 if(i-1 .eq. io_id) then
1039 if(ssize .gt. 0) then
1040 allocate(outV(ssize) )
1041 outV(1:ssize) = inV(1:ssize)
1047 if(ssize .gt. 0 ) then
1048 call mpi_send(inV(start:start+ssize-1), ssize, &
1049 MPI_INTEGER, i-1,tag,HYDRO_COMM_WORLD,ierr)
1054 if(my_id .lt. imod) then
1055 lsize = ncomsize + 1
1059 if( lsize .gt. 0) then
1060 allocate(outV(lsize) )
1061 call mpi_recv(outV,lsize, &
1062 MPI_INTEGER, io_id,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
1065 call mpp_land_sync()
1068 END subroutine com_decomp1dInt
1070 subroutine com_decomp1dInt8(inV,gsize,outV,lsize)
1071 ! output outV and lsize
1073 integer(kind=int64),intent(in),dimension(:) :: inV
1074 integer(kind=int64),allocatable,dimension(:) :: outV
1075 integer :: i, ierr, tag, imod, ncomsize
1076 integer :: lsize, ssize,start, gsize, end
1078 ncomsize = gsize/numprocs
1079 imod = mod(gsize,numprocs)
1082 if(my_id .eq. io_id) then
1086 if(i-1 .lt. imod) then
1087 ssize = ncomsize + 1
1093 end = start + ssize - 1
1095 if(i-1 .eq. io_id) then
1096 if(ssize .gt. 0) then
1097 allocate(outV(ssize) )
1098 outV(1:ssize) = inV(1:ssize)
1104 if(ssize .gt. 0 ) then
1105 call mpi_send(inV(start:start+ssize-1), ssize, &
1106 MPI_INTEGER8, i-1,tag,HYDRO_COMM_WORLD,ierr)
1111 if(my_id .lt. imod) then
1112 lsize = ncomsize + 1
1116 if( lsize .gt. 0) then
1117 allocate(outV(lsize) )
1118 call mpi_recv(outV,lsize, &
1119 MPI_INTEGER8, io_id,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
1122 call mpp_land_sync()
1125 END subroutine com_decomp1dInt8
1127 subroutine com_write1dInt(inV,lsize,outV,gsize)
1128 ! output outV and lsize
1130 integer,INTENT(in),dimension(:) :: inV
1131 integer,dimension(:) :: outV
1132 integer :: i, ierr, tag, imod, ncomsize
1133 integer :: lsize, rsize,start, gsize, end
1135 ncomsize = gsize/numprocs
1136 imod = mod(gsize,numprocs)
1138 if(my_id .eq. io_id) then
1142 if(i-1 .lt. imod) then
1143 rsize = ncomsize + 1
1149 end = start + rsize - 1
1151 if(i-1 .eq. io_id) then
1152 if(rsize .gt. 0) then
1153 outV(1:rsize) = inV(1:rsize)
1156 if(rsize .gt. 0 ) then
1157 call mpi_recv(outV(start:start+rsize-1), rsize, &
1158 MPI_INTEGER, i-1,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
1163 if(my_id .lt. imod) then
1164 lsize = ncomsize + 1
1168 if( lsize .gt. 0) then
1169 call mpi_send(inV, lsize, &
1170 MPI_INTEGER, io_id,tag,HYDRO_COMM_WORLD,ierr)
1174 call mpp_land_sync()
1176 END subroutine com_write1dInt
1178 subroutine com_write1dInt8(inV,lsize,outV,gsize)
1179 ! output outV and lsize
1181 integer(kind=int64), intent(in),dimension(:) :: inV
1182 integer(kind=int64), dimension(:) :: outV
1183 integer :: i, ierr, tag, imod, ncomsize
1184 integer :: lsize, rsize,start, gsize, end
1186 ncomsize = gsize/numprocs
1187 imod = mod(gsize,numprocs)
1189 if(my_id .eq. io_id) then
1193 if(i-1 .lt. imod) then
1194 rsize = ncomsize + 1
1200 end = start + rsize - 1
1202 if(i-1 .eq. io_id) then
1203 if(rsize .gt. 0) then
1204 outV(1:rsize) = inV(1:rsize)
1207 if(rsize .gt. 0 ) then
1208 call mpi_recv(outV(start:start+rsize-1), rsize, &
1209 MPI_INTEGER8, i-1,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
1214 if(my_id .lt. imod) then
1215 lsize = ncomsize + 1
1219 if( lsize .gt. 0) then
1220 call mpi_send(inV, lsize, &
1221 MPI_INTEGER8, io_id,tag,HYDRO_COMM_WORLD,ierr)
1225 call mpp_land_sync()
1227 END subroutine com_write1dInt8
1229 subroutine pack_decomp_int(g1bufid, ndata, nprocs_map, lnsizes, istart,bufid)
1232 integer, dimension(:) :: g1bufid, nprocs_map, lnsizes, bufid
1233 integer :: i,j,k, tag, ierr
1234 integer, allocatable,dimension(:) :: buf
1235 integer, dimension(:) :: istart
1236 integer, dimension(numprocs) :: count
1240 if(my_id .eq. io_id) then
1241 allocate(buf(ndata))
1246 buf(istart(k) + count(k)) = g1bufid(i)
1247 count(k) = count(k) + 1
1250 ! write(6,*) " count = ", count
1251 ! write(6,*) " istart = ", istart
1252 ! write(6,*) " lnsizes = ", lnsizes
1256 call mpp_land_sync()
1257 ! call hydro_finish()
1259 if(my_id .ne. IO_id) then
1261 if(lnsizes(my_id + 1) .gt. 0) then
1262 call mpi_recv(bufid,lnsizes(my_id + 1),&
1263 MPI_INTEGER,io_id,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
1266 do i = 0, numprocs - 1
1267 if(i .ne. my_id) then
1269 if(lnsizes(i+1) .gt. 0) then
1270 call mpi_send(buf(istart(i+1):istart(i+1)+lnsizes(i+1)-1), &
1271 lnsizes(i+1),MPI_INTEGER,i, tag,HYDRO_COMM_WORLD,ierr)
1274 if(lnsizes(i+1) .gt. 0) then
1275 bufid = buf(istart(i+1):istart(i+1)+lnsizes(i+1)-1)
1280 if(my_id .eq. io_id) then
1281 if(allocated(buf)) deallocate(buf)
1283 end subroutine pack_decomp_int
1285 subroutine pack_decomp_int8(g1bufid, ndata, nprocs_map, lnsizes, istart,bufid)
1288 integer, dimension(:) :: nprocs_map, lnsizes
1289 integer :: i,j,k, tag, ierr
1290 integer(kind=int64), allocatable,dimension(:) :: buf, bufid, g1bufid
1291 integer, dimension(:) :: istart
1292 integer, dimension(numprocs) :: count
1296 if(my_id .eq. io_id) then
1297 allocate(buf(ndata))
1302 buf(istart(k) + count(k)) = g1bufid(i)
1303 count(k) = count(k) + 1
1306 ! write(6,*) " count = ", count
1307 ! write(6,*) " istart = ", istart
1308 ! write(6,*) " lnsizes = ", lnsizes
1312 call mpp_land_sync()
1313 ! call hydro_finish()
1315 if(my_id .ne. IO_id) then
1317 if(lnsizes(my_id + 1) .gt. 0) then
1318 call mpi_recv(bufid,lnsizes(my_id + 1),&
1319 MPI_INTEGER8,io_id,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
1322 do i = 0, numprocs - 1
1323 if(i .ne. my_id) then
1325 if(lnsizes(i+1) .gt. 0) then
1326 call mpi_send(buf(istart(i+1):istart(i+1)+lnsizes(i+1)-1), &
1327 lnsizes(i+1),MPI_INTEGER8,i, tag,HYDRO_COMM_WORLD,ierr)
1330 if(lnsizes(i+1) .gt. 0) then
1331 bufid = buf(istart(i+1):istart(i+1)+lnsizes(i+1)-1)
1336 if(my_id .eq. io_id) then
1337 if(allocated(buf)) deallocate(buf)
1339 end subroutine pack_decomp_int8
1341 subroutine pack_decomp_real8(g1bufid, ndata, nprocs_map, lnsizes, istart,bufid)
1344 real*8, dimension(:) :: g1bufid, bufid
1345 integer,dimension(:) :: nprocs_map, lnsizes
1346 integer :: i,j,k, tag, ierr
1347 real*8, allocatable,dimension(:) :: buf
1348 integer, dimension(:) :: istart
1349 integer, dimension(numprocs) :: count
1351 if(my_id .eq. io_id) then
1352 allocate(buf(ndata))
1357 buf(istart(k) + count(k)) = g1bufid(i)
1358 count(k) = count(k) + 1
1362 call mpp_land_sync()
1363 if(my_id .ne. IO_id) then
1365 if(lnsizes(my_id + 1) .gt. 0) then
1366 call mpi_recv(bufid,lnsizes(my_id + 1),&
1367 MPI_DOUBLE_PRECISION,io_id,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
1370 do i = 0, numprocs - 1
1371 if(i .ne. my_id) then
1373 if(lnsizes(i+1) .gt. 0) then
1374 call mpi_send(buf(istart(i+1):istart(i+1)+lnsizes(i+1)-1), &
1375 lnsizes(i+1),MPI_DOUBLE_PRECISION,i, tag,HYDRO_COMM_WORLD,ierr)
1378 if(lnsizes(my_id + 1) .gt. 0) then
1379 bufid = buf(istart(i + 1):istart(i+1)+lnsizes(i+1)-1)
1384 if(my_id .eq. io_id) then
1385 if(allocated(buf)) deallocate(buf)
1387 end subroutine pack_decomp_real8
1389 ! this is used for nhdPlus with Lake.
1390 ! resolve the data from TO_NODE grids, and update back to NLINKSL grids.
1391 subroutine TONODE2RSL (ind,inVar,size,gNLINKSL,NLINKSL,ioVar,flag)
1393 integer,intent(in) :: size,gNLINKSL,NLINKSL !
1394 integer,intent(in) , dimension(size) :: ind, inVar
1395 integer,intent(inout), dimension(nlinksl) :: ioVar
1396 integer, allocatable, dimension(:) :: gvar, buf, tmpInd
1397 integer :: i,j,k, tag, ierr, tmpSize, flag
1399 if(gNLINKSL .le. 0) return
1401 if(my_id .eq. io_id) then
1402 allocate(gvar(gNLINKSL))
1406 call ReachLS_wInt(ioVar,gvar)
1408 if(my_id .eq. io_id) then
1410 if(i-1 .eq. io_id) then
1412 if(inVar(k) .ne. flag) then
1413 gvar(ind(k)) = inVar(k)
1418 call mpi_recv(tmpSize,1,MPI_INTEGER,i-1,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
1419 if(tmpSize .gt. 0) then
1420 allocate(buf(tmpSize))
1421 allocate(tmpInd(tmpSize))
1423 call mpi_recv(tmpInd, tmpSize , &
1424 MPI_INTEGER,i-1,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
1426 call mpi_recv(buf, tmpSize , &
1427 MPI_INTEGER,i-1,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
1429 if(buf(k) .ne. flag) then
1430 gvar(tmpInd(k)) = buf(k)
1433 if(allocated(buf)) deallocate(buf)
1434 if(allocated(tmpInd)) deallocate(tmpInd)
1440 call mpi_send(size,1,MPI_INTEGER,io_id,tag,HYDRO_COMM_WORLD,ierr)
1441 if(size .gt. 0) then
1443 call mpi_send(ind(1:size),size, &
1444 MPI_INTEGER,io_id,tag,HYDRO_COMM_WORLD,ierr)
1446 call mpi_send(inVar(1:size),size, &
1447 MPI_INTEGER,io_id,tag,HYDRO_COMM_WORLD,ierr)
1450 call ReachLS_decomp(gvar, ioVar)
1451 if(allocated(gvar)) deallocate(gvar)
1452 end subroutine TONODE2RSL
1454 subroutine TONODE2RSL8 (ind,inVar,size,gNLINKSL,NLINKSL,ioVar,flag)
1456 integer, intent(in) :: size,gNLINKSL,NLINKSL !
1457 integer, intent(in) , dimension(size) :: ind
1458 integer(kind=int64), intent(in) , dimension(size) ::inVar
1459 integer(kind=int64), intent(inout), dimension(nlinksl) :: ioVar
1460 integer, allocatable, dimension(:) :: tmpInd
1461 integer(kind=int64), allocatable, dimension(:) :: gvar, buf
1462 integer :: i,j,k, tag, ierr, tmpSize, flag
1464 if(gNLINKSL .le. 0) return
1466 if(my_id .eq. io_id) then
1467 allocate(gvar(gNLINKSL))
1471 call ReachLS_wInt8(ioVar,gvar)
1473 if(my_id .eq. io_id) then
1475 if(i-1 .eq. io_id) then
1477 if(inVar(k) .ne. flag) then
1478 gvar(ind(k)) = inVar(k)
1483 call mpi_recv(tmpSize,1,MPI_INTEGER,i-1,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
1484 if(tmpSize .gt. 0) then
1485 allocate(buf(tmpSize))
1486 allocate(tmpInd(tmpSize))
1488 call mpi_recv(tmpInd, tmpSize , &
1489 MPI_INTEGER,i-1,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
1491 call mpi_recv(buf, tmpSize , &
1492 MPI_INTEGER8,i-1,tag,HYDRO_COMM_WORLD,mpp_status,ierr)
1494 if(buf(k) .ne. flag) then
1495 gvar(tmpInd(k)) = buf(k)
1498 if(allocated(buf)) deallocate(buf)
1499 if(allocated(tmpInd)) deallocate(tmpInd)
1505 call mpi_send(size,1,MPI_INTEGER,io_id,tag,HYDRO_COMM_WORLD,ierr)
1506 if(size .gt. 0) then
1508 call mpi_send(ind(1:size),size, &
1509 MPI_INTEGER,io_id,tag,HYDRO_COMM_WORLD,ierr)
1511 call mpi_send(inVar(1:size),size, &
1512 MPI_INTEGER8,io_id,tag,HYDRO_COMM_WORLD,ierr)
1515 call ReachLS_decomp(gvar, ioVar)
1516 if(allocated(gvar)) deallocate(gvar)
1517 end subroutine TONODE2RSL8
1519 END MODULE MODULE_mpp_ReachLS