mod_oasis_coupler.F90 82 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069
  1. !> Initialize the OASIS coupler infrastructure
  2. MODULE mod_oasis_coupler
  3. ! - - - - - - - - - - - - - - - - - - - - - - - - - - -
  4. !
  5. USE mod_oasis_kinds
  6. USE mod_oasis_data
  7. USE mod_oasis_parameters
  8. USE mod_oasis_namcouple
  9. USE mod_oasis_sys
  10. USE mod_oasis_map
  11. USE mod_oasis_part
  12. USE mod_oasis_var
  13. USE mod_oasis_mpi
  14. USE mod_oasis_string
  15. USE mod_oasis_io
  16. USE mod_oasis_timer
  17. USE mct_mod
  18. USE grids ! scrip
  19. USE netcdf
  20. IMPLICIT NONE
  21. private
  22. public oasis_coupler_setup
  23. ! Type of data
  24. public prism_router_type
  25. public prism_coupler_type
  26. ! COUPLING INFO
  27. !> Router information for rearranging data on tasks
  28. type prism_router_type
  29. !--- fixed at initialization ---
  30. type(mct_router) :: router !< router
  31. end type prism_router_type
  32. integer(kind=ip_i4_p),public,parameter :: prism_coupler_avsmax=5 !< maximum number of higher order terms in mapping
  33. !> Coupler data for managing all aspects of coupling in OASIS
  34. type prism_coupler_type
  35. !--- fixed at initialization ---
  36. type(mct_aVect) :: aVect1 !< primary aVect
  37. type(mct_aVect) :: aVect1m !< extra aVect needed for mapping
  38. type(mct_aVect) :: aVect2 !< higher order mapping data
  39. type(mct_aVect) :: aVect3 !< higher order mapping data
  40. type(mct_aVect) :: aVect4 !< higher order mapping data
  41. type(mct_aVect) :: aVect5 !< higher order mapping data
  42. logical :: aVon(prism_coupler_avsmax) !< flags indicating whether aVects 2-5 are active
  43. character(len=ic_xl) :: rstfile !< restart file
  44. character(len=ic_xl) :: inpfile !< input file if data is read
  45. character(len=ic_xl) :: fldlist !< field list
  46. integer(kind=ip_i4_p) :: nflds !< number of fields
  47. integer(kind=ip_i4_p),pointer :: varid(:) !< varid for each field
  48. logical :: valid !< is this coupler valid
  49. integer(kind=ip_i4_p) :: namID !< namcouple ID
  50. integer(kind=ip_i4_p) :: partID !< local variable partition ID
  51. integer(kind=ip_i4_p) :: rpartID !< router partition ID
  52. integer(kind=ip_i4_p) :: routerID !< router ID
  53. integer(kind=ip_i4_p) :: mapperID !< mapper ID
  54. character(len=ic_med) :: maploc !< map location setting, src or dst
  55. integer(kind=ip_i4_p) :: ops !< namcouple operation (ip_exported,...)
  56. integer(kind=ip_i4_p) :: comp !< other model compid to couple
  57. integer(kind=ip_i4_p) :: tag !< communcation tag
  58. integer(kind=ip_i4_p) :: seq !< sequence number
  59. integer(kind=ip_i4_p) :: dt !< coupling period (secs)
  60. integer(kind=ip_i4_p) :: lag !< put lag positive is put sooner (secs)
  61. integer(kind=ip_i4_p) :: maxtime !< max time for the coupler
  62. integer(kind=ip_i4_p) :: trans !< transformation (ip_average,...)
  63. integer(kind=ip_i4_p) :: conserv !< conserve operation (ip_cnone,ip_cglobal,...)
  64. character(len=ic_med) :: consopt !< conserve option (bfb, opt)
  65. integer(kind=ip_i4_p) :: getput !< get/put flag
  66. logical :: sndrcv !< send recv flag
  67. logical :: output !< output flag
  68. logical :: input !< input flag
  69. logical :: snddiag !< diagnose src fields as part of coupling
  70. logical :: rcvdiag !< diagnose rcv fields as part of coupling
  71. real(kind=ip_double_p):: sndmult !< send field multiplier term
  72. real(kind=ip_double_p):: sndadd !< send field addition term
  73. real(kind=ip_double_p):: rcvmult !< receive field multiplier term
  74. real(kind=ip_double_p):: rcvadd !< receive field addition term
  75. !--- time varying info ---
  76. integer(kind=ip_i4_p) :: ltime !< time at last coupling
  77. integer(kind=ip_i4_p),pointer :: avcnt(:) !< counter for averaging
  78. integer(kind=ip_i4_p),pointer :: status(:) !< status of variables in coupler
  79. end type prism_coupler_type
  80. integer(kind=ip_i4_p) :: prism_mrouter !< max routers
  81. integer(kind=ip_i4_p) :: prism_nrouter = 0 !< router counter
  82. type(prism_router_type) ,public, pointer:: prism_router(:) !< prism_router array
  83. integer(kind=ip_i4_p) ,public :: prism_mcoupler !< max couplers
  84. type(prism_coupler_type),public, pointer :: prism_coupler_put(:) !< prism_coupler put array
  85. type(prism_coupler_type),public, pointer :: prism_coupler_get(:) !< prism_coupler get array
  86. integer(kind=ip_i4_p) ,public :: lcouplerid !< last coupler id
  87. integer(kind=ip_i4_p) ,public :: lcouplertime !< last coupler time
  88. integer(kind=ip_i4_p) ,public :: lastseq !< last coupler sequence
  89. integer(kind=ip_i4_p) ,public :: lastseqtime !< last coupler sequence time
  90. !#include <netcdf.inc>
  91. !------------------------------------------------------------
  92. CONTAINS
  93. !------------------------------------------------------------
  94. !> Main routine to setup couplers
  95. !> This routine initializes all the coupler data based on the namcouple
  96. !> inputs and the calls into the OASIS initialization interfaces from models.
  97. !> It reconciles everything. This is called from oasis_enddef.
  98. SUBROUTINE oasis_coupler_setup()
  99. !----------------------------------------------------------
  100. ! This routine reconciles the coupling stuff
  101. !----------------------------------------------------------
  102. IMPLICIT none
  103. integer(kind=ip_i4_p) :: n,n1,n2,nn,nv,nm,nv1,nv1a,nns,lnn,nc,nf,nvf,npc,r1
  104. integer(kind=ip_i4_p) :: pe
  105. integer(kind=ip_i4_p) :: part1, part2
  106. integer(kind=ip_i4_p) :: spart,dpart ! src, dst partitions for mapping
  107. ! part1 = my local part, partID
  108. ! part2 = other partition for mapping
  109. ! spart = src part for mapping; put=part1, get=part2
  110. ! dpart = dst part for mapping; put=part2, get=part1
  111. integer(kind=ip_i4_p) :: mapID,namID
  112. type(mct_sMat),pointer :: sMati(:)
  113. integer(kind=ip_i4_p) :: ncid,dimid,status
  114. integer(kind=ip_i4_p) :: lsize,gsize
  115. integer(kind=ip_i4_p) :: svarid
  116. integer(kind=ip_i4_p),allocatable :: varidtmp(:)
  117. integer(kind=ip_i4_p) :: part
  118. character(len=ic_med) :: cstring
  119. character(len=ic_lvar):: myfld
  120. integer(kind=ip_i4_p) :: myfldi
  121. character(len=ic_xl) :: myfldlist ! field list
  122. character(len=ic_lvar):: otfld
  123. character(len=ic_xl) :: otfldlist ! field list
  124. integer(kind=ip_i4_p) :: nx,ny
  125. character(len=ic_lvar):: gridname
  126. character(len=ic_long):: tmp_mapfile
  127. integer(kind=ip_i4_p) :: flag
  128. logical :: found, exists, found2
  129. integer(kind=ip_i4_p) :: mynvar
  130. integer(kind=ip_i4_p) :: nwgts
  131. character(len=ic_lvar):: tmpfld
  132. type(prism_coupler_type),pointer :: pcpointer
  133. type(prism_coupler_type),pointer :: pcpntpair
  134. integer(kind=ip_i4_p) :: ifind,nfind
  135. character(len=ic_lvar),pointer :: myvar(:)
  136. integer(kind=ip_i4_p) ,pointer :: myops(:)
  137. integer(kind=ip_i4_p) ,pointer :: nallvar(:)
  138. character(len=ic_lvar),pointer :: allvar(:,:)
  139. integer(kind=ip_i4_p) ,pointer :: allops(:,:)
  140. integer(kind=ip_i4_p) ,pointer :: namsrc_checkused(:) ! 0 = not used
  141. integer(kind=ip_i4_p) ,pointer :: namsrc_checkused_g(:) ! 0 = not used
  142. type sortnamfld_type
  143. integer(kind=ip_i4_p) :: num ! total number of namcouple fields
  144. integer(kind=ip_i4_p) ,pointer :: namnum(:) ! namcouple number
  145. integer(kind=ip_i4_p) ,pointer :: fldnum(:) ! namcouple field number in namcouple
  146. character(len=ic_lvar),pointer :: fld(:) ! namcouple field name
  147. end type sortnamfld_type
  148. type(sortnamfld_type) :: sortnsrc
  149. type(sortnamfld_type) :: sortndst
  150. type sortvarfld_type
  151. integer(kind=ip_i4_p) :: num ! total number of var fields
  152. integer(kind=ip_i4_p) ,pointer :: modnum(:) ! model number
  153. integer(kind=ip_i4_p) ,pointer :: varnum(:) ! var field number in model
  154. character(len=ic_lvar),pointer :: fld(:) ! variable field name
  155. end type sortvarfld_type
  156. type(sortvarfld_type) :: sortvars
  157. type(sortvarfld_type) :: sorttest
  158. integer(kind=ip_i4_p) ,pointer :: sortkey(:)
  159. ! character(len=*),parameter :: smatread_method = 'orig'
  160. character(len=*),parameter :: smatread_method = 'ceg'
  161. logical, parameter :: local_timers_on = .false.
  162. character(len=*),parameter :: subname = '(oasis_coupler_setup)'
  163. !----------------------------------------------------------
  164. call oasis_debug_enter(subname)
  165. ! call oasis_mpi_barrier(mpi_comm_global)
  166. IF (local_timers_on) call oasis_timer_start('cpl_setup')
  167. if (local_timers_on) call oasis_timer_start('cpl_setup_n1')
  168. write(nulprt,*) subname,' smatread_method = ',trim(smatread_method)
  169. !-----------------------------------------
  170. !> * Allocate and zero prism_router, prism_mapper, prism_coupler based on nnamcpl
  171. ! there cannot be more than that needed
  172. !-----------------------------------------
  173. call oasis_debug_note(subname//' set defaults for datatypes')
  174. prism_mrouter = nnamcpl * 2 ! multiply by 2 for coupling to self
  175. allocate(prism_router(prism_mrouter))
  176. prism_nrouter = 0
  177. prism_mmapper = nnamcpl
  178. allocate(prism_mapper(prism_mmapper))
  179. prism_nmapper = 0
  180. prism_mapper(:)%nwgts = 0
  181. prism_mapper(:)%file = ""
  182. prism_mapper(:)%loc = ""
  183. prism_mapper(:)%opt = ""
  184. prism_mapper(:)%optval= ""
  185. prism_mapper(:)%init = .false.
  186. prism_mapper(:)%spart = ispval
  187. prism_mapper(:)%dpart = ispval
  188. prism_mapper(:)%AVred = .false.
  189. prism_mcoupler = nnamcpl
  190. allocate(prism_coupler_put(prism_mcoupler))
  191. allocate(prism_coupler_get(prism_mcoupler))
  192. do nc = 1,prism_mcoupler
  193. do npc = 1,2
  194. if (npc == 1) then
  195. pcpointer => prism_coupler_put(nc)
  196. pcpntpair => prism_coupler_get(nc)
  197. endif
  198. if (npc == 2) then
  199. pcpointer => prism_coupler_get(nc)
  200. pcpntpair => prism_coupler_put(nc)
  201. endif
  202. pcpointer%rstfile = ""
  203. pcpointer%inpfile = ""
  204. pcpointer%fldlist = ""
  205. pcpointer%nflds = 0
  206. pcpointer%namID = 0
  207. pcpointer%valid = .false.
  208. !tcx is this alloc pcpointer or prism_coupler_*
  209. allocate(pcpointer%varid(1))
  210. pcpointer%varid(:) = ispval
  211. pcpointer%aVon(:) = .false.
  212. pcpointer%ops = ispval
  213. pcpointer%comp = ispval
  214. pcpointer%routerID = ispval
  215. pcpointer%mapperID = ispval
  216. pcpointer%maploc = ""
  217. pcpointer%tag = ispval
  218. pcpointer%dt = ispval
  219. pcpointer%lag = 0
  220. pcpointer%maxtime = 0
  221. pcpointer%getput = ispval
  222. pcpointer%sndrcv = .false.
  223. pcpointer%output = .false.
  224. pcpointer%input = .false.
  225. pcpointer%trans = ip_instant
  226. pcpointer%conserv = ip_cnone
  227. pcpointer%ltime = ispval
  228. pcpointer%snddiag = .false.
  229. pcpointer%rcvdiag = .false.
  230. pcpointer%sndmult = 1.0_ip_double_p
  231. pcpointer%sndadd = 0.0_ip_double_p
  232. pcpointer%rcvmult = 1.0_ip_double_p
  233. pcpointer%rcvadd = 0.0_ip_double_p
  234. enddo ! npc
  235. enddo ! nc
  236. lcouplerid = ispval
  237. lcouplertime = ispval
  238. lastseq = ispval
  239. lastseqtime = ispval
  240. !----------------------------------------------------------
  241. !> * Generate model variable lists across all models based on def_var calls.
  242. !> These will be reconciled with the namcouple input. These are sorted
  243. !> to improve search performance later.
  244. !----------------------------------------------------------
  245. call oasis_debug_note(subname//' share var info between models')
  246. allocate(allvar(maxvar,prism_amodels))
  247. allocate(nallvar(prism_amodels))
  248. allocate(allops(maxvar,prism_amodels))
  249. allocate(myvar(maxvar))
  250. allocate(myops(maxvar))
  251. allvar = " "
  252. nallvar = 0
  253. allops = -1
  254. if (local_timers_on) call oasis_timer_start('cpl_setup_n1_bcast')
  255. do n = 1,prism_amodels
  256. if (n == compid) then
  257. myvar = " "
  258. myops = 0
  259. mynvar = prism_nvar
  260. do n1 = 1, prism_nvar
  261. myvar(n1) = trim(prism_var(n1)%name)
  262. myops(n1) = prism_var(n1)%ops
  263. ! check that each var name is unique for a given model
  264. do n2 = 1,n1-1
  265. if (myvar(n1) == myvar(n2)) then
  266. WRITE(nulprt,*) subname,estr,'variable name defined more than once by def_var = ',trim(myvar(n1))
  267. call oasis_abort()
  268. endif
  269. enddo
  270. enddo
  271. endif
  272. if (OASIS_debug >= 5) then
  273. write(nulprt,*) subname,' BCAST from ',n,mpi_root_global(n)
  274. call oasis_flush(nulprt)
  275. endif
  276. call oasis_mpi_bcast(mynvar,mpi_comm_global,'mynvar',mpi_root_global(n))
  277. if (OASIS_debug >= 5) then
  278. write(nulprt,*) subname,' bcast mynvar ',mynvar
  279. call oasis_flush(nulprt)
  280. endif
  281. nallvar(n) = mynvar
  282. call oasis_mpi_bcast(myvar,mpi_comm_global,'myvar',mpi_root_global(n))
  283. if (OASIS_debug >= 5) then
  284. write(nulprt,*) subname,' bcast myvar ',trim(myvar(1))
  285. call oasis_flush(nulprt)
  286. endif
  287. allvar(:,n) = myvar(:)
  288. call oasis_mpi_bcast(myops,mpi_comm_global,'myops',mpi_root_global(n))
  289. if (OASIS_debug >= 5) then
  290. write(nulprt,*) subname,' bcast myops ',myops(1)
  291. call oasis_flush(nulprt)
  292. endif
  293. allops(:,n) = myops(:)
  294. enddo
  295. if (local_timers_on) call oasis_timer_stop('cpl_setup_n1_bcast')
  296. deallocate(myvar,myops)
  297. if (OASIS_debug >= 2) then
  298. write(nulprt,*) subname,' model variable info:'
  299. do nm = 1,prism_amodels
  300. write(nulprt,'(8x,a,2i6)') ' model,nvars = ',nm,nallvar(nm)
  301. do nv = 1,nallvar(nm)
  302. cstring = 'unknown'
  303. if (allops(nv,nm) == OASIS_Out) cstring = 'prism_out'
  304. if (allops(nv,nm) == OASIS_In) cstring = 'prism_in'
  305. write(nulprt,'(16x,a,2i6,2x,a,i6,2x,a)') ' model,idx,var,ops = ',nm,nv,&
  306. trim(allvar(nv,nm)),allops(nv,nm),&
  307. trim(cstring)
  308. enddo
  309. enddo
  310. write(nulprt,*) ' '
  311. call oasis_flush(nulprt)
  312. endif
  313. ! generate sortvars sorted list
  314. n1 = 0
  315. do n = 1,prism_amodels
  316. n1 = n1 + nallvar(n)
  317. enddo
  318. allocate(sortvars%fld(n1))
  319. allocate(sortvars%modnum(n1))
  320. allocate(sortvars%varnum(n1))
  321. allocate(sortkey(n1))
  322. sortvars%num = n1
  323. n1 = 0
  324. do n = 1,prism_amodels
  325. do n2 = 1,nallvar(n)
  326. n1 = n1 + 1
  327. sortkey(n1) = n1
  328. sortvars%fld(n1) = allvar(n2,n)
  329. sortvars%modnum(n1) = n
  330. sortvars%varnum(n1) = n2
  331. enddo
  332. enddo
  333. call cplsort(sortvars%num, sortvars%fld, sortkey)
  334. call cplsortkey(sortvars%num, sortvars%modnum, sortkey)
  335. call cplsortkey(sortvars%num, sortvars%varnum, sortkey)
  336. if (OASIS_debug >= 15) then
  337. write(nulprt,*) subname//' Sorted array : sortvars'
  338. do n1 = 1,sortvars%num
  339. write(nulprt,*) subname,'sort sortvars',n1,sortkey(n1),sortvars%modnum(n1),sortvars%varnum(n1),trim(sortvars%fld(n1))
  340. enddo
  341. endif
  342. deallocate(sortkey)
  343. !----------------------------------------------------------
  344. !> * Setup couplers based on namcouple and model variable info.
  345. ! These must be paired up consistently, create couplers in
  346. ! sorted order (nns)
  347. ! nn = namcpl counter, sorted
  348. ! nm = model counter, compid is my nm
  349. ! nv = variable counter
  350. ! nv1 = my variable counter
  351. !----------------------------------------------------------
  352. if (local_timers_on) call oasis_timer_stop ('cpl_setup_n1')
  353. !--------------------------------
  354. !> * Preprocess namcouple strings and sort for faster searches
  355. !--------------------------------
  356. ! count namcouple field names
  357. if (local_timers_on) call oasis_timer_start('cpl_setup_n2')
  358. n1 = 0
  359. n2 = 0
  360. do nn = 1,nnamcpl
  361. n1 = n1 + oasis_string_listGetNum(namsrcfld(nn))
  362. n2 = n2 + oasis_string_listGetNum(namdstfld(nn))
  363. if (n1 /= n2) then
  364. WRITE(nulprt,*) subname,estr,'number of fields in namcouple inconsistent ',nn,n1,n2
  365. WRITE(nulprt,*) subname,estr,'namcouple src fields = ',trim(namsrcfld(nn))
  366. WRITE(nulprt,*) subname,estr,'namcouple dst fields = ',trim(namdstfld(nn))
  367. call oasis_abort()
  368. endif
  369. enddo
  370. ! allocate space
  371. ! note: n2==n1
  372. sortnsrc%num = n1
  373. allocate(sortnsrc%fld(n1))
  374. allocate(sortnsrc%namnum(n1))
  375. allocate(sortnsrc%fldnum(n1))
  376. sortndst%num = n2
  377. allocate(sortndst%fld(n2))
  378. allocate(sortndst%namnum(n2))
  379. allocate(sortndst%fldnum(n2))
  380. ! this will check that all namcouple vars are used in application
  381. allocate(namsrc_checkused(sortnsrc%num))
  382. namsrc_checkused = 0
  383. ! fill and sort sortnsrc
  384. allocate(sortkey(sortnsrc%num))
  385. n1 = 0
  386. do nn = 1,nnamcpl
  387. do n2 = 1,oasis_string_listGetNum(namsrcfld(nn))
  388. n1 = n1 + 1
  389. sortkey(n1) = n1
  390. sortnsrc%namnum(n1) = nn
  391. sortnsrc%fldnum(n1) = n2
  392. call oasis_string_listGetName(namsrcfld(nn),n2,sortnsrc%fld(n1))
  393. enddo
  394. enddo
  395. call cplsort(sortnsrc%num, sortnsrc%fld, sortkey)
  396. call cplsortkey(sortnsrc%num, sortnsrc%namnum, sortkey)
  397. call cplsortkey(sortnsrc%num, sortnsrc%fldnum, sortkey)
  398. if (OASIS_debug >= 15) then
  399. write(nulprt,*) subname//' Sorted array : sortnsrc'
  400. do n1 = 1,sortnsrc%num
  401. write(nulprt,*) subname,'sort sortnsrc',n1,sortkey(n1), &
  402. sortnsrc%namnum(n1),sortnsrc%fldnum(n1),trim(sortnsrc%fld(n1))
  403. enddo
  404. endif
  405. deallocate(sortkey)
  406. ! fill and sort sortndst
  407. allocate(sortkey(sortndst%num))
  408. n1 = 0
  409. do nn = 1,nnamcpl
  410. do n2 = 1,oasis_string_listGetNum(namdstfld(nn))
  411. n1 = n1 + 1
  412. sortkey(n1) = n1
  413. sortndst%namnum(n1) = nn
  414. sortndst%fldnum(n1) = n2
  415. call oasis_string_listGetName(namdstfld(nn),n2,sortndst%fld(n1))
  416. enddo
  417. enddo
  418. call cplsort(sortndst%num, sortndst%fld, sortkey)
  419. call cplsortkey(sortndst%num, sortndst%namnum, sortkey)
  420. call cplsortkey(sortndst%num, sortndst%fldnum, sortkey)
  421. if (OASIS_debug >= 15) then
  422. write(nulprt,*) subname//' Sorted array : sortndst'
  423. do n1 = 1,sortndst%num
  424. write(nulprt,*) subname,'sort sortndst',n1,sortkey(n1), &
  425. sortndst%namnum(n1),sortndst%fldnum(n1),trim(sortndst%fld(n1))
  426. enddo
  427. endif
  428. deallocate(sortkey)
  429. if (OASIS_debug >= 1500) then
  430. write(nulprt,*) subname,' Test sort code: '
  431. n1 = 10
  432. allocate(sorttest%fld(n1))
  433. allocate(sorttest%modnum(n1))
  434. allocate(sorttest%varnum(n1))
  435. allocate(sortkey(n1))
  436. sorttest%num = n1
  437. sorttest%fld(:) = 'A'
  438. do n1 = 1,sorttest%num
  439. sortkey(n1) = n1
  440. if (n1 == 1) sorttest%fld(n1) = 'D'
  441. if (n1 == 2) sorttest%fld(n1) = 'C'
  442. if (n1 == 4) sorttest%fld(n1) = 'C'
  443. if (n1 == 5) sorttest%fld(n1) = 'D'
  444. if (n1 == 8) sorttest%fld(n1) = 'C'
  445. if (n1 == 9) sorttest%fld(n1) = 'B'
  446. if (n1 == 10) sorttest%fld(n1) = 'C'
  447. sorttest%modnum(n1) = n1+100
  448. sorttest%varnum(n1) = n1
  449. enddo
  450. call cplsort(sorttest%num, sorttest%fld, sortkey)
  451. call cplsortkey(sorttest%num, sorttest%modnum, sortkey)
  452. call cplsortkey(sorttest%num, sorttest%varnum, sortkey)
  453. write(nulprt,*) subname//' Sorted array : sorttest'
  454. do n1 = 1,sorttest%num
  455. write(nulprt,*) subname,'sort sorttest',n1,sortkey(n1), &
  456. sorttest%modnum(n1),sorttest%varnum(n1),trim(sorttest%fld(n1))
  457. enddo
  458. tmpfld = 'A'
  459. call cplfind(sorttest%num, sorttest%fld, tmpfld, ifind, nfind)
  460. write(nulprt,*) subname,' cpl find1 ',trim(tmpfld),ifind,nfind
  461. do n1 = ifind,ifind+nfind-1
  462. write(nulprt,*) subname,' cpl find2 ',n1,trim(sorttest%fld(n1))
  463. enddo
  464. tmpfld = 'B'
  465. call cplfind(sorttest%num, sorttest%fld, tmpfld, ifind, nfind)
  466. write(nulprt,*) subname,' cpl find1 ',trim(tmpfld),ifind,nfind
  467. do n1 = ifind,ifind+nfind-1
  468. write(nulprt,*) subname,' cpl find2 ',n1,trim(sorttest%fld(n1))
  469. enddo
  470. tmpfld = 'C'
  471. call cplfind(sorttest%num, sorttest%fld, tmpfld, ifind, nfind)
  472. write(nulprt,*) subname,' cpl find1 ',trim(tmpfld),ifind,nfind
  473. do n1 = ifind,ifind+nfind-1
  474. write(nulprt,*) subname,' cpl find2 ',n1,trim(sorttest%fld(n1))
  475. enddo
  476. tmpfld = 'D'
  477. call cplfind(sorttest%num, sorttest%fld, tmpfld, ifind, nfind)
  478. write(nulprt,*) subname,' cpl find1 ',trim(tmpfld),ifind,nfind
  479. do n1 = ifind,ifind+nfind-1
  480. write(nulprt,*) subname,' cpl find2 ',n1,trim(sorttest%fld(n1))
  481. enddo
  482. tmpfld = 'E'
  483. call cplfind(sorttest%num, sorttest%fld, tmpfld, ifind, nfind)
  484. write(nulprt,*) subname,' cpl find1 ',trim(tmpfld),ifind,nfind
  485. do n1 = ifind,ifind+nfind-1
  486. write(nulprt,*) subname,' cpl find2 ',n1,trim(sorttest%fld(n1))
  487. enddo
  488. deallocate(sortkey)
  489. deallocate(sorttest%fld)
  490. deallocate(sorttest%modnum)
  491. deallocate(sorttest%varnum)
  492. write(nulprt,*) subname,' Test cplfind: '
  493. n1 = max(min(sortndst%num,sortndst%num/3),1)
  494. tmpfld = sortndst%fld(n1)
  495. call cplfind(sortndst%num, sortndst%fld, tmpfld, ifind, nfind)
  496. write(nulprt,*) subname,' cpl find1 ',trim(tmpfld),ifind,nfind
  497. do n1 = ifind,ifind+nfind-1
  498. write(nulprt,*) subname,' cpl find2 ',n1,trim(sortndst%fld(n1))
  499. enddo
  500. n1 = max(min(sortndst%num,1),1)
  501. tmpfld = sortndst%fld(n1)
  502. call cplfind(sortndst%num, sortndst%fld, tmpfld, ifind, nfind)
  503. write(nulprt,*) subname,' cpl find1 ',trim(tmpfld),ifind,nfind
  504. do n1 = ifind,ifind+nfind-1
  505. write(nulprt,*) subname,' cpl find2 ',n1,trim(sortndst%fld(n1))
  506. enddo
  507. n1 = max(min(sortndst%num,2),1)
  508. tmpfld = sortndst%fld(n1)
  509. call cplfind(sortndst%num, sortndst%fld, tmpfld, ifind, nfind)
  510. write(nulprt,*) subname,' cpl find1 ',trim(tmpfld),ifind,nfind
  511. do n1 = ifind,ifind+nfind-1
  512. write(nulprt,*) subname,' cpl find2 ',n1,trim(sortndst%fld(n1))
  513. enddo
  514. n1 = max(min(sortndst%num,sortndst%num-1),1)
  515. tmpfld = sortndst%fld(n1)
  516. call cplfind(sortndst%num, sortndst%fld, tmpfld, ifind, nfind)
  517. write(nulprt,*) subname,' cpl find1 ',trim(tmpfld),ifind,nfind
  518. do n1 = ifind,ifind+nfind-1
  519. write(nulprt,*) subname,' cpl find2 ',n1,trim(sortndst%fld(n1))
  520. enddo
  521. n1 = max(min(sortndst%num,sortndst%num),1)
  522. tmpfld = sortndst%fld(n1)
  523. call cplfind(sortndst%num, sortndst%fld, tmpfld, ifind, nfind)
  524. write(nulprt,*) subname,' cpl find1 ',trim(tmpfld),ifind,nfind
  525. do n1 = ifind,ifind+nfind-1
  526. write(nulprt,*) subname,' cpl find2 ',n1,trim(sortndst%fld(n1))
  527. enddo
  528. CALL oasis_flush(nulprt)
  529. endif
  530. if (local_timers_on) call oasis_timer_stop ('cpl_setup_n2')
  531. call oasis_debug_note(subname//' compare vars and namcouple')
  532. call oasis_debug_note(subname//' setup couplers')
  533. if (local_timers_on) call oasis_timer_start('cpl_setup_n3')
  534. !--------------------------------
  535. !> * Loop over all my model variables
  536. !--------------------------------
  537. do nv1 = 1,prism_nvar
  538. !--------------------------------
  539. !> * Get parition and field information
  540. !--------------------------------
  541. part1 = prism_var(nv1)%part
  542. myfld = prism_var(nv1)%name
  543. IF (OASIS_debug >= 20) THEN
  544. WRITE(nulprt,*) ' '
  545. WRITE(nulprt,*) subname,' get part and fld ',nv1,part1,trim(myfld)
  546. CALL oasis_flush(nulprt)
  547. ENDIF
  548. !--------------------------------
  549. !> * Check if variable is In or Out and then find namcouple matches
  550. !--------------------------------
  551. if (local_timers_on) call oasis_timer_start('cpl_setup_n3a')
  552. if (prism_var(nv1)%ops == OASIS_Out) then
  553. call cplfind(sortnsrc%num, sortnsrc%fld, myfld, ifind, nfind)
  554. elseif (prism_var(nv1)%ops == OASIS_In) then
  555. call cplfind(sortndst%num, sortndst%fld, myfld, ifind, nfind)
  556. endif
  557. if (local_timers_on) call oasis_timer_stop ('cpl_setup_n3a')
  558. !--------------------------------
  559. !> * Loop over the namcouple matches
  560. !--------------------------------
  561. do nf = ifind,ifind+nfind-1
  562. if (local_timers_on) call oasis_timer_start('cpl_setup_n3b')
  563. flag = OASIS_NotDef
  564. if (prism_var(nv1)%ops == OASIS_Out) then
  565. nn = sortnsrc%namnum(nf)
  566. myfldi = sortnsrc%fldnum(nf)
  567. myfldlist = namsrcfld(nn)
  568. otfldlist = namdstfld(nn)
  569. flag = OASIS_Out
  570. elseif (prism_var(nv1)%ops == OASIS_In) then
  571. nn = sortndst%namnum(nf)
  572. myfldi = sortndst%fldnum(nf)
  573. myfldlist = namdstfld(nn)
  574. otfldlist = namsrcfld(nn)
  575. flag = OASIS_In
  576. endif
  577. nns = namnn2sort(nn)
  578. IF (OASIS_debug >= 20) THEN
  579. WRITE(nulprt,*) subname,' found fld1 ',trim(myfld),nv1,nf
  580. WRITE(nulprt,*) subname,' found fld2 ',trim(myfld),nns,nn,myfldi,flag
  581. CALL oasis_flush(nulprt)
  582. ENDIF
  583. if (local_timers_on) call oasis_timer_stop ('cpl_setup_n3b')
  584. !--------------------------------
  585. ! my variable is in this namcouple input
  586. !--------------------------------
  587. if (flag /= OASIS_NotDef) then
  588. if (local_timers_on) call oasis_timer_start('cpl_setup_n3c')
  589. !--------------------------------
  590. !> * Migrate namcouple info into part
  591. !--------------------------------
  592. IF (OASIS_debug >= 20) THEN
  593. WRITE(nulprt,*) subname,' migrate namcouple to part '
  594. CALL oasis_flush(nulprt)
  595. ENDIF
  596. if (flag == OASIS_In) then
  597. if (prism_part(part1)%nx < 1) then
  598. prism_part(part1)%nx = namdst_nx(nn)
  599. prism_part(part1)%ny = namdst_ny(nn)
  600. prism_part(part1)%gridname = trim(namdstgrd(nn))
  601. endif
  602. endif
  603. if (flag == OASIS_Out) then
  604. if (prism_part(part1)%nx < 1) then
  605. prism_part(part1)%nx = namsrc_nx(nn)
  606. prism_part(part1)%ny = namsrc_ny(nn)
  607. prism_part(part1)%gridname = trim(namsrcgrd(nn))
  608. endif
  609. endif
  610. IF (OASIS_debug >= 20) THEN
  611. WRITE(nulprt,*) subname,' Field : ',trim(prism_var(nn)%name)
  612. WRITE(nulprt,*) subname,' Grid dst : ',trim(namdstgrd(nn))
  613. WRITE(nulprt,*) subname,' Grid src : ',trim(namsrcgrd(nn))
  614. ! WRITE(nulprt,*) subname,' prism_part : ',prism_part(part1)%gridname
  615. CALL oasis_flush(nulprt)
  616. ENDIF
  617. !--------------------------------
  618. !> * Make sure it's either an In or Out, sanity check
  619. !--------------------------------
  620. if (flag /= OASIS_In .and. flag /= OASIS_Out) then
  621. write(nulprt,*) subname,estr,'var must be either OASIS_In or OASIS_Out for var = ',trim(myfld)
  622. call oasis_abort()
  623. endif
  624. if (OASIS_debug >= 20) then
  625. write(nulprt,'(1x,2a,4i6,2a)') subname,' ca: myfld',nn,compid,&
  626. nv1,myfldi,' ',trim(myfld)
  627. call oasis_flush(nulprt)
  628. endif
  629. !--------------------------------
  630. !> * Determine matching field name from namcouple
  631. !--------------------------------
  632. if (local_timers_on) call oasis_timer_start('cpl_setup_n3c1')
  633. otfld = 'NOmatchNOyesNOyesNO'
  634. call oasis_string_listGetName(otfldlist,myfldi,otfld)
  635. if (local_timers_on) call oasis_timer_stop ('cpl_setup_n3c1')
  636. IF (OASIS_debug >= 20) THEN
  637. WRITE(nulprt,*) subname,' otfld ',trim(otfld)
  638. CALL oasis_flush(nulprt)
  639. ENDIF
  640. !--------------------------------
  641. !> * Search for list of models with other variable
  642. !--------------------------------
  643. if (local_timers_on) call oasis_timer_start('cpl_setup_n3c2')
  644. call cplfind(sortvars%num, sortvars%fld, otfld, ifind, nfind)
  645. if (local_timers_on) call oasis_timer_stop ('cpl_setup_n3c2')
  646. if (local_timers_on) call oasis_timer_stop ('cpl_setup_n3c')
  647. !--------------------------------
  648. !> * Loop over those other matching variable names
  649. !--------------------------------
  650. found = .false.
  651. do nvf = ifind, ifind+nfind-1
  652. ! check used appropriate array value, we are using "src" side sorted list
  653. ! if output, just set the nf value
  654. ! if input, search for an nn and myfldi match in the list
  655. if (prism_var(nv1)%ops == OASIS_Out) then
  656. namsrc_checkused(nf) = 1
  657. if (OASIS_debug >= 20) then
  658. write(nulprt,*) subname,' set src checkused ',trim(myfld),':',trim(otfld),nf
  659. call oasis_flush(nulprt)
  660. endif
  661. endif
  662. if (prism_var(nv1)%ops == OASIS_In) then
  663. n1 = 0
  664. found2 = .false.
  665. do while (n1 < sortnsrc%num .and. .not.found2)
  666. n1 = n1 + 1
  667. if (nn == sortnsrc%namnum(n1) .and. myfldi == sortnsrc%fldnum(n1)) then
  668. namsrc_checkused(n1) = 1
  669. found2 = .true.
  670. if (OASIS_debug >= 20) then
  671. write(nulprt,*) subname,' set dst checkused ',trim(myfld),':',trim(otfld),n1
  672. call oasis_flush(nulprt)
  673. endif
  674. endif
  675. enddo
  676. endif
  677. if (local_timers_on) call oasis_timer_start('cpl_setup_n3d')
  678. nm = sortvars%modnum(nvf)
  679. nv = sortvars%varnum(nvf)
  680. if (OASIS_debug >= 20) then
  681. write(nulprt,*) subname,' match otfld ',trim(otfld),nn
  682. call oasis_flush(nulprt)
  683. endif
  684. !--------------------------------
  685. !> * Check that one side is In and other side is Out for communication
  686. !> * Check if input or output, field name should match on both sides.
  687. !--------------------------------
  688. if (namfldops(nn) == ip_exported .or. namfldops(nn) == ip_expout) then
  689. ! tcraig allow this now
  690. ! if (nm == compid) then
  691. ! write(nulprt,*) subname,estr,'send recv pair on same model = ', &
  692. ! trim(myfld),' ',trim(otfld)
  693. ! call oasis_abort()
  694. ! endif
  695. if (flag == OASIS_Out .and. allops(nv,nm) /= OASIS_In) then
  696. write(nulprt,*) subname,estr,'send recv pair both Out = ', &
  697. trim(myfld),' ',trim(otfld)
  698. call oasis_abort()
  699. endif
  700. if (flag == OASIS_In .and. allops(nv,nm) /= OASIS_Out) then
  701. write(nulprt,*) subname,estr,'send recv pair both In = ', &
  702. trim(myfld),' ',trim(otfld)
  703. call oasis_abort()
  704. endif
  705. endif
  706. if (namfldops(nn) == ip_input .or. namfldops(nn) == ip_output) then
  707. if (trim(myfld) /= trim(otfld)) then
  708. write(nulprt,*) subname,estr,'namcouple field names do not match in/out = ', &
  709. trim(myfld),' ',trim(otfld)
  710. call oasis_abort()
  711. endif
  712. endif
  713. !--------------------------------
  714. ! Only an error to find two sources for a destination
  715. ! Not an error if a two destinations have a single source
  716. !--------------------------------
  717. if (flag == OASIS_In .and. found) then
  718. write(nulprt,*) subname,estr,'found two sources for field = ',trim(otfld)
  719. call oasis_abort()
  720. endif
  721. found = .true.
  722. nc = nns
  723. if (flag == OASIS_Out) pcpointer => prism_coupler_put(nc)
  724. if (flag == OASIS_In) pcpointer => prism_coupler_get(nc)
  725. !--------------------------------
  726. !> * Generate field list, multiple field support
  727. !--------------------------------
  728. IF (OASIS_debug >= 20) THEN
  729. WRITE(nulprt,*) subname,' set prism_coupler '
  730. CALL oasis_flush(nulprt)
  731. ENDIF
  732. ! tcraig, changed this to make sure order of fields in list matches on all tasks
  733. ! Use the field lists in the namcouple
  734. ! Assumes all namcoupler variables are coupled
  735. ! The nflds counter doesn't do much anymore here
  736. ! The varid size should be size(myfldlist)
  737. ! Will need to change IF all namcoupler variables don't need to be coupled
  738. pcpointer%nflds = pcpointer%nflds + 1
  739. !tcx
  740. ! this used to add fields to list one at a time
  741. ! svarid = size(pcpointer%varid)
  742. ! if (pcpointer%nflds > svarid) then
  743. ! allocate(varidtmp(svarid))
  744. ! varidtmp(1:svarid) = pcpointer%varid(1:svarid)
  745. ! deallocate(pcpointer%varid)
  746. ! allocate(pcpointer%varid(pcpointer%nflds+10))
  747. ! pcpointer%varid(1:svarid) = varidtmp(1:svarid)
  748. ! deallocate(varidtmp)
  749. ! endif
  750. !
  751. ! if (pcpointer%nflds == 1) then
  752. ! pcpointer%fldlist = trim(myfld)
  753. ! else
  754. ! pcpointer%fldlist = trim(pcpointer%fldlist)//':'//trim(myfld)
  755. ! endif
  756. ! pcpointer%varid(pcpointer%nflds) = nv1
  757. !tcx
  758. if (pcpointer%nflds == 1) then
  759. pcpointer%fldlist = trim(myfldlist)
  760. deallocate(pcpointer%varid)
  761. allocate(pcpointer%varid(oasis_string_listGetNum(myfldlist)))
  762. pcpointer%varid(:) = ispval
  763. endif
  764. svarid = size(pcpointer%varid)
  765. if (myfldi > svarid .or. pcpointer%nflds > svarid) then
  766. WRITE(nulprt,*) subname,estr,'multiple field coupling setup error',svarid,myfldi,pcpointer%nflds
  767. call oasis_abort()
  768. endif
  769. pcpointer%varid(myfldi) = nv1
  770. !--------------------------------
  771. !> * Add this coupler to list of prism_var couplers
  772. !--------------------------------
  773. prism_var(nv1)%ncpl = prism_var(nv1)%ncpl + 1
  774. if (prism_var(nv1)%ncpl > mvarcpl) then
  775. WRITE(nulprt,*) subname,estr,'ncpl too high, max size (mvarcpl) = ',mvarcpl
  776. WRITE(nulprt,*) subname,estr,'increase mvarcpl in mod_oasis_var'
  777. call oasis_abort()
  778. endif
  779. prism_var(nv1)%cpl(prism_var(nv1)%ncpl) = nc
  780. !--------------------------------
  781. ! prism_coupler settings
  782. !> * Copy namcouple settings into this coupler or
  783. !> check that coupler is consistent with prior setting
  784. !--------------------------------
  785. if (pcpointer%valid) then
  786. if (pcpointer%comp /= nm) then
  787. WRITE(nulprt,*) subname,estr,'mismatch in field comp for var = ',trim(myfld)
  788. call oasis_abort()
  789. endif
  790. if (pcpointer%namID /= nn) then
  791. WRITE(nulprt,*) subname,estr,'mismatch in field namID for var = ',trim(myfld)
  792. call oasis_abort()
  793. endif
  794. if (pcpointer%partID /= part1) then
  795. WRITE(nulprt,*) subname,estr,'mismatch in field partID for var = ',trim(myfld)
  796. call oasis_abort()
  797. endif
  798. else
  799. pcpointer%comp = nm
  800. pcpointer%seq = namfldseq(nn)
  801. pcpointer%dt = namflddti(nn)
  802. pcpointer%lag = namfldlag(nn)
  803. pcpointer%maxtime= namruntim
  804. pcpointer%rstfile= trim(namrstfil(nn))
  805. pcpointer%inpfile= trim(naminpfil(nn))
  806. pcpointer%mapperID = -1
  807. pcpointer%partID = part1
  808. pcpointer%rpartID= part1
  809. pcpointer%namID = nn
  810. pcpointer%trans = namfldtrn(nn)
  811. pcpointer%conserv= namfldcon(nn)
  812. pcpointer%consopt= namfldcoo(nn)
  813. pcpointer%ops = namfldops(nn)
  814. pcpointer%tag = compid*100*1000 + compid*1000 + nn
  815. pcpointer%getput = OASIS_NotDef
  816. pcpointer%sndrcv = .false.
  817. pcpointer%output = .false.
  818. pcpointer%input = .false.
  819. pcpointer%sndmult= namfldsmu(nn)
  820. pcpointer%sndadd = namfldsad(nn)
  821. pcpointer%rcvmult= namflddmu(nn)
  822. pcpointer%rcvadd = namflddad(nn)
  823. pcpointer%snddiag= namchecki(nn)
  824. pcpointer%rcvdiag= namchecko(nn)
  825. !--------------------------------
  826. !> * Set prism_coupler input and output flags
  827. ! prism_coupler comm flags, need for tags to match up on both sides
  828. ! tags assume up to 1000 namcouple inputs and 100 models
  829. !--------------------------------
  830. IF (OASIS_debug >= 20) THEN
  831. WRITE(nulprt,*) subname,' inout flags '
  832. CALL oasis_flush(nulprt)
  833. ENDIF
  834. if (namfldops(nn) == ip_output .or. namfldops(nn) == ip_expout) then
  835. pcpointer%output = .true.
  836. pcpointer%getput = OASIS3_PUT
  837. endif
  838. if (namfldops(nn) == ip_input) then
  839. pcpointer%input = .true.
  840. pcpointer%getput = OASIS3_GET
  841. endif
  842. if (namfldops(nn) == ip_exported .or. namfldops(nn) == ip_expout) then
  843. pcpointer%sndrcv = .true.
  844. if (flag == OASIS_Out) then
  845. pcpointer%tag = nm*100*1000 + compid*1000 + nn
  846. pcpointer%getput = OASIS3_PUT
  847. elseif (flag == OASIS_In) then
  848. pcpointer%tag = compid*100*1000 + nm*1000 + nn
  849. pcpointer%getput = OASIS3_GET
  850. endif
  851. !--------------------------------
  852. !> * Setup prism_coupler router
  853. ! cannot reuse router because don't really know what's on the other side
  854. ! if router is already set for the coupler, then fine, otherwise, set new router
  855. !--------------------------------
  856. if (pcpointer%routerID == ispval) then
  857. prism_nrouter = prism_nrouter+1
  858. if (prism_nrouter > prism_mrouter) then
  859. write(nulprt,*) subname,estr,'prism_nrouter too large = ',prism_nrouter,prism_mrouter
  860. write(nulprt,*) subname,estr,'check prism_mrouter in oasis_coupler_setup '
  861. call oasis_abort()
  862. endif
  863. pcpointer%routerID = prism_nrouter
  864. endif
  865. endif
  866. !--------------------------------
  867. !> * Setup prism_coupler mapper
  868. !--------------------------------
  869. IF (OASIS_debug >= 20) THEN
  870. WRITE(nulprt,*) subname,' mapper '
  871. CALL oasis_flush(nulprt)
  872. ENDIF
  873. tmp_mapfile = nammapfil(nn)
  874. if (trim(tmp_mapfile) == 'idmap' .and. trim(namscrmet(nn)) /= trim(cspval)) then
  875. if (trim(namscrmet(nn)) == 'CONSERV') then
  876. tmp_mapfile = 'rmp_'//trim(namsrcgrd(nn))//'_to_'//trim(namdstgrd(nn))//&
  877. &'_'//trim(namscrmet(nn))//'_'//trim(namscrnor(nn))//'.nc'
  878. else
  879. tmp_mapfile = 'rmp_'//trim(namsrcgrd(nn))//'_to_'//trim(namdstgrd(nn))//&
  880. &'_'//trim(namscrmet(nn))//'.nc'
  881. endif
  882. endif
  883. if (trim(tmp_mapfile) /= 'idmap') then
  884. pcpointer%maploc = trim(nammaploc(nn))
  885. if ((flag == OASIS_In .and. trim(nammaploc(nn)) == 'dst') .or. &
  886. (flag == OASIS_Out .and. trim(nammaploc(nn)) == 'src')) then
  887. !--------------------------------
  888. !> * Try to reuse mapper already defined,
  889. !> must match mapping file and partition
  890. !--------------------------------
  891. mapID = -1
  892. do n = 1,prism_nmapper
  893. if (trim(prism_mapper(n)%file) == trim(tmp_mapfile) .and. &
  894. trim(prism_mapper(n)%loc ) == trim(nammaploc(nn)) .and. &
  895. trim(prism_mapper(n)%opt ) == trim(nammapopt(nn))) then
  896. if (flag == OASIS_In .and. prism_mapper(n)%dpart == part1) mapID = n
  897. if (flag == OASIS_Out .and. prism_mapper(n)%spart == part1) mapID = n
  898. endif
  899. enddo
  900. !--------------------------------
  901. !> * Or get ready to initialize a new mapper
  902. !--------------------------------
  903. if (mapID < 1) then
  904. prism_nmapper = prism_nmapper + 1
  905. if (prism_nmapper > prism_mmapper) then
  906. write(nulprt,*) subname,estr,'prism_nmapper too large',prism_nmapper,prism_mmapper
  907. write(nulprt,*) subname,estr,'check prism_mmapper in oasis_coupler_setup '
  908. call oasis_abort()
  909. endif
  910. mapID = prism_nmapper
  911. prism_mapper(mapID)%file = trim(tmp_mapfile)
  912. prism_mapper(mapID)%loc = trim(nammaploc(nn))
  913. prism_mapper(mapID)%opt = trim(nammapopt(nn))
  914. prism_mapper(mapID)%srcgrid = trim(namsrcgrd(nn))
  915. prism_mapper(mapID)%dstgrid = trim(namdstgrd(nn))
  916. if (flag == OASIS_In ) prism_mapper(mapID)%dpart = part1
  917. if (flag == OASIS_Out) prism_mapper(mapID)%spart = part1
  918. if (OASIS_debug > 15) then
  919. write(nulprt,*) subname,' DEBUG new mapper for file ',&
  920. trim(prism_mapper(mapID)%file)
  921. call oasis_flush(nulprt)
  922. endif
  923. endif
  924. pcpointer%mapperID = mapID
  925. endif ! flag and nammaploc match
  926. endif ! nammapfil
  927. pcpointer%valid = .true.
  928. endif ! valid
  929. if (local_timers_on) call oasis_timer_stop('cpl_setup_n3d')
  930. enddo ! nvf
  931. endif ! my var found
  932. enddo ! nfind
  933. enddo ! nv1
  934. if (local_timers_on) call oasis_timer_stop ('cpl_setup_n3')
  935. if (local_timers_on) call oasis_timer_start('cpl_setup_n4')
  936. if (local_timers_on) call oasis_timer_start('cpl_setup_n4a')
  937. ! aggregate checkused info across all pes and then check on each component root
  938. allocate(namsrc_checkused_g(sortnsrc%num))
  939. call oasis_mpi_max(namsrc_checkused,namsrc_checkused_g,mpi_comm_global,string=trim(subname)//':srccheckused',all=.true.)
  940. found = .false.
  941. do n1 = 1,sortnsrc%num
  942. if (namsrc_checkused_g(n1) /= 1) then
  943. if (mpi_rank_local == 0) write(nulprt,*) subname,estr,'namcouple variable not used: ',trim(sortnsrc%fld(n1))
  944. found = .true.
  945. endif
  946. enddo
  947. ! call oasis_mpi_barrier(mpi_comm_global)
  948. if (found) call oasis_abort()
  949. deallocate(namsrc_checkused_g)
  950. !--- deallocate temporary ---
  951. deallocate(allvar,nallvar,allops)
  952. deallocate(namsrc_checkused)
  953. deallocate(sortnsrc%fld)
  954. deallocate(sortnsrc%namnum)
  955. deallocate(sortnsrc%fldnum)
  956. deallocate(sortndst%fld)
  957. deallocate(sortndst%namnum)
  958. deallocate(sortndst%fldnum)
  959. deallocate(sortvars%fld)
  960. deallocate(sortvars%modnum)
  961. deallocate(sortvars%varnum)
  962. if (OASIS_debug >= 20) then
  963. write(nulprt,*) ' '
  964. write(nulprt,*) subname,' couplers setup'
  965. do nc = 1,prism_mcoupler
  966. !tcx can't write here, something uninitialized???
  967. !-> CEG it was dpart so added extra if into the print routine
  968. ! if (prism_coupler_put(nc)%valid) call prism_coupler_print(nc,prism_coupler_put(nc))
  969. ! if (prism_coupler_get(nc)%valid) call prism_coupler_print(nc,prism_coupler_get(nc))
  970. enddo
  971. write(nulprt,*) ' '
  972. call oasis_flush(nulprt)
  973. endif
  974. if (mpi_comm_local == MPI_COMM_NULL) then
  975. return
  976. endif
  977. !----------------------------------------------------------
  978. !> * Initialize coupling infrastructure based on initial coupler setup above
  979. !----------------------------------------------------------
  980. call oasis_debug_note(subname//' initialize coupling datatypes')
  981. !----------------------------------------------------------
  982. !> * Loop over all couplers
  983. !----------------------------------------------------------
  984. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4a')
  985. do nc = 1,prism_mcoupler
  986. do npc = 1,2
  987. if (npc == 1) then
  988. pcpointer => prism_coupler_put(nc)
  989. pcpntpair => prism_coupler_get(nc)
  990. endif
  991. if (npc == 2) then
  992. pcpointer => prism_coupler_get(nc)
  993. pcpntpair => prism_coupler_put(nc)
  994. endif
  995. if (OASIS_debug >= 20) then
  996. write(nulprt,*) subname,' DEBUG cb:initialize coupler ',nc,npc,pcpointer%valid
  997. call oasis_flush(nulprt)
  998. endif
  999. if (pcpointer%valid) then
  1000. if (local_timers_on) call oasis_timer_start('cpl_setup_n4b')
  1001. if (OASIS_debug >= 5) then
  1002. write(nulprt,*) subname,' DEBUG ci:initialize coupler ',nc,npc
  1003. call oasis_flush(nulprt)
  1004. endif
  1005. namID = pcpointer%namID
  1006. part1 = pcpointer%partID
  1007. mapID = pcpointer%mapperID
  1008. if (part1 <= 0) then
  1009. write(nulprt,*) subname,estr,'part1 invalid = ',part1
  1010. call oasis_abort()
  1011. endif
  1012. !--------------------------------
  1013. !> * Initialize avect1 which stores the get/put data
  1014. !--------------------------------
  1015. gsize = mct_gsmap_gsize(prism_part(part1)%gsmap)
  1016. lsize = mct_gsmap_lsize(prism_part(part1)%gsmap,mpi_comm_local)
  1017. if (OASIS_debug >= 15) then
  1018. write(nulprt,'(1x,2a,5i10)') subname,' DEBUG ci:part1 info ',namID,part1,mapID,gsize,lsize
  1019. write(nulprt,'(1x,2a,4i12)') subname,' DEBUG ci:part1a',prism_part(part1)%gsmap%ngseg,&
  1020. prism_part(part1)%gsmap%gsize
  1021. do n1 = 1,prism_part(part1)%gsmap%ngseg
  1022. write(nulprt,'(1x,2a,4i12)') subname,' DEBUG ci:part1b',n1,&
  1023. prism_part(part1)%gsmap%start(n1),&
  1024. prism_part(part1)%gsmap%length(n1),&
  1025. prism_part(part1)%gsmap%pe_loc(n1)
  1026. enddo
  1027. call oasis_flush(nulprt)
  1028. endif
  1029. call mct_avect_init(pcpointer%avect1,rList=trim(pcpointer%fldlist),lsize=lsize)
  1030. call mct_avect_zero(pcpointer%avect1)
  1031. pcpointer%aVon(1) = .true.
  1032. if (OASIS_debug >= 15) then
  1033. write(nulprt,*) subname,' DEBUG ci:avect1 initialized '
  1034. call oasis_flush(nulprt)
  1035. endif
  1036. !--------------------------------
  1037. !> * Compute nflds for this coupling and initialize avcnt and status
  1038. !--------------------------------
  1039. pcpointer%nflds = mct_aVect_nRAttr(pcpointer%avect1)
  1040. allocate(pcpointer%status(pcpointer%nflds))
  1041. allocate(pcpointer%avcnt (pcpointer%nflds))
  1042. pcpointer%avcnt(:) = 0
  1043. if (pcpointer%getput == OASIS3_PUT) pcpointer%status = OASIS_COMM_WAIT
  1044. if (pcpointer%getput == OASIS3_GET) pcpointer%status = OASIS_COMM_READY
  1045. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4b')
  1046. !--------------------------------
  1047. !> * Initialize the mapper data
  1048. !--------------------------------
  1049. if (mapID > 0) then
  1050. if (prism_mapper(mapID)%init) then
  1051. if (local_timers_on) call oasis_timer_start('cpl_setup_n4c')
  1052. !--------------------------------
  1053. ! mapper already initialized
  1054. !--------------------------------
  1055. if (pcpointer%getput == OASIS3_PUT) then
  1056. part2 = prism_mapper(mapID)%dpart
  1057. else
  1058. part2 = prism_mapper(mapID)%spart
  1059. endif
  1060. gsize = mct_gsmap_gsize(prism_part(part2)%gsmap)
  1061. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4c')
  1062. else
  1063. !--------------------------------
  1064. ! instantiate mapper
  1065. ! read/generate mapping file
  1066. ! read non local grid size
  1067. ! get gsmap for non local grid
  1068. ! read mapping weights and initialize sMatP
  1069. !--------------------------------
  1070. if (local_timers_on) call oasis_timer_start('cpl_setup_n4d')
  1071. if (OASIS_debug >= 15) then
  1072. write(nulprt,*) subname,' DEBUG ci:read mapfile ',trim(prism_mapper(mapID)%file)
  1073. call oasis_flush(nulprt)
  1074. endif
  1075. if (mpi_rank_local == 0) then
  1076. if (local_timers_on) call oasis_timer_start('cpl_setup_n4da')
  1077. if (local_timers_on) call oasis_timer_start('cpl_setup_n4da1')
  1078. inquire(file=trim(prism_mapper(mapID)%file),exist=exists)
  1079. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4da1')
  1080. if (OASIS_debug >= 15) then
  1081. write(nulprt,*) subname,' DEBUG ci: inquire mapfile ',&
  1082. trim(prism_mapper(mapID)%file),exists
  1083. call oasis_flush(nulprt)
  1084. endif
  1085. if (.not.exists) then
  1086. if (trim(namscrmet(namID)) /= trim(cspval)) then
  1087. !--------------------------------
  1088. ! generate mapping file on root pe
  1089. ! taken from oasis3 scriprmp
  1090. !--------------------------------
  1091. call oasis_timer_start('cpl_setup_genmap')
  1092. call oasis_map_genmap(mapID,namID)
  1093. call oasis_timer_stop('cpl_setup_genmap')
  1094. else
  1095. write(nulprt,*) subname,estr,'map file does not exist and SCRIPR not set = ',&
  1096. trim(prism_mapper(mapID)%file)
  1097. call oasis_abort()
  1098. endif
  1099. endif
  1100. !--------------------------------
  1101. ! open mapping file
  1102. !--------------------------------
  1103. if (local_timers_on) call oasis_timer_start('cpl_setup_n4da3')
  1104. status = nf90_open(trim(prism_mapper(mapID)%file),nf90_nowrite,ncid)
  1105. if (OASIS_debug >= 15) then
  1106. status = nf90_inq_dimid(ncid,'dst_grid_size',dimid)
  1107. status = nf90_inquire_dimension(ncid,dimid,len=gsize)
  1108. write(nulprt,*) subname," DEBUG dst_grid_size ",gsize
  1109. status = nf90_inq_dimid(ncid,'src_grid_size',dimid)
  1110. status = nf90_inquire_dimension(ncid,dimid,len=gsize)
  1111. write(nulprt,*) subname," DEBUG src_grid_size ",gsize
  1112. endif
  1113. if (pcpointer%getput == OASIS3_PUT) &
  1114. status = nf90_inq_dimid(ncid,'dst_grid_size',dimid)
  1115. if (pcpointer%getput == OASIS3_GET) &
  1116. status = nf90_inq_dimid(ncid,'src_grid_size',dimid)
  1117. status = nf90_inquire_dimension(ncid,dimid,len=gsize)
  1118. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4da3')
  1119. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4da')
  1120. endif ! rank = 0
  1121. if (local_timers_on) call oasis_timer_start('cpl_setup_n4db')
  1122. call oasis_mpi_bcast(gsize,mpi_comm_local,subname//' gsize')
  1123. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4db')
  1124. if (local_timers_on) call oasis_timer_start('cpl_setup_n4dc')
  1125. if (pcpointer%getput == OASIS3_PUT) then
  1126. nx = namdst_nx(namID)
  1127. ny = namdst_ny(namID)
  1128. gridname = trim(namdstgrd(namID))
  1129. else
  1130. nx = namsrc_nx(namID)
  1131. ny = namsrc_ny(namID)
  1132. gridname = trim(namsrcgrd(namID))
  1133. endif
  1134. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4dc')
  1135. !tcx improve match here with nx,ny,gridname
  1136. if (local_timers_on) call oasis_timer_start('cpl_setup_n4dd')
  1137. call oasis_part_create(part2,'1d',gsize,nx,ny,gridname,prism_part(part1)%mpicom,mpi_comm_local)
  1138. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4dd')
  1139. if (OASIS_Debug >= 15) then
  1140. write(nulprt,*) subname," DEBUG part_create part1 gsize",prism_part(part1)%gsize
  1141. do r1 = 1,prism_part(part1)%gsmap%ngseg
  1142. write(nulprt,*) subname," DEBUG part_create part1 info ",&
  1143. prism_part(part1)%gsmap%start(r1),prism_part(part1)%gsmap%length(r1),&
  1144. prism_part(part1)%gsmap%pe_loc(r1)
  1145. enddo
  1146. write(nulprt,*) subname," DEBUG part_create part2 gsize",prism_part(part2)%gsize
  1147. do r1 = 1,prism_part(part2)%gsmap%ngseg
  1148. write(nulprt,*) subname," DEBUG part_create part2 info ",prism_part(part2)%gsmap%start(r1),&
  1149. prism_part(part2)%gsmap%length(r1),prism_part(part2)%gsmap%pe_loc(r1)
  1150. enddo
  1151. endif
  1152. if (local_timers_on) call oasis_timer_start('cpl_setup_n4de')
  1153. if (prism_part(part2)%nx < 1) then
  1154. prism_part(part2)%nx = nx
  1155. prism_part(part2)%ny = ny
  1156. prism_part(part2)%gridname = trim(gridname)
  1157. endif
  1158. if (pcpointer%getput == OASIS3_PUT) then
  1159. !prism_mapper(mapID)%spart = part1 ! set above
  1160. prism_mapper(mapID)%dpart = part2
  1161. else
  1162. prism_mapper(mapID)%spart = part2
  1163. !prism_mapper(mapID)%dpart = part1 ! set above
  1164. endif
  1165. spart = prism_mapper(mapID)%spart
  1166. dpart = prism_mapper(mapID)%dpart
  1167. !--- cstring sets whether src or dst are rearranged in remap
  1168. !--- src = rearrange and map (bfb), dst = map and rearrange (partial sum)
  1169. if (prism_mapper(mapID)%opt == 'opt') then
  1170. if (prism_part(spart)%gsize > prism_part(dpart)%gsize) then
  1171. cstring = 'dst'
  1172. else
  1173. cstring = 'src'
  1174. endif
  1175. elseif (prism_mapper(mapID)%opt == 'bfb') then
  1176. cstring = 'src'
  1177. elseif (prism_mapper(mapID)%opt == 'sum') then
  1178. cstring = 'dst'
  1179. else
  1180. write(nulprt,*) subname,estr,'mapper opt invalid expect bfb or sum =',trim(prism_mapper(mapID)%opt)
  1181. call oasis_abort()
  1182. endif
  1183. if (prism_mapper(mapID)%optval /= '' .and. &
  1184. prism_mapper(mapID)%optval /= trim(cstring)) then
  1185. write(nulprt,*) subname,estr,'mapper opt changed',&
  1186. trim(prism_mapper(mapID)%optval),' ',trim(cstring)
  1187. call oasis_abort()
  1188. endif
  1189. prism_mapper(mapID)%optval = trim(cstring)
  1190. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4de')
  1191. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4d')
  1192. !-------------------------------
  1193. ! smatreaddnc allocates sMati to nwgts
  1194. ! then instantiate an sMatP for each set of wgts
  1195. ! to support higher order mapping
  1196. !-------------------------------
  1197. if (smatread_method == "ceg") then
  1198. if (local_timers_on) call oasis_timer_start('smatrd_ceg')
  1199. call oasis_map_smatreaddnc_ceg(sMati,prism_part(spart)%gsmap,prism_part(dpart)%gsmap, &
  1200. trim(cstring),trim(prism_mapper(mapID)%file),mpi_rank_local,mpi_comm_local,nwgts)
  1201. if (local_timers_on) call oasis_timer_stop('smatrd_ceg')
  1202. else
  1203. if (local_timers_on) call oasis_timer_start('smatrd_orig')
  1204. call oasis_map_smatreaddnc_orig(sMati,prism_part(spart)%gsmap,prism_part(dpart)%gsmap, &
  1205. trim(cstring),trim(prism_mapper(mapID)%file),mpi_rank_local,mpi_comm_local,nwgts)
  1206. if (local_timers_on) call oasis_timer_stop('smatrd_orig')
  1207. endif
  1208. if (local_timers_on) call oasis_timer_start('cpl_setup_sminit')
  1209. prism_mapper(mapID)%nwgts = nwgts
  1210. allocate(prism_mapper(mapID)%sMatP(nwgts))
  1211. do n = 1,nwgts
  1212. call mct_sMatP_Init(prism_mapper(mapID)%sMatP(n), sMati(n), &
  1213. prism_part(spart)%gsmap, prism_part(dpart)%gsmap, 0, mpi_comm_local, compid)
  1214. call mct_sMat_Clean(sMati(n))
  1215. enddo
  1216. deallocate(sMati)
  1217. if (local_timers_on) call oasis_timer_stop('cpl_setup_sminit')
  1218. if (local_timers_on) call oasis_timer_start('cpl_setup_n4e')
  1219. lsize = mct_smat_gNumEl(prism_mapper(mapID)%sMatP(1)%Matrix,mpi_comm_local)
  1220. prism_mapper(mapID)%init = .true.
  1221. if (OASIS_debug >= 15) then
  1222. write(nulprt,*) subname," DEBUG ci:done initializing prism_mapper",mapID,&
  1223. " nElements = ",lsize," nwgts = ",nwgts
  1224. call oasis_flush(nulprt)
  1225. endif
  1226. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4e')
  1227. endif ! map init
  1228. if (local_timers_on) call oasis_timer_start('cpl_setup_n4f')
  1229. !--------------------------------
  1230. !> * Read mapper mask and area if not already done
  1231. !--------------------------------
  1232. if (.not.prism_mapper(mapID)%AVred .and. pcpointer%conserv /= ip_cnone) then
  1233. ! initialize and load AV_ms and AV_md
  1234. spart = prism_mapper(mapID)%spart
  1235. dpart = prism_mapper(mapID)%dpart
  1236. lsize = mct_gsmap_lsize(prism_part(spart)%gsmap,mpi_comm_local)
  1237. call mct_avect_init(prism_mapper(mapID)%av_ms,iList='mask',rList='area',lsize=lsize)
  1238. call mct_avect_zero(prism_mapper(mapID)%av_ms)
  1239. ! gridname = prism_part(spart)%gridname
  1240. gridname=prism_mapper(mapID)%srcgrid
  1241. call oasis_io_read_avfld('masks.nc',prism_mapper(mapID)%av_ms, &
  1242. prism_part(spart)%gsmap,mpi_comm_local,'mask',trim(gridname)//'.msk',fldtype='int')
  1243. call oasis_io_read_avfld('areas.nc',prism_mapper(mapID)%av_ms, &
  1244. prism_part(spart)%gsmap,mpi_comm_local,'area',trim(gridname)//'.srf',fldtype='real')
  1245. lsize = mct_gsmap_lsize(prism_part(dpart)%gsmap,mpi_comm_local)
  1246. call mct_avect_init(prism_mapper(mapID)%av_md,iList='mask',rList='area',lsize=lsize)
  1247. call mct_avect_zero(prism_mapper(mapID)%av_md)
  1248. ! gridname = prism_part(dpart)%gridname
  1249. gridname=prism_mapper(mapID)%dstgrid
  1250. call oasis_io_read_avfld('masks.nc',prism_mapper(mapID)%av_md, &
  1251. prism_part(dpart)%gsmap,mpi_comm_local,'mask',trim(gridname)//'.msk',fldtype='int')
  1252. call oasis_io_read_avfld('areas.nc',prism_mapper(mapID)%av_md, &
  1253. prism_part(dpart)%gsmap,mpi_comm_local,'area',trim(gridname)//'.srf',fldtype='real')
  1254. prism_mapper(mapID)%AVred = .true.
  1255. if (OASIS_debug >= 30) then
  1256. write(nulprt,*) subname,' DEBUG msi ',minval(prism_mapper(mapID)%av_ms%iAttr(:,:)),&
  1257. maxval(prism_mapper(mapID)%av_ms%iAttr(:,:)),&
  1258. sum(prism_mapper(mapID)%av_ms%iAttr(:,:))
  1259. write(nulprt,*) subname,' DEBIG msr ',minval(prism_mapper(mapID)%av_ms%rAttr(:,:)),&
  1260. maxval(prism_mapper(mapID)%av_ms%rAttr(:,:)),&
  1261. sum(prism_mapper(mapID)%av_ms%rAttr(:,:))
  1262. write(nulprt,*) subname,' DEBUG mdi ',minval(prism_mapper(mapID)%av_md%iAttr(:,:)),&
  1263. maxval(prism_mapper(mapID)%av_md%iAttr(:,:)),&
  1264. sum(prism_mapper(mapID)%av_md%iAttr(:,:))
  1265. write(nulprt,*) subname,' DEBUG mdr ',minval(prism_mapper(mapID)%av_md%rAttr(:,:)),&
  1266. maxval(prism_mapper(mapID)%av_md%rAttr(:,:)),&
  1267. sum(prism_mapper(mapID)%av_md%rAttr(:,:))
  1268. CALL oasis_flush(nulprt)
  1269. endif
  1270. endif
  1271. !--------------------------------
  1272. !> * Initialize avect1m, the data in avect1 mapped to another grid
  1273. !--------------------------------
  1274. lsize = mct_gsmap_lsize(prism_part(part2)%gsmap,mpi_comm_local)
  1275. if (OASIS_debug >= 15) then
  1276. write(nulprt,'(1x,2a,4i12)') subname,' DEBUG ci:part2 info ',part2,mapID,gsize,lsize
  1277. write(nulprt,'(1x,2a,4i12)') subname,' DEBUG ci:part2a',prism_part(part2)%gsmap%ngseg,&
  1278. prism_part(part2)%gsmap%gsize
  1279. do n1 = 1,prism_part(part2)%gsmap%ngseg
  1280. write(nulprt,'(1x,2a,4i12)') subname,' DEBUG ci:part2b',n1,prism_part(part2)%gsmap%start(n1),&
  1281. prism_part(part2)%gsmap%length(n1),prism_part(part2)%gsmap%pe_loc(n1)
  1282. enddo
  1283. call oasis_flush(nulprt)
  1284. endif
  1285. call mct_avect_init(pcpointer%avect1m,rList=trim(pcpointer%fldlist),lsize=lsize)
  1286. call mct_avect_zero(pcpointer%avect1m)
  1287. if (OASIS_debug >= 15) then
  1288. write(nulprt,*) subname,' DEBUG ci:avect1m initialized '
  1289. call oasis_flush(nulprt)
  1290. endif
  1291. !--------------------------------
  1292. ! router partition is always other part
  1293. !--------------------------------
  1294. pcpointer%rpartID = part2
  1295. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4f')
  1296. else
  1297. !--------------------------------
  1298. ! router partition is just coupler part
  1299. ! Set to this by default above
  1300. !--------------------------------
  1301. ! pcpointer%rpartID = pcpointer%partID
  1302. endif ! no mapper
  1303. endif ! endif of pcpointer%valid
  1304. ! print'(I3,A,X,L,X,8(I8,X))',mpi_rank_global, 'would have done sndrcv here', pcpointer%sndrcv,pcpointer%comp,compid, &
  1305. ! pcpointer%valid, mapID, pcpointer%rPartID, pcpointer%routerID
  1306. enddo ! npc
  1307. enddo ! nc
  1308. !-------------------------------------------------
  1309. ! CEG split 1 loop into 2 to allow map reading on different models in parallel.
  1310. !-------------------------------------------------
  1311. do nc = 1, prism_mcoupler ! nc
  1312. do npc=1,2
  1313. if (npc == 1) then
  1314. pcpointer => prism_coupler_put(nc)
  1315. pcpntpair => prism_coupler_get(nc)
  1316. endif
  1317. if (npc == 2) then
  1318. pcpointer => prism_coupler_get(nc)
  1319. pcpntpair => prism_coupler_put(nc)
  1320. endif
  1321. namID = pcpointer%namID
  1322. part1 = pcpointer%partID
  1323. mapID = pcpointer%mapperID
  1324. ! print'(I3,A,X,L,X,8(I8,X))',mpi_rank_global, '..finally doing sndrcv here', pcpointer%sndrcv, pcpointer%comp, compid, &
  1325. ! pcpointer%valid, mapID, pcpointer%rPartID, pcpointer%routerID
  1326. ! if (mapID > 0) then
  1327. !--------------------------------
  1328. !> * Initialize router based on rpartID
  1329. !--------------------------------
  1330. if (local_timers_on) call oasis_timer_start('cpl_setup_n4_sr')
  1331. if (pcpointer%sndrcv) then
  1332. if (OASIS_debug >= 15) then
  1333. write(nulprt,*) subname,' DEBUG ci:initialize router ',pcpointer%routerID,&
  1334. pcpointer%comp,pcpointer%rpartID
  1335. call oasis_flush(nulprt)
  1336. endif
  1337. if (compid == pcpointer%comp) then
  1338. ! routers for sending to self
  1339. ! setup router on second pass so rpartID is defined on both sides
  1340. ! setup both routers at the same time
  1341. if (local_timers_on) call oasis_timer_start('cpl_setup_n4_sra')
  1342. if (npc == 2) then
  1343. if (OASIS_debug >= 15) then
  1344. write(nulprt,*) subname,' DEBUG self router between part ',pcpointer%rpartID,' and part ',pcpntpair%rpartID, &
  1345. ' with router ',pcpointer%routerID,' and router ',pcpntpair%routerID,' for compid ',compid
  1346. endif
  1347. call mct_router_init(prism_part(pcpointer%rpartID)%gsmap, prism_part(pcpntpair%rpartID)%gsmap, &
  1348. mpi_comm_local, prism_router(pcpointer%routerID)%router)
  1349. call mct_router_init(prism_part(pcpntpair%rpartID)%gsmap, prism_part(pcpointer%rpartID)%gsmap, &
  1350. mpi_comm_local, prism_router(pcpntpair%routerID)%router)
  1351. if (OASIS_debug >= 15) then
  1352. write(nulprt,*) subname," DEBUG ci:done initializing prism_router",&
  1353. pcpointer%routerID
  1354. if (OASIS_debug >= 20) then
  1355. do r1 = 1,prism_part(pcpointer%rpartID)%gsmap%ngseg
  1356. write(nulprt,*) subname," DEBUG router gs1 info ",prism_part(pcpointer%rpartID)%gsmap%start(r1),&
  1357. prism_part(pcpointer%rpartID)%gsmap%length(r1),prism_part(pcpointer%rpartID)%gsmap%pe_loc(r1)
  1358. enddo
  1359. do r1 = 1,prism_part(pcpointer%partID)%gsmap%ngseg
  1360. write(nulprt,*) subname," DEBUG router gs2 info ",prism_part(pcpointer%partID)%gsmap%start(r1),&
  1361. prism_part(pcpointer%partID)%gsmap%length(r1),prism_part(pcpointer%partID)%gsmap%pe_loc(r1)
  1362. enddo
  1363. do r1 = 1,prism_part(pcpntpair%rpartID)%gsmap%ngseg
  1364. write(nulprt,*) subname," DEBUG router gs3 info ",prism_part(pcpntpair%rpartID)%gsmap%start(r1),&
  1365. prism_part(pcpntpair%rpartID)%gsmap%length(r1),prism_part(pcpntpair%rpartID)%gsmap%pe_loc(r1)
  1366. enddo
  1367. do r1 = 1,prism_part(pcpntpair%partid)%gsmap%ngseg
  1368. write(nulprt,*) subname," DEBUG router gs4 info ",prism_part(pcpntpair%partid)%gsmap%start(r1),&
  1369. prism_part(pcpntpair%partid)%gsmap%length(r1),prism_part(pcpntpair%partid)%gsmap%pe_loc(r1)
  1370. enddo
  1371. do r1 = 1,prism_router(pcpointer%routerID)%router%nprocs
  1372. write(nulprt,*) subname," DEBUG router info ",pcpointer%routerID,r1, &
  1373. prism_router(pcpointer%routerID)%router%pe_list(r1),prism_router(pcpointer%routerID)%router%locsize(r1)
  1374. enddo
  1375. endif
  1376. call oasis_flush(nulprt)
  1377. endif
  1378. if (OASIS_debug >= 15) then
  1379. write(nulprt,*) subname," DEBUG ci:done initializing prism_router",&
  1380. pcpntpair%routerID
  1381. if (OASIS_debug >= 20) then
  1382. do r1 = 1,prism_router(pcpntpair%routerID)%router%nprocs
  1383. write(nulprt,*) subname," DEBUG router info ",pcpntpair%routerID,r1, &
  1384. prism_router(pcpntpair%routerID)%router%pe_list(r1),prism_router(pcpntpair%routerID)%router%locsize(r1)
  1385. enddo
  1386. endif
  1387. call oasis_flush(nulprt)
  1388. endif
  1389. endif
  1390. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4_sra')
  1391. else
  1392. if (local_timers_on) call oasis_timer_start('cpl_setup_n4_srb')
  1393. call mct_router_init(pcpointer%comp,prism_part(pcpointer%rpartID)%gsmap, &
  1394. mpi_comm_local,prism_router(pcpointer%routerID)%router)
  1395. if (OASIS_debug >= 15) then
  1396. write(nulprt,*) subname," DEBUG ci:done initializing prism_router",&
  1397. pcpointer%routerID
  1398. if (OASIS_debug >= 20) then
  1399. do r1 = 1,prism_router(pcpointer%routerID)%router%nprocs
  1400. write(nulprt,*) subname," DEBUG router info ",pcpointer%routerID,r1, &
  1401. prism_router(pcpointer%routerID)%router%pe_list(r1),prism_router(pcpointer%routerID)%router%locsize(r1)
  1402. enddo
  1403. endif
  1404. call oasis_flush(nulprt)
  1405. endif
  1406. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4_srb')
  1407. endif
  1408. endif
  1409. if (local_timers_on) call oasis_timer_stop('cpl_setup_n4_sr')
  1410. enddo ! npc
  1411. enddo ! prism_mcoupler
  1412. if (local_timers_on) call oasis_timer_start('cpl_setup_n4g')
  1413. !----------------------------------------------------------
  1414. !> * Diagnostics for all couplers
  1415. !----------------------------------------------------------
  1416. if (OASIS_debug >= 2) then
  1417. write(nulprt,*) ' '
  1418. write(nulprt,*) subname,' couplers initialized'
  1419. do nc = 1,prism_mcoupler
  1420. if (prism_coupler_put(nc)%valid) call oasis_coupler_print(nc,prism_coupler_put(nc))
  1421. if (prism_coupler_get(nc)%valid) call oasis_coupler_print(nc,prism_coupler_get(nc))
  1422. enddo
  1423. write(nulprt,*) ' '
  1424. CALL oasis_flush(nulprt)
  1425. endif
  1426. IF (LUCIA_debug > 0) THEN
  1427. DO nc = 1, prism_mcoupler
  1428. IF (prism_coupler_put(nc)%valid) &
  1429. WRITE(nullucia, '(A12,I4.4,1X,A)') 'Balance: SN ', prism_coupler_put(nc)%namID, TRIM(prism_coupler_put(nc)%fldlist)
  1430. IF (prism_coupler_get(nc)%valid) &
  1431. WRITE(nullucia, '(A12,I4.4,1X,A)') 'Balance: RC ', prism_coupler_get(nc)%namID, TRIM(prism_coupler_get(nc)%fldlist)
  1432. ENDDO
  1433. ENDIF
  1434. if (local_timers_on) call oasis_timer_stop ('cpl_setup_n4g')
  1435. if (local_timers_on) call oasis_timer_stop ('cpl_setup_n4')
  1436. IF (local_timers_on) call oasis_timer_stop('cpl_setup')
  1437. call oasis_debug_exit(subname)
  1438. END SUBROUTINE oasis_coupler_setup
  1439. !------------------------------------------------------------
  1440. !> Print routine for oasis_couplers
  1441. SUBROUTINE oasis_coupler_print(cplid,pcprint)
  1442. IMPLICIT NONE
  1443. integer(ip_i4_p), intent(in) :: cplid !< coupler id
  1444. type(prism_coupler_type), intent(in) :: pcprint !< specific prism_coupler
  1445. !----------------------------------------------------------
  1446. integer(ip_i4_p) :: mapid, rouid, parid, namid, nflds, rpard
  1447. integer(ip_i4_p) :: spart,dpart
  1448. character(len=*),parameter :: subname = '(oasis_coupler_print)'
  1449. call oasis_debug_enter(subname)
  1450. mapid = pcprint%mapperid
  1451. rouid = pcprint%routerid
  1452. parid = pcprint%partid
  1453. rpard = pcprint%rpartid
  1454. namid = pcprint%namid
  1455. nflds = pcprint%nflds
  1456. write(nulprt,*) ' '
  1457. write(nulprt,*) subname,' model and cplid',compid,cplid
  1458. if (pcprint%getput == OASIS3_PUT) then
  1459. write(nulprt,*) subname,' send fields ',trim(pcprint%fldlist)
  1460. write(nulprt,*) subname,' from model ',compid
  1461. write(nulprt,*) subname,' to model ',pcprint%comp
  1462. write(nulprt,*) subname,' using router ',rouid
  1463. write(nulprt,*) subname,' transform ',pcprint%trans
  1464. write(nulprt,*) subname,' snd diagnose ',pcprint%snddiag
  1465. write(nulprt,*) subname,' snd fld mult ',pcprint%sndmult
  1466. write(nulprt,*) subname,' snd fld add ',pcprint%sndadd
  1467. endif
  1468. if (pcprint%getput == OASIS3_GET) then
  1469. write(nulprt,*) subname,' recv fields ',trim(pcprint%fldlist)
  1470. write(nulprt,*) subname,' from model ',pcprint%comp
  1471. write(nulprt,*) subname,' to model ',compid
  1472. write(nulprt,*) subname,' using router ',rouid
  1473. write(nulprt,*) subname,' rcv diagnose ',pcprint%rcvdiag
  1474. write(nulprt,*) subname,' rcv fld mult ',pcprint%rcvmult
  1475. write(nulprt,*) subname,' rcv fld add ',pcprint%rcvadd
  1476. endif
  1477. write(nulprt,*) subname,' namcouple op ',pcprint%ops
  1478. write(nulprt,*) subname,' valid ',pcprint%valid
  1479. write(nulprt,*) subname,' namcouple id ',namid
  1480. write(nulprt,*) subname,' variable ids ',pcprint%varid(1:nflds)
  1481. write(nulprt,*) subname,' sndrcv flag ',pcprint%sndrcv
  1482. write(nulprt,*) subname,' output flag ',pcprint%output
  1483. write(nulprt,*) subname,' input flag ',pcprint%input
  1484. write(nulprt,*) subname,' input file ',trim(pcprint%inpfile)
  1485. write(nulprt,*) subname,' restart file ',trim(pcprint%rstfile)
  1486. write(nulprt,*) subname,' tag ',pcprint%tag
  1487. write(nulprt,*) subname,' seq ',pcprint%seq
  1488. write(nulprt,*) subname,' maxtime ',pcprint%maxtime
  1489. write(nulprt,*) subname,' dt, lag ',pcprint%dt,pcprint%lag
  1490. ! write(nulprt,*) subname,' partid, size ',parid,trim(prism_part(parid)%gridname),&
  1491. ! prism_part(parid)%gsize
  1492. write(nulprt,*) subname,' partid, size ',parid,prism_part(parid)%gsize
  1493. write(nulprt,*) subname,' partid, nx,ny ',prism_part(parid)%nx,prism_part(parid)%ny
  1494. ! write(nulprt,*) subname,' rpartid,size ',rpard,trim(prism_part(rpard)%gridname),&
  1495. ! prism_part(rpard)%gsize
  1496. write(nulprt,*) subname,' rpartid,size ',rpard,prism_part(rpard)%gsize
  1497. write(nulprt,*) subname,' rpartid,nx,ny ',prism_part(rpard)%nx,prism_part(rpard)%ny
  1498. write(nulprt,*) subname,' maploc ',trim(pcprint%maploc)
  1499. if (mapid > 0) then
  1500. WRITE(nulprt,*) subname,' src grid :',trim(prism_mapper(mapid)%srcgrid)
  1501. WRITE(nulprt,*) subname,' dst grid :',trim(prism_mapper(mapid)%dstgrid)
  1502. write(nulprt,*) subname,' use map ',mapid,trim(prism_mapper(mapid)%file)
  1503. write(nulprt,*) subname,' nwgts ',mapid,prism_mapper(mapid)%nwgts
  1504. spart = prism_mapper(mapid)%spart
  1505. dpart = prism_mapper(mapid)%dpart
  1506. write(nulprt,*) subname,' conserve ',pcprint%conserv
  1507. write(nulprt,*) subname,' conserve opt ',pcprint%consopt
  1508. write(nulprt,*) subname,' location ',trim(prism_mapper(mapid)%loc)
  1509. write(nulprt,*) subname,' opt,optval ',trim(prism_mapper(mapid)%opt),' ',&
  1510. trim(prism_mapper(mapid)%optval)
  1511. write(nulprt,*) subname,' s/d partids ',spart,dpart
  1512. if (spart > 0) &
  1513. write(nulprt,*) subname,' from/to partition',trim(prism_part(spart)%gridname),' ',&
  1514. trim(prism_part(dpart)%gridname)
  1515. write(nulprt,*) subname,' from nx,ny ',prism_part(spart)%gsize,prism_part(spart)%nx,&
  1516. prism_part(spart)%ny
  1517. if (dpart > 0) &
  1518. write(nulprt,*) subname,' to nx,ny ',prism_part(dpart)%gsize, prism_part(dpart)%nx,&
  1519. prism_part(dpart)%ny
  1520. endif ! mapid > 0
  1521. call oasis_flush(nulprt)
  1522. call oasis_debug_exit(subname)
  1523. END SUBROUTINE oasis_coupler_print
  1524. !------------------------------------------------------------
  1525. ! !BOP ===========================================================================
  1526. !
  1527. !> Sort a character array using a sort key.
  1528. !
  1529. ! !DESCRIPTION:
  1530. ! Sort a character array and the associated array(s) based on a
  1531. ! reasonably fast sort algorithm
  1532. !
  1533. ! !INTERFACE: -----------------------------------------------------------------
  1534. subroutine cplsort(num, fld, sortkey)
  1535. ! !USES:
  1536. !--- local kinds ---
  1537. integer,parameter :: R8 = ip_double_p
  1538. integer,parameter :: IN = ip_i4_p
  1539. integer,parameter :: CL = ic_lvar
  1540. ! !INPUT/OUTPUT PARAMETERS:
  1541. integer(IN), intent(in) :: num !< size of array
  1542. character(len=CL),intent(inout) :: fld(:) !< sort field
  1543. integer(IN) ,intent(inout) :: sortkey(:) !< sortkey
  1544. ! !EOP
  1545. !--- local ---
  1546. integer(IN) :: n1,n2
  1547. logical :: stopnow
  1548. character(CL), pointer :: tmpfld(:)
  1549. integer(IN) , pointer :: tmpkey(:)
  1550. !--- formats ---
  1551. character(*),parameter :: subName = '(cplsort) '
  1552. !-------------------------------------------------------------------------------
  1553. !
  1554. !-------------------------------------------------------------------------------
  1555. ! call oasis_debug_enter(subname)
  1556. allocate(tmpfld((num+1)/2))
  1557. allocate(tmpkey((num+1)/2))
  1558. call MergeSort(num,fld,tmpfld,sortkey,tmpkey)
  1559. deallocate(tmpfld)
  1560. deallocate(tmpkey)
  1561. ! call oasis_debug_exit(subname)
  1562. end subroutine cplsort
  1563. !------------------------------------------------------------
  1564. ! !BOP ===========================================================================
  1565. !
  1566. !> Sort an integer array using a sort key.
  1567. !
  1568. ! !DESCRIPTION:
  1569. ! Rearrange and integer array based on an input sortkey
  1570. !
  1571. ! !INTERFACE: -----------------------------------------------------------------
  1572. subroutine cplsortkey(num, arr, sortkey)
  1573. ! !USES:
  1574. !--- local kinds ---
  1575. integer,parameter :: R8 = ip_double_p
  1576. integer,parameter :: IN = ip_i4_p
  1577. integer,parameter :: CL = ic_lvar
  1578. ! !INPUT/OUTPUT PARAMETERS:
  1579. integer(IN),intent(in) :: num !< size of array
  1580. integer(IN),intent(inout) :: arr(:) !< field to sort
  1581. integer(IN),intent(in) :: sortkey(:) !< sortkey
  1582. ! !EOP
  1583. !--- local ---
  1584. integer(IN) :: n1,n2
  1585. integer(IN), pointer :: tmparr(:)
  1586. !--- formats ---
  1587. character(*),parameter :: subName = '(cplsortkey) '
  1588. !-------------------------------------------------------------------------------
  1589. !
  1590. !-------------------------------------------------------------------------------
  1591. ! call oasis_debug_enter(subname)
  1592. if (num /= size(arr) .or. num /= size(sortkey)) then
  1593. WRITE(nulprt,*) subname,estr,'on size of input arrays :',num,size(arr),size(sortkey)
  1594. call oasis_abort()
  1595. endif
  1596. allocate(tmparr(num))
  1597. tmparr(1:num) = arr(1:num)
  1598. do n1 = 1,num
  1599. arr(n1) = tmparr(sortkey(n1))
  1600. enddo
  1601. deallocate(tmparr)
  1602. ! call oasis_debug_exit(subname)
  1603. end subroutine cplsortkey
  1604. !------------------------------------------------------------
  1605. ! !BOP ===========================================================================
  1606. !
  1607. !> Search a character field list for a matching values
  1608. !
  1609. ! !DESCRIPTION:
  1610. ! Sort a character array and the associated array(s) based on a
  1611. ! reasonably fast sort algorithm
  1612. !
  1613. ! !INTERFACE: -----------------------------------------------------------------
  1614. subroutine cplfind(num, fldlist, fld, ifind, nfind)
  1615. ! !USES:
  1616. !--- local kinds ---
  1617. integer,parameter :: R8 = ip_double_p
  1618. integer,parameter :: IN = ip_i4_p
  1619. integer,parameter :: CL = ic_lvar
  1620. ! !INPUT/OUTPUT PARAMETERS:
  1621. integer(IN), intent(in) :: num !< size of array
  1622. character(len=CL),intent(in) :: fldlist(:) !< sorted field list
  1623. character(len=CL),intent(in) :: fld !< field to search for
  1624. integer(IN) ,intent(out) :: ifind !< first match index
  1625. integer(IN) ,intent(out) :: nfind !< number that match
  1626. ! !EOP
  1627. !--- local ---
  1628. integer(IN) :: is,ie,im
  1629. logical :: found
  1630. !--- formats ---
  1631. character(*),parameter :: subName = '(cplfind) '
  1632. !-------------------------------------------------------------------------------
  1633. !
  1634. !-------------------------------------------------------------------------------
  1635. ! call oasis_debug_enter(subname)
  1636. ifind = 0
  1637. nfind = 0
  1638. is = 1
  1639. ie = num
  1640. found = .false.
  1641. ! check endpoints first, the binary search uses integer
  1642. ! math which makes hitting the endpoints more difficult
  1643. ! so check manually. also if list size is 1, need to do this.
  1644. if (.not.found) then
  1645. im = 1
  1646. if (fld == fldlist(im)) found = .true.
  1647. endif
  1648. if (.not.found) then
  1649. im = num
  1650. if (fld == fldlist(im)) found = .true.
  1651. endif
  1652. ! do a binary search
  1653. do while (.not.found .and. ie > is)
  1654. im = (is + ie) / 2
  1655. im = max(im,is)
  1656. im = min(im,ie)
  1657. ! write(nulprt,*) subname,'tcx',is,ie,im,trim(fld),' ',trim(fldlist(im))
  1658. if (fld == fldlist(im)) then
  1659. found = .true.
  1660. elseif (fld > fldlist(im)) then
  1661. is = max(im,is+1)
  1662. else
  1663. ie = min(im,ie-1)
  1664. endif
  1665. enddo
  1666. ! if a match was found, find first and last instance of match in list
  1667. if (found) then
  1668. is = im
  1669. ie = im
  1670. if (is > 1) then
  1671. do while (fld == fldlist(is-1) .and. is > 1)
  1672. is = is - 1
  1673. enddo
  1674. endif
  1675. if (ie < num) then
  1676. do while (fld == fldlist(ie+1) .and. ie < num)
  1677. ie = ie + 1
  1678. enddo
  1679. endif
  1680. ifind = is
  1681. nfind = (ie - is + 1)
  1682. endif
  1683. ! call oasis_debug_exit(subname)
  1684. end subroutine cplfind
  1685. !------------------------------------------------------------
  1686. !> Merge routine needed for mergesort
  1687. subroutine Merge(A,X,NA,B,Y,NB,C,Z,NC)
  1688. !--- local kinds ---
  1689. integer,parameter :: R8 = ip_double_p
  1690. integer,parameter :: IN = ip_i4_p
  1691. integer,parameter :: CL = ic_lvar
  1692. integer, intent(in) :: NA,NB,NC ! Normal usage: NA+NB = NC
  1693. character(CL), intent(inout) :: A(NA) ! B overlays C(NA+1:NC)
  1694. integer(IN) , intent(inout) :: X(NA) ! B overlays C(NA+1:NC)
  1695. character(CL), intent(in) :: B(NB)
  1696. integer(IN) , intent(in) :: Y(NB)
  1697. character(CL), intent(inout) :: C(NC)
  1698. integer(IN) , intent(inout) :: Z(NC)
  1699. integer :: I,J,K
  1700. character(*),parameter :: subName = '(Merge) '
  1701. ! write(nulprt,*) subname//' NA,NB,NC = ',NA,NB,NC
  1702. I = 1; J = 1; K = 1;
  1703. do while(I <= NA .and. J <= NB)
  1704. if (A(I) <= B(J)) then
  1705. C(K) = A(I)
  1706. Z(K) = X(I)
  1707. I = I+1
  1708. else
  1709. C(K) = B(J)
  1710. Z(K) = Y(J)
  1711. J = J+1
  1712. endif
  1713. K = K + 1
  1714. enddo
  1715. do while (I <= NA)
  1716. C(K) = A(I)
  1717. Z(K) = X(I)
  1718. I = I + 1
  1719. K = K + 1
  1720. enddo
  1721. return
  1722. end subroutine merge
  1723. !------------------------------------------------------------
  1724. !> Generic mergesort routine
  1725. recursive subroutine MergeSort(N,A,T,S,Z)
  1726. !--- local kinds ---
  1727. integer,parameter :: R8 = ip_double_p
  1728. integer,parameter :: IN = ip_i4_p
  1729. integer,parameter :: CL = ic_lvar
  1730. integer , intent(in) :: N ! size
  1731. character(CL), dimension(N) , intent(inout) :: A ! data to sort
  1732. character(CL), dimension((N+1)/2), intent(out) :: T ! data tmp
  1733. integer(IN) , dimension(N) , intent(inout) :: S ! sortkey
  1734. integer(IN) , dimension((N+1)/2), intent(out) :: Z ! sortkey tmp
  1735. integer :: NA,NB
  1736. character(CL) :: V
  1737. integer(IN) :: Y
  1738. character(*),parameter :: subName = '(MergeSort) '
  1739. ! write(nulprt,*) subname//' N = ',N
  1740. if (N < 2) return
  1741. if (N == 2) then
  1742. if (A(1) > A(2)) then
  1743. V = A(1)
  1744. Y = S(1)
  1745. A(1) = A(2)
  1746. S(1) = S(2)
  1747. A(2) = V
  1748. S(2) = Y
  1749. endif
  1750. return
  1751. endif
  1752. NA=(N+1)/2
  1753. NB=N-NA
  1754. call MergeSort(NA,A,T,S,Z)
  1755. call MergeSort(NB,A(NA+1),T,S(NA+1),Z)
  1756. if (A(NA) > A(NA+1)) then
  1757. T(1:NA)=A(1:NA)
  1758. Z(1:NA)=S(1:NA)
  1759. call Merge(T,Z,NA,A(NA+1),S(NA+1),NB,A,S,N)
  1760. endif
  1761. return
  1762. end subroutine MergeSort
  1763. !===============================================================================
  1764. END MODULE mod_oasis_coupler