remap_conserv.F 91 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653
  1. C****
  2. C ************************
  3. C * OASIS MODULE *
  4. C * ------------ *
  5. C ************************
  6. C****
  7. C***********************************************************************
  8. C This module belongs to the SCRIP library. It is modified to run
  9. C within OASIS.
  10. C Main modifications:
  11. C - Some allocated array will be freed in the end to allow multiple
  12. C calls of SCRIP
  13. C - Introduction of a logical flag to distinguish between the first
  14. C and following calls of scrip conservative remapping
  15. C - Masking of overlapping grid points for source and target grid
  16. C For these points, links and weights of overlapped point are used
  17. C
  18. C Modified by V. Gayler, M&D 20.09.2001
  19. C Modified by D. Declat, CERFACS 27.06.2002
  20. C***********************************************************************
  21. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  22. !
  23. ! this module contains necessary routines for computing addresses
  24. ! and weights for a conservative interpolation between any two
  25. ! grids on a sphere. the weights are computed by performing line
  26. ! integrals around all overlap regions of the two grids. see
  27. ! Dukowicz and Kodis, SIAM J. Sci. Stat. Comput. 8, 305 (1987) and
  28. ! Jones, P.W. Monthly Weather Review (submitted).
  29. !
  30. !-----------------------------------------------------------------------
  31. !
  32. ! CVS:$Id: remap_conserv.f 1811 2008-12-19 08:41:41Z valcke $
  33. !
  34. ! Copyright (c) 1997, 1998 the Regents of the University of
  35. ! California.
  36. !
  37. ! This software and ancillary information (herein called software)
  38. ! called SCRIP is made available under the terms described here.
  39. ! The software has been approved for release with associated
  40. ! LA-CC Number 98-45.
  41. !
  42. ! Unless otherwise indicated, this software has been authored
  43. ! by an employee or employees of the University of California,
  44. ! operator of the Los Alamos National Laboratory under Contract
  45. ! No. W-7405-ENG-36 with the U.S. Department of Energy. The U.S.
  46. ! Government has rights to use, reproduce, and distribute this
  47. ! software. The public may copy and use this software without
  48. ! charge, provided that this Notice and any statement of authorship
  49. ! are reproduced on all copies. Neither the Government nor the
  50. ! University makes any warranty, express or implied, or assumes
  51. ! any liability or responsibility for the use of this software.
  52. !
  53. ! If software is modified to produce derivative works, such modified
  54. ! software should be clearly marked, so as not to confuse it with
  55. ! the version available from Los Alamos National Laboratory.
  56. !
  57. !***********************************************************************
  58. module remap_conservative
  59. !-----------------------------------------------------------------------
  60. use kinds_mod ! defines common data types
  61. use constants ! defines common constants
  62. use timers ! module for timing
  63. use grids ! module containing grid information
  64. use remap_vars ! module containing remap information
  65. USE mod_oasis_flush
  66. implicit none
  67. !-----------------------------------------------------------------------
  68. !
  69. ! module variables
  70. !
  71. !-----------------------------------------------------------------------
  72. #ifdef TREAT_OVERLAY
  73. integer (kind=int_kind), DIMENSION(:), allocatable ::
  74. $ grid2_overlap ! overlapping points
  75. #endif
  76. integer (kind=int_kind), save ::
  77. & num_srch_cells ! num cells in restricted search arrays
  78. integer (kind=int_kind), dimension(:), allocatable, save ::
  79. & srch_add ! global address of cells in srch arrays
  80. ! integer (kind=int_kind), dimension(:), allocatable, save ::
  81. ! & msk_srch_add ! masks of cells in srch arrays
  82. real (kind=dbl_kind), parameter ::
  83. & north_thresh = 1.45_dbl_kind, ! threshold for coord transf.
  84. & south_thresh =-2.00_dbl_kind ! threshold for coord transf.
  85. real (kind=dbl_kind), dimension(:,:), allocatable, save ::
  86. & srch_corner_lat, ! lat of each corner of srch cells
  87. & srch_corner_lon ! lon of each corner of srch cells
  88. !***********************************************************************
  89. contains
  90. !***********************************************************************
  91. subroutine remap_conserv
  92. !-----------------------------------------------------------------------
  93. !
  94. ! this routine traces the perimeters of every grid cell on each
  95. ! grid checking for intersections with the other grid and computing
  96. ! line integrals for each subsegment.
  97. !
  98. !-----------------------------------------------------------------------
  99. !-----------------------------------------------------------------------
  100. !
  101. ! local variables
  102. !
  103. !-----------------------------------------------------------------------
  104. integer (kind=int_kind), parameter ::
  105. & max_subseg = 10000 ! max number of subsegments per segment
  106. ! to prevent infinite loop
  107. integer (kind=int_kind) ::
  108. & grid1_add, ! current linear address for grid1 cell
  109. & grid2_add, ! current linear address for grid2 cell
  110. & min_add, ! addresses for restricting search of
  111. & max_add, ! destination grid
  112. & n, nwgt, ! generic counters
  113. & corner, ! corner of cell that segment starts from
  114. & next_corn, ! corner of cell that segment ends on
  115. & num_subseg, ! number of subsegments
  116. & overunit,
  117. & ifix_grid
  118. logical (kind=log_kind) ::
  119. & lcoinc, ! flag for coincident segments
  120. & lrevers, ! flag for reversing direction of segment
  121. & lbegin, ! flag for first integration of a segment
  122. & full, !
  123. & ll_debug ! for debug outputs
  124. logical (kind=log_kind), dimension(:), allocatable ::
  125. & srch_mask ! mask for restricting searches
  126. real (kind=dbl_kind) ::
  127. & intrsct_lat, intrsct_lon, ! lat/lon of next intersect
  128. & beglat, endlat, beglon, endlon, ! endpoints of current seg.
  129. & norm_factor, ! factor for normalizing wts
  130. & delta, ! precision
  131. & r2d
  132. real (kind=dbl_kind), dimension(:), allocatable ::
  133. & grid2_centroid_lat, grid2_centroid_lon, ! centroid coords
  134. & grid1_centroid_lat, grid1_centroid_lon ! on each grid
  135. real (kind=dbl_kind), dimension(2) :: begseg ! begin lat/lon for
  136. ! full segment
  137. real (kind=dbl_kind), dimension(6) :: weights ! local wgt array
  138. !-----------------------------------------------------------------------
  139. !
  140. IF (nlogprt .GE. 2) THEN
  141. WRITE (UNIT = nulou,FMT = *)' '
  142. WRITE (UNIT = nulou,FMT = *)'Entering routine remap_conserv'
  143. CALL OASIS_FLUSH_SCRIP(nulou)
  144. ENDIF
  145. weights = 0.
  146. !
  147. !-----------------------------------------------------------------------
  148. !
  149. ! initialize centroid arrays
  150. !
  151. !-----------------------------------------------------------------------
  152. allocate( grid1_centroid_lat(grid1_size),
  153. & grid1_centroid_lon(grid1_size),
  154. & grid2_centroid_lat(grid2_size),
  155. & grid2_centroid_lon(grid2_size))
  156. grid1_centroid_lat = zero
  157. grid1_centroid_lon = zero
  158. grid2_centroid_lat = zero
  159. grid2_centroid_lon = zero
  160. !-----------------------------------------------------------------------
  161. !
  162. ! integrate around each cell on grid1
  163. !
  164. !-----------------------------------------------------------------------
  165. allocate(srch_mask(grid2_size))
  166. #ifdef TREAT_OVERLAY
  167. ! Check overlapping point of the source grid
  168. !
  169. IF (nlogprt .GE. 2) THEN
  170. WRITE(nulou,*) 'Check overlapping point of the source grid'
  171. CALL OASIS_FLUSH_SCRIP(nulou)
  172. ENDIF
  173. CALL get_unit(overunit)
  174. OPEN(overunit, FILE = './overlap.dat', STATUS = 'UNKNOWN')
  175. WRITE(overunit, *) 'list of overlapping point of the source grid'
  176. WRITE(overunit,*) 'grid1_size =', grid1_size
  177. delta = epsilon(1.)
  178. ! Initialise array that contains addresse of overlap grid point
  179. DO grid1_add = 1,grid1_size
  180. grid1_add_repl1(grid1_add)=grid1_add
  181. END DO
  182. do grid1_add = 1,grid1_size
  183. DO n = grid1_add+1, grid1_size
  184. IF ((ABS(grid1_center_lon(grid1_add)-
  185. $ grid1_center_lon(n))<delta).and.
  186. $ (ABS(grid1_center_lat(grid1_add)-
  187. $ grid1_center_lat(n))<delta)) THEN
  188. IF (grid1_mask(n) .or. grid1_mask(grid1_add)) THEN
  189. WRITE(overunit,*)grid1_add, grid1_mask(grid1_add)
  190. $ , n, grid1_mask(n)
  191. IF (grid1_mask(n)) THEN
  192. grid1_mask(n) = .false.
  193. grid1_mask(grid1_add) = .true.
  194. grid1_add_repl1(grid1_add) = n
  195. ENDIF
  196. WRITE(overunit,*)grid1_add, grid1_mask(grid1_add)
  197. $ , n, grid1_mask(n)
  198. ENDIF
  199. END IF
  200. END DO
  201. END DO
  202. ! Check overlapping point of the target grid
  203. !
  204. IF (nlogprt .GE. 2) THEN
  205. WRITE(nulou,*) 'Check overlapping point of the target grid'
  206. CALL OASIS_FLUSH_SCRIP(nulou)
  207. ENDIF
  208. WRITE(overunit, *) 'list of overlapping point of the target grid'
  209. WRITE(overunit,*) 'grid2_size =', grid2_size
  210. allocate(grid2_overlap(grid2_size))
  211. grid2_overlap = -1
  212. delta = epsilon(1.)
  213. DO grid2_add = 1,grid2_size
  214. DO n = grid2_add+1, grid2_size
  215. IF ((ABS(grid2_center_lon(grid2_add)-
  216. $ grid2_center_lon(n))<delta).and.
  217. $ (ABS(grid2_center_lat(grid2_add)-
  218. $ grid2_center_lat(n))<delta)) THEN
  219. grid2_overlap(grid2_add) = n
  220. WRITE(overunit,*)grid2_add, grid2_mask(grid2_add)
  221. $ , n, grid2_mask(n)
  222. END IF
  223. END DO
  224. END DO
  225. CALL release_UNIT(overunit)
  226. #endif TREAT_OVERLAY
  227. ! Sweeps
  228. IF (nlogprt .GE. 2) THEN
  229. WRITE (nulou,*) 'grid1 sweep '
  230. CALL OASIS_FLUSH_SCRIP(nulou)
  231. ENDIF
  232. !
  233. ll_debug = .false.
  234. ifix_grid=6975
  235. do grid1_add = 1,grid1_size
  236. IF (ll_debug) THEN
  237. WRITE(88,*) 'grid1_add=', grid1_add
  238. CALL OASIS_FLUSH_SCRIP(88)
  239. ENDIF
  240. !***
  241. !*** restrict searches first using search bins
  242. !***
  243. call timer_start(1)
  244. min_add = grid2_size
  245. max_add = 1
  246. do n=1,num_srch_bins
  247. if (grid1_add >= bin_addr1(1,n) .and.
  248. & grid1_add <= bin_addr1(2,n)) then
  249. min_add = min(min_add, bin_addr2(1,n))
  250. max_add = max(max_add, bin_addr2(2,n))
  251. endif
  252. end do
  253. !***
  254. !*** further restrict searches using bounding boxes
  255. !***
  256. num_srch_cells = 0
  257. do grid2_add = min_add,max_add
  258. srch_mask(grid2_add) = (grid2_bound_box(1,grid2_add) <=
  259. & grid1_bound_box(2,grid1_add)) .and.
  260. & (grid2_bound_box(2,grid2_add) >=
  261. & grid1_bound_box(1,grid1_add)) .and.
  262. & (grid2_bound_box(3,grid2_add) <=
  263. & grid1_bound_box(4,grid1_add)) .and.
  264. & (grid2_bound_box(4,grid2_add) >=
  265. & grid1_bound_box(3,grid1_add))
  266. if (srch_mask(grid2_add)) num_srch_cells = num_srch_cells+1
  267. end do
  268. !***
  269. !*** create search arrays
  270. !***
  271. ! allocate(srch_add(num_srch_cells), msk_srch_add(num_srch_cells),
  272. ! & srch_corner_lat(grid2_corners,num_srch_cells),
  273. ! & srch_corner_lon(grid2_corners,num_srch_cells))
  274. allocate(srch_add(num_srch_cells),
  275. & srch_corner_lat(grid2_corners,num_srch_cells),
  276. & srch_corner_lon(grid2_corners,num_srch_cells))
  277. n = 0
  278. gather1: do grid2_add = min_add,max_add
  279. if (srch_mask(grid2_add)) then
  280. n = n+1
  281. srch_add(n) = grid2_add
  282. srch_corner_lat(:,n) = grid2_corner_lat(:,grid2_add)
  283. srch_corner_lon(:,n) = grid2_corner_lon(:,grid2_add)
  284. endif
  285. end do gather1
  286. call timer_stop(1)
  287. IF (ll_debug) THEN
  288. WRITE(88,*)' '
  289. WRITE(88,*)' ** Grid1 cell and associated search cells **'
  290. DO corner = 1,grid1_corners
  291. WRITE(88,1111) corner,
  292. & grid1_corner_lon(corner,grid1_add),
  293. & grid1_corner_lat(corner,grid1_add)
  294. ENDDO
  295. WRITE(88,*) ' num_srch_cells=', num_srch_cells
  296. WRITE(88,*) ' '
  297. IF (num_srch_cells .ne. 0)
  298. & WRITE(88,*) ' srch_add(:)=', srch_add(:)
  299. DO n=1, num_srch_cells
  300. DO corner = 1,grid2_corners
  301. WRITE(88,1112) n, srch_corner_lon(corner,n),
  302. & srch_corner_lat(corner,n)
  303. END DO
  304. END DO
  305. WRITE(88,*)' ***************************************'
  306. WRITE(88,*)' '
  307. CALL OASIS_FLUSH_SCRIP(88)
  308. ENDIF
  309. 1111 format (' grid1 corner, lon, lat = ', I8, 2X, F12.4, 2X, F12.4)
  310. 1112 format (' srch cell, lon, lat = ', I8, 2X, F12.4, 2X, F12.4)
  311. !***
  312. !*** integrate around this cell
  313. !***
  314. do corner = 1,grid1_corners
  315. next_corn = mod(corner,grid1_corners) + 1
  316. !***
  317. !*** define endpoints of the current segment
  318. !***
  319. beglat = grid1_corner_lat(corner,grid1_add)
  320. beglon = grid1_corner_lon(corner,grid1_add)
  321. endlat = grid1_corner_lat(next_corn,grid1_add)
  322. endlon = grid1_corner_lon(next_corn,grid1_add)
  323. lrevers = .false.
  324. !***
  325. !*** to ensure exact path taken during both
  326. !*** sweeps, always integrate segments in the same
  327. !*** direction (SW to NE).
  328. !***
  329. if ((endlat < beglat) .or.
  330. & (endlat == beglat .and. endlon < beglon)) then
  331. beglat = grid1_corner_lat(next_corn,grid1_add)
  332. beglon = grid1_corner_lon(next_corn,grid1_add)
  333. endlat = grid1_corner_lat(corner,grid1_add)
  334. endlon = grid1_corner_lon(corner,grid1_add)
  335. lrevers = .true.
  336. IF (ll_debug) WRITE(88, *) ' sweep1 LREVERS TRUE'
  337. endif
  338. begseg(1) = beglat
  339. begseg(2) = beglon
  340. lbegin = .true.
  341. num_subseg = 0
  342. !***
  343. !*** if this is a constant-longitude segment, skip the rest
  344. !*** since the line integral contribution will be zero.
  345. !***
  346. IF (ll_debug) THEN
  347. IF (endlon .eq. beglon) THEN
  348. WRITE(88,1113) beglon, beglat
  349. WRITE(88,1114) endlon, endlat
  350. WRITE(88, *)' sweep1 endlon == beglon; skip segment'
  351. WRITE(88,*) ' '
  352. ENDIF
  353. ENDIF
  354. 1113 format (' endlon == beglon; beglon, beglat = ',
  355. & 2X, F12.4, 2X, F12.4)
  356. 1114 format (' endlon == beglon; endlon, endlat = ',
  357. & 2X, F12.4, 2X, F12.4)
  358. if (endlon /= beglon) then
  359. !***
  360. !*** integrate along this segment, detecting intersections
  361. !*** and computing the line integral for each sub-segment
  362. !***
  363. do while (beglat /= endlat .or. beglon /= endlon)
  364. !***
  365. !*** prevent infinite loops if integration gets stuck
  366. !*** near cell or threshold boundary
  367. !***
  368. num_subseg = num_subseg + 1
  369. if (num_subseg > max_subseg) THEN
  370. write(nulou,*) 'ERROR=>integration stalled:'
  371. write(nulou,*) 'num_subseg exceeded limit'
  372. write(nulou,*)
  373. & '=>Verify corners in grids.nc, especially'
  374. write(nulou,*)
  375. & 'if calculated by OASIS routine corners'
  376. write(nulou,*)
  377. & 'integration stalled: num_subseg exceeded limit'
  378. CALL OASIS_FLUSH_SCRIP(nulou)
  379. stop
  380. endif
  381. !***
  382. !*** find next intersection of this segment with a grid
  383. !*** line on grid 2.
  384. !***
  385. call timer_start(2)
  386. IF (ll_debug) THEN
  387. WRITE(88,*) ' '
  388. WRITE(88,1115) beglon, beglat
  389. WRITE(88,1116) endlon, endlat
  390. WRITE(88,*) ' '
  391. CALL OASIS_FLUSH_SCRIP(88)
  392. ENDIF
  393. 1115 format (' avant intersection; beglon, beglat = ',
  394. & 2X, F12.4, 2X, F12.4)
  395. 1116 format (' avant intersection; endlon, endlat = ',
  396. & 2X, F12.4, 2X, F12.4)
  397. call intersection(grid2_add,intrsct_lat,intrsct_lon,
  398. & lcoinc, beglat, beglon, endlat, endlon, begseg,
  399. & lbegin, lrevers)
  400. IF (ll_debug) THEN
  401. WRITE(88,*) ' After call intersection, grid2_add',
  402. & grid2_add
  403. WRITE(88,1117) beglon, beglat
  404. WRITE(88,1118) endlon, endlat
  405. WRITE(88,1119) intrsct_lon, intrsct_lat
  406. WRITE(88,*) ' '
  407. CALL OASIS_FLUSH_SCRIP(88)
  408. ENDIF
  409. 1117 format(' après intersection; beglon, beglat = ',
  410. & 2X, F12.4, 2X, F12.4)
  411. 1118 format (' après intersection; endlon, endlat = ',
  412. & 2X, F12.4, 2X, F12.4)
  413. 1119 format (' après intersection; intrsct_lon, intrsct_lat = ',
  414. & 2X, F12.4, 2X, F12.4)
  415. call timer_stop(2)
  416. lbegin = .false.
  417. !***
  418. !*** compute line integral for this subsegment.
  419. !***
  420. call timer_start(3)
  421. if (grid2_add /= 0) THEN
  422. call line_integral(weights, num_wts,
  423. & beglon, intrsct_lon, beglat, intrsct_lat,
  424. & grid1_center_lon(grid1_add),
  425. & grid2_center_lon(grid2_add))
  426. IF (ll_debug) THEN
  427. WRITE(88,*) ' A1) WEIGHTS for this subsegment =',
  428. & weights(1)
  429. WRITE(88,*) ' '
  430. CALL OASIS_FLUSH_SCRIP(88)
  431. ENDIF
  432. else
  433. call line_integral(weights, num_wts,
  434. & beglon, intrsct_lon, beglat, intrsct_lat,
  435. & grid1_center_lon(grid1_add),
  436. & grid1_center_lon(grid1_add))
  437. IF (ll_debug) THEN
  438. WRITE(88,*) ' B1) WEIGHTS for this subsegment =',
  439. & weights(1)
  440. WRITE(88,*) ' '
  441. CALL OASIS_FLUSH_SCRIP(88)
  442. ENDIF
  443. endif
  444. call timer_stop(3)
  445. !***
  446. !*** if integrating in reverse order, change
  447. !*** sign of weights
  448. !***
  449. if (lrevers) then
  450. weights = -weights
  451. IF (ll_debug) THEN
  452. WRITE(88,*) ' LREVERS; WEIGHTS for this subsegment =',
  453. & weights(1)
  454. WRITE(88,*) ' '
  455. ENDIF
  456. ENDIF
  457. !***
  458. !*** store the appropriate addresses and weights.
  459. !*** also add contributions to cell areas and centroids.
  460. !***
  461. 1120 format (' STORE add1,add2,blon,blat,ilon,ilat,WEIGHTS=',
  462. & 1X,I8,1X,I8,1X,F12.8,1X,F12.8,1X,F12.8,1X,F12.8, E12.8)
  463. 1121 format (' overlap STORE grid1_add, grid2_add, WEIGHTS=',
  464. & 1X,I8,1X,I8,1X,F12.8,1X,F12.8,1X,F12.8,1X,F12.8, E12.8)
  465. 1122 format (' lfracnei STORE grid1_add, grid2_add, WEIGHTS=',
  466. & 1X,I8,1X,I8,1X,F12.8,1X,F12.8,1X,F12.8,1X,F12.8, E12.8)
  467. if (grid2_add /= 0) then
  468. if (grid1_mask(grid1_add)) then
  469. call timer_start(4)
  470. call store_link_cnsrv(grid1_add, grid2_add,
  471. & weights)
  472. IF (ll_debug) THEN
  473. WRITE(88,*) ' after store_link_cnsrv norm1'
  474. WRITE(88,1120) grid1_add, grid2_add,beglon, beglat,
  475. & intrsct_lon,intrsct_lat,weights(1)
  476. ENDIF
  477. #ifdef TREAT_OVERLAY
  478. IF (grid2_overlap(grid2_add)/=-1) then
  479. call store_link_cnsrv(grid1_add,
  480. & grid2_overlap(grid2_add), weights)
  481. IF (ll_debug) THEN
  482. WRITE(88,*) ' after store_link_cnsrv overlap1'
  483. WRITE(88,1121) grid1_add, grid2_add,beglon, beglat,
  484. & intrsct_lon,intrsct_lat,weights(1)
  485. ENDIF
  486. ENDIF
  487. #endif
  488. call timer_stop(4)
  489. grid1_frac(grid1_add) = grid1_frac(grid1_add)
  490. & + weights(1)
  491. grid2_frac(grid2_add) = grid2_frac(grid2_add)
  492. & + weights(num_wts+1)
  493. #ifdef TREAT_OVERLAY
  494. IF (grid2_overlap(grid2_add)/=-1)
  495. $ grid2_frac(grid2_overlap(grid2_add)) =
  496. $ grid2_frac(grid2_overlap(grid2_add)) +
  497. $ weights(num_wts+1)
  498. #endif
  499. endif
  500. endif
  501. grid1_area(grid1_add) = grid1_area(grid1_add)
  502. & + weights(1)
  503. grid1_centroid_lat(grid1_add) =
  504. & grid1_centroid_lat(grid1_add) + weights(2)
  505. grid1_centroid_lon(grid1_add) =
  506. & grid1_centroid_lon(grid1_add) + weights(3)
  507. !***
  508. !*** reset beglat and beglon for next subsegment.
  509. !***
  510. beglat = intrsct_lat
  511. beglon = intrsct_lon
  512. end do
  513. endif
  514. !***
  515. !*** end of segment
  516. !***
  517. end do
  518. !***
  519. !*** finished with this cell: deallocate search array and
  520. !*** start on next cell
  521. ! deallocate(srch_add, msk_srch_add, srch_corner_lat,
  522. ! & srch_corner_lon)
  523. deallocate(srch_add, srch_corner_lat,
  524. & srch_corner_lon)
  525. end do
  526. deallocate(srch_mask)
  527. IF (nlogprt .GE. 2) THEN
  528. WRITE(nulou,*) 'grid1 end sweep '
  529. CALL OASIS_FLUSH_SCRIP(nulou)
  530. ENDIF
  531. !
  532. !-----------------------------------------------------------------------
  533. !
  534. ! integrate around each cell on grid2
  535. !
  536. !-----------------------------------------------------------------------
  537. allocate(srch_mask(grid1_size))
  538. IF (nlogprt .GE. 2) THEN
  539. WRITE(nulou,*) 'grid2 sweep '
  540. CALL OASIS_FLUSH_SCRIP(nulou)
  541. ENDIF
  542. do grid2_add = 1,grid2_size
  543. IF (ll_debug .and. grid2_add == ifix_grid ) THEN
  544. WRITE(98,*) 'grid2_add=', grid2_add
  545. CALL OASIS_FLUSH_SCRIP(88)
  546. ENDIF
  547. !***
  548. !*** restrict searches first using search bins
  549. !***
  550. call timer_start(5)
  551. min_add = grid1_size
  552. max_add = 1
  553. do n=1,num_srch_bins
  554. if (grid2_add >= bin_addr2(1,n) .and.
  555. & grid2_add <= bin_addr2(2,n)) then
  556. min_add = min(min_add, bin_addr1(1,n))
  557. max_add = max(max_add, bin_addr1(2,n))
  558. endif
  559. end do
  560. !***
  561. !*** further restrict searches using bounding boxes
  562. !***
  563. num_srch_cells = 0
  564. do grid1_add = min_add, max_add
  565. srch_mask(grid1_add) = (grid1_bound_box(1,grid1_add) <=
  566. & grid2_bound_box(2,grid2_add)) .and.
  567. & (grid1_bound_box(2,grid1_add) >=
  568. & grid2_bound_box(1,grid2_add)) .and.
  569. & (grid1_bound_box(3,grid1_add) <=
  570. & grid2_bound_box(4,grid2_add)) .and.
  571. & (grid1_bound_box(4,grid1_add) >=
  572. & grid2_bound_box(3,grid2_add))
  573. if (srch_mask(grid1_add)) num_srch_cells = num_srch_cells+1
  574. end DO
  575. ! allocate(srch_add(num_srch_cells),msk_srch_add(num_srch_cells),
  576. ! & srch_corner_lat(grid1_corners,num_srch_cells),
  577. ! & srch_corner_lon(grid1_corners,num_srch_cells))
  578. allocate(srch_add(num_srch_cells),
  579. & srch_corner_lat(grid1_corners,num_srch_cells),
  580. & srch_corner_lon(grid1_corners,num_srch_cells))
  581. n = 0
  582. gather2: do grid1_add = min_add,max_add
  583. if (srch_mask(grid1_add)) then
  584. n = n+1
  585. srch_add(n) = grid1_add
  586. ! msk_srch_add(n) = srch_mask(grid1_add)
  587. srch_corner_lat(:,n) = grid1_corner_lat(:,grid1_add)
  588. srch_corner_lon(:,n) = grid1_corner_lon(:,grid1_add)
  589. endif
  590. end do gather2
  591. call timer_stop(5)
  592. IF (ll_debug .and. grid2_add == ifix_grid) THEN
  593. WRITE(98,*)' '
  594. WRITE(98,*)' ** Grid2 cell and associated search cells **'
  595. DO corner = 1,grid2_corners
  596. WRITE(98,1131) corner,
  597. & grid2_corner_lon(corner,grid2_add),
  598. & grid2_corner_lat(corner,grid2_add)
  599. ENDDO
  600. WRITE(98,*) ' num_srch_cells=', num_srch_cells
  601. WRITE(98,*) ' '
  602. WRITE(98,*) ' srch_add(:)=', srch_add(:)
  603. ! WRITE(98,*) ' msk_srch_add(:)=', msk_srch_add(:)
  604. DO n=1, num_srch_cells
  605. DO corner = 1,grid2_corners
  606. WRITE(98,1132) n, srch_corner_lon(corner,n),
  607. & srch_corner_lat(corner,n)
  608. END DO
  609. END DO
  610. WRITE(98,*)' ***************************************'
  611. WRITE(98,*)' '
  612. ENDIF
  613. 1131 format (' grid2 corner, lon, lat = ', I8, 2X, F12.4, 2X, F12.4)
  614. 1132 format (' srch cell, lon, lat = ', I8, 2X, F12.4, 2X, F12.4)
  615. !***
  616. !*** integrate around this cell
  617. !***
  618. ! full = .false.
  619. ! do grid1_add = min_add,max_add
  620. ! if (grid1_mask(grid1_add)) full = .true.
  621. ! end do
  622. ! if (full) then
  623. do corner = 1,grid2_corners
  624. next_corn = mod(corner,grid2_corners) + 1
  625. beglat = grid2_corner_lat(corner,grid2_add)
  626. beglon = grid2_corner_lon(corner,grid2_add)
  627. endlat = grid2_corner_lat(next_corn,grid2_add)
  628. endlon = grid2_corner_lon(next_corn,grid2_add)
  629. lrevers = .false.
  630. !***
  631. !*** to ensure exact path taken during both
  632. !*** sweeps, always integrate in the same direction
  633. !***
  634. if ((endlat < beglat) .or.
  635. & (endlat == beglat .and. endlon < beglon)) then
  636. beglat = grid2_corner_lat(next_corn,grid2_add)
  637. beglon = grid2_corner_lon(next_corn,grid2_add)
  638. endlat = grid2_corner_lat(corner,grid2_add)
  639. endlon = grid2_corner_lon(corner,grid2_add)
  640. lrevers = .true.
  641. IF (ll_debug .and. grid2_add == ifix_grid)
  642. $ WRITE(98, *) ' sweep2 LREVERS TRUE'
  643. endif
  644. begseg(1) = beglat
  645. begseg(2) = beglon
  646. lbegin = .true.
  647. !***
  648. !*** if this is a constant-longitude segment, skip the rest
  649. !*** since the line integral contribution will be zero.
  650. !***
  651. IF (ll_debug .and. grid2_add == ifix_grid) THEN
  652. IF (endlon .eq. beglon) THEN
  653. WRITE(98,1113) beglon, beglat
  654. WRITE(98,1114) endlon, endlat
  655. WRITE(98, *)' sweep2 endlon == beglon; skip segment'
  656. WRITE(98,*) ' '
  657. ENDIF
  658. ENDIF
  659. if (endlon /= beglon) then
  660. num_subseg = 0
  661. !***
  662. !*** integrate along this segment, detecting intersections
  663. !*** and computing the line integral for each sub-segment
  664. !***
  665. do while (beglat /= endlat .or. beglon /= endlon)
  666. !***
  667. !*** prevent infinite loops if integration gets stuck
  668. !*** near cell or threshold boundary
  669. !***
  670. num_subseg = num_subseg + 1
  671. if (num_subseg > max_subseg) THEN
  672. write(nulou,*) 'ERROR=>integration stalled:'
  673. write(nulou,*) 'num_subseg exceeded limit'
  674. write(nulou,*) 'Verify corners in grids.nc, especially'
  675. write(nulou,*) 'if calculated by OASIS routine corners'
  676. write(nulou,*)
  677. & 'integration stalled: num_subseg exceeded limit'
  678. CALL OASIS_FLUSH_SCRIP(nulou)
  679. stop
  680. endif
  681. !***
  682. !*** find next intersection of this segment with a line
  683. !*** on grid 1.
  684. !***
  685. call timer_start(6)
  686. IF (ll_debug .and. grid2_add == ifix_grid) THEN
  687. WRITE(98,1115) beglon, beglat
  688. WRITE(98,1116) endlon, endlat
  689. WRITE(98,*) ' '
  690. ENDIF
  691. call intersection(grid1_add,intrsct_lat,intrsct_lon,lcoinc,
  692. & beglat, beglon, endlat, endlon, begseg,
  693. & lbegin, lrevers)
  694. IF (ll_debug .and. grid2_add == ifix_grid) THEN
  695. WRITE(98,*) ' After call intersection, grid1_add',
  696. & grid1_add
  697. WRITE(98,1117) beglon, beglat
  698. WRITE(98,1118) endlon, endlat
  699. WRITE(98,1119) intrsct_lon, intrsct_lat
  700. WRITE(98,*) ' '
  701. ENDIF
  702. call timer_stop(6)
  703. lbegin = .false.
  704. !***
  705. !*** compute line integral for this subsegment.
  706. !***
  707. call timer_start(7)
  708. if (grid1_add /= 0) then
  709. call line_integral(weights, num_wts,
  710. & beglon, intrsct_lon, beglat, intrsct_lat,
  711. & grid1_center_lon(grid1_add),
  712. & grid2_center_lon(grid2_add))
  713. IF (ll_debug .and. grid2_add == ifix_grid) THEN
  714. WRITE(98,*) ' A2) WEIGHTS for this subsegment =',
  715. & weights(1)
  716. WRITE(98,*) ' '
  717. ENDIF
  718. else
  719. call line_integral(weights, num_wts,
  720. & beglon, intrsct_lon, beglat, intrsct_lat,
  721. & grid2_center_lon(grid2_add),
  722. & grid2_center_lon(grid2_add))
  723. IF (ll_debug .and. grid2_add == ifix_grid) THEN
  724. WRITE(98,*) ' B2) WEIGHTS for this subsegment =',
  725. & weights(1)
  726. WRITE(98,*) ' '
  727. ENDIF
  728. endif
  729. call timer_stop(7)
  730. if (lrevers) then
  731. weights = -weights
  732. IF (ll_debug .and. grid2_add == ifix_grid) THEN
  733. WRITE(98,*) ' LREVERS; WEIGHTS for this subsegment =',
  734. & weights(1)
  735. WRITE(98,*) ' '
  736. ENDIF
  737. endif
  738. !***
  739. !*** store the appropriate addresses and weights.
  740. !*** also add contributions to cell areas and centroids.
  741. !*** if there is a coincidence, do not store weights
  742. !*** because they have been captured in the previous loop.
  743. !*** the grid1 mask is the master mask
  744. !***
  745. IF (ll_debug .and. lcoinc .and. grid2_add == ifix_grid)
  746. & WRITE(98,*) ' LCOINC is TRUE; weight not stored'
  747. if (.not. lcoinc .and. grid1_add /= 0) then
  748. if (grid1_mask(grid1_add)) then
  749. call timer_start(8)
  750. call store_link_cnsrv(grid1_add, grid2_add, weights)
  751. IF (ll_debug .and. grid2_add == ifix_grid) THEN
  752. WRITE(98,*) ' after store_link_cnsrv norm2'
  753. WRITE(98,1120) grid1_add, grid2_add,beglon, beglat,
  754. & intrsct_lon,intrsct_lat,weights(1)
  755. ENDIF
  756. call timer_stop(8)
  757. grid1_frac(grid1_add) = grid1_frac(grid1_add) +
  758. & weights(1)
  759. grid2_frac(grid2_add) = grid2_frac(grid2_add) +
  760. & weights(num_wts+1)
  761. endif
  762. endif
  763. grid2_area(grid2_add) = grid2_area(grid2_add) +
  764. & weights(num_wts+1)
  765. grid2_centroid_lat(grid2_add) =
  766. & grid2_centroid_lat(grid2_add) + weights(num_wts+2)
  767. grid2_centroid_lon(grid2_add) =
  768. & grid2_centroid_lon(grid2_add) + weights(num_wts+3)
  769. !***
  770. !*** reset beglat and beglon for next subsegment.
  771. !***
  772. beglat = intrsct_lat
  773. beglon = intrsct_lon
  774. end DO
  775. END if
  776. !***
  777. !*** end of segment
  778. !***
  779. end do
  780. !***
  781. !*** finished with this cell: deallocate search array and
  782. !*** start on next cell
  783. ! deallocate(srch_add, msk_srch_add, srch_corner_lat,
  784. ! & srch_corner_lon)
  785. deallocate(srch_add, srch_corner_lat,
  786. & srch_corner_lon)
  787. end do
  788. deallocate(srch_mask)
  789. #ifdef TREAT_OVERLAY
  790. deallocate(grid2_overlap)
  791. #endif
  792. IF (nlogprt .GE. 2) THEN
  793. WRITE(nulou,*) 'grid2 end sweep '
  794. CALL OASIS_FLUSH_SCRIP(nulou)
  795. ENDIF
  796. IF (ll_debug) THEN
  797. do n=1,num_links_map1
  798. WRITE(88,*) 'grid1, grid2, weight= ',
  799. & grid1_add_map1(n), grid2_add_map1(n), wts_map1(1,n)
  800. END DO
  801. ENDIF
  802. !-----------------------------------------------------------------------
  803. !
  804. ! correct for situations where N/S pole not explicitly included in
  805. ! grid (i.e. as a grid corner point). if pole is missing from only
  806. ! one grid, need to correct only the area and centroid of that
  807. ! grid. if missing from both, do complete weight calculation.
  808. !
  809. !-----------------------------------------------------------------------
  810. !*** North Pole
  811. weights(1) = pi2
  812. weights(2) = pi*pi
  813. weights(3) = zero
  814. weights(4) = pi2
  815. weights(5) = pi*pi
  816. weights(6) = zero
  817. grid1_add = 0
  818. pole_loop1: do n=1,grid1_size
  819. if (grid1_area(n) < -three*pih .and.
  820. & grid1_center_lat(n) > zero) then
  821. grid1_add = n
  822. exit pole_loop1
  823. endif
  824. end do pole_loop1
  825. grid2_add = 0
  826. pole_loop2: do n=1,grid2_size
  827. if (grid2_area(n) < -three*pih .and.
  828. & grid2_center_lat(n) > zero) then
  829. grid2_add = n
  830. exit pole_loop2
  831. endif
  832. end do pole_loop2
  833. if (grid1_add /=0) then
  834. grid1_area(grid1_add) = grid1_area(grid1_add) + weights(1)
  835. grid1_centroid_lat(grid1_add) =
  836. & grid1_centroid_lat(grid1_add) + weights(2)
  837. grid1_centroid_lon(grid1_add) =
  838. & grid1_centroid_lon(grid1_add) + weights(3)
  839. endif
  840. if (grid2_add /=0) then
  841. grid2_area(grid2_add) = grid2_area(grid2_add) +
  842. & weights(num_wts+1)
  843. grid2_centroid_lat(grid2_add) =
  844. & grid2_centroid_lat(grid2_add) + weights(num_wts+2)
  845. grid2_centroid_lon(grid2_add) =
  846. & grid2_centroid_lon(grid2_add) + weights(num_wts+3)
  847. endif
  848. if (grid1_add /= 0 .and. grid2_add /=0) then
  849. call store_link_cnsrv(grid1_add, grid2_add, weights)
  850. grid1_frac(grid1_add) = grid1_frac(grid1_add) +
  851. & weights(1)
  852. grid2_frac(grid2_add) = grid2_frac(grid2_add) +
  853. & weights(num_wts+1)
  854. endif
  855. !*** South Pole
  856. weights(1) = pi2
  857. weights(2) = -pi*pi
  858. weights(3) = zero
  859. weights(4) = pi2
  860. weights(5) = -pi*pi
  861. weights(6) = zero
  862. grid1_add = 0
  863. pole_loop3: do n=1,grid1_size
  864. if (grid1_area(n) < -three*pih .and.
  865. & grid1_center_lat(n) < zero) then
  866. grid1_add = n
  867. exit pole_loop3
  868. endif
  869. end do pole_loop3
  870. grid2_add = 0
  871. pole_loop4: do n=1,grid2_size
  872. if (grid2_area(n) < -three*pih .and.
  873. & grid2_center_lat(n) < zero) then
  874. grid2_add = n
  875. exit pole_loop4
  876. endif
  877. end do pole_loop4
  878. if (grid1_add /=0) then
  879. grid1_area(grid1_add) = grid1_area(grid1_add) + weights(1)
  880. grid1_centroid_lat(grid1_add) =
  881. & grid1_centroid_lat(grid1_add) + weights(2)
  882. grid1_centroid_lon(grid1_add) =
  883. & grid1_centroid_lon(grid1_add) + weights(3)
  884. endif
  885. if (grid2_add /=0) then
  886. grid2_area(grid2_add) = grid2_area(grid2_add) +
  887. & weights(num_wts+1)
  888. grid2_centroid_lat(grid2_add) =
  889. & grid2_centroid_lat(grid2_add) + weights(num_wts+2)
  890. grid2_centroid_lon(grid2_add) =
  891. & grid2_centroid_lon(grid2_add) + weights(num_wts+3)
  892. endif
  893. if (grid1_add /= 0 .and. grid2_add /=0) then
  894. call store_link_cnsrv(grid1_add, grid2_add, weights)
  895. grid1_frac(grid1_add) = grid1_frac(grid1_add) +
  896. & weights(1)
  897. grid2_frac(grid2_add) = grid2_frac(grid2_add) +
  898. & weights(num_wts+1)
  899. endif
  900. !-----------------------------------------------------------------------
  901. !
  902. ! finish centroid computation
  903. !
  904. !-----------------------------------------------------------------------
  905. where (grid1_area /= zero)
  906. grid1_centroid_lat = grid1_centroid_lat/grid1_area
  907. grid1_centroid_lon = grid1_centroid_lon/grid1_area
  908. end where
  909. where (grid2_area /= zero)
  910. grid2_centroid_lat = grid2_centroid_lat/grid2_area
  911. grid2_centroid_lon = grid2_centroid_lon/grid2_area
  912. end where
  913. !-----------------------------------------------------------------------
  914. !
  915. ! include centroids in weights and normalize using destination
  916. ! area if requested
  917. !
  918. !-----------------------------------------------------------------------
  919. do n=1,num_links_map1
  920. grid1_add = grid1_add_map1(n)
  921. grid2_add = grid2_add_map1(n)
  922. do nwgt=1,num_wts
  923. weights( nwgt) = wts_map1(nwgt,n)
  924. ! if (num_maps > 1) then
  925. ! weights(num_wts+nwgt) = wts_map2(nwgt,n)
  926. ! endif
  927. end do
  928. select case(norm_opt)
  929. case (norm_opt_dstarea)
  930. if (grid2_area(grid2_add) /= zero) then
  931. if (luse_grid2_area) then
  932. norm_factor = one/grid2_area_in(grid2_add)
  933. else
  934. norm_factor = one/grid2_area(grid2_add)
  935. endif
  936. else
  937. norm_factor = zero
  938. endif
  939. case (norm_opt_frcarea)
  940. if (grid2_frac(grid2_add) /= zero) then
  941. if (luse_grid2_area) then
  942. norm_factor = grid2_area(grid2_add)/
  943. & (grid2_frac(grid2_add)*
  944. & grid2_area_in(grid2_add))
  945. else
  946. norm_factor = one/grid2_frac(grid2_add)
  947. endif
  948. else
  949. norm_factor = zero
  950. endif
  951. case (norm_opt_none)
  952. norm_factor = one
  953. end select
  954. wts_map1(1,n) = weights(1)*norm_factor
  955. wts_map1(2,n) = (weights(2) - weights(1)*
  956. & grid1_centroid_lat(grid1_add))*
  957. & norm_factor
  958. wts_map1(3,n) = (weights(3) - weights(1)*
  959. & grid1_centroid_lon(grid1_add))*
  960. & norm_factor
  961. ! if (num_maps > 1) then
  962. ! select case(norm_opt)
  963. ! case (norm_opt_dstarea)
  964. ! if (grid1_area(grid1_add) /= zero) then
  965. ! if (luse_grid1_area) then
  966. ! norm_factor = one/grid1_area_in(grid1_add)
  967. ! else
  968. ! norm_factor = one/grid1_area(grid1_add)
  969. ! endif
  970. ! else
  971. ! norm_factor = zero
  972. ! endif
  973. ! case (norm_opt_frcarea)
  974. ! if (grid1_frac(grid1_add) /= zero) then
  975. ! if (luse_grid1_area) then
  976. ! norm_factor = grid1_area(grid1_add)/
  977. ! & (grid1_frac(grid1_add)*
  978. ! & grid1_area_in(grid1_add))
  979. ! else
  980. ! norm_factor = one/grid1_frac(grid1_add)
  981. ! endif
  982. ! else
  983. ! norm_factor = zero
  984. ! endif
  985. ! case (norm_opt_none)
  986. ! norm_factor = one
  987. ! end select
  988. !
  989. ! wts_map2(1,n) = weights(num_wts+1)*norm_factor
  990. ! wts_map2(2,n) = (weights(num_wts+2) - weights(num_wts+1)*
  991. ! & grid2_centroid_lat(grid2_add))*
  992. ! & norm_factor
  993. ! wts_map2(3,n) = (weights(num_wts+3) - weights(num_wts+1)*
  994. ! & grid2_centroid_lon(grid2_add))*
  995. ! & norm_factor
  996. ! endif
  997. end do
  998. IF (nlogprt .GE. 2) THEN
  999. WRITE(nulou,*) 'Total number of links = ',num_links_map1
  1000. CALL OASIS_FLUSH_SCRIP(nulou)
  1001. ENDIF
  1002. where (grid1_area /= zero) grid1_frac = grid1_frac/grid1_area
  1003. where (grid2_area /= zero) grid2_frac = grid2_frac/grid2_area
  1004. !-----------------------------------------------------------------------
  1005. !
  1006. ! perform some error checking on final weights
  1007. !
  1008. !-----------------------------------------------------------------------
  1009. grid2_centroid_lat = zero
  1010. grid2_centroid_lon = zero
  1011. do n=1,grid1_size
  1012. IF (nlogprt .GE. 2) THEN
  1013. if (grid1_area(n) < -.01) then
  1014. WRITE(nulou,*) 'Grid 1 area error: n, area, mask ='
  1015. & ,n,grid1_area(n), grid1_mask(n)
  1016. endif
  1017. if (grid1_centroid_lat(n) < -pih-.01 .or.
  1018. & grid1_centroid_lat(n) > pih+.01) then
  1019. WRITE(nulou,*)'Grid1 centroid lat error:
  1020. &n, centroid_lat, mask='
  1021. & ,n,grid1_centroid_lat(n), grid1_mask(n)
  1022. endif
  1023. CALL OASIS_FLUSH_SCRIP(nulou)
  1024. ENDIF
  1025. grid1_centroid_lat(n) = zero
  1026. grid1_centroid_lon(n) = zero
  1027. end do
  1028. do n=1,grid2_size
  1029. IF (nlogprt .GE. 2) THEN
  1030. if (grid2_area(n) < -.01) then
  1031. WRITE(nulou,*) 'Grid 2 area error: n, area, mask ='
  1032. & ,n,grid2_area(n), grid2_mask(n)
  1033. endif
  1034. if (grid2_centroid_lat(n) < -pih-.01 .or.
  1035. & grid2_centroid_lat(n) > pih+.01) then
  1036. WRITE(nulou,*) 'Grid 2 centroid lat error:
  1037. &n, centroid_lat, mask='
  1038. & ,n,grid2_centroid_lat(n), grid2_mask(n)
  1039. endif
  1040. CALL OASIS_FLUSH_SCRIP(nulou)
  1041. ENDIF
  1042. grid2_centroid_lat(n) = zero
  1043. grid2_centroid_lon(n) = zero
  1044. end do
  1045. do n=1,num_links_map1
  1046. grid1_add = grid1_add_map1(n)
  1047. grid2_add = grid2_add_map1(n)
  1048. IF (nlogprt .GE. 2) THEN
  1049. if (wts_map1(1,n) < -.01) THEN
  1050. write(nulou,*)'Map 1 weight < 0 '
  1051. WRITE(NULOU,*)
  1052. & 'grid1_add, grid2_add, wts_map1, grid1_mask, grid2_mask',
  1053. & grid1_add, grid2_add, wts_map1(1,n),
  1054. & grid1_mask(grid1_add), grid2_mask(grid2_add)
  1055. endif
  1056. if (norm_opt/=norm_opt_none .and. wts_map1(1,n)>1.01) then
  1057. write(nulou,*)'Map 1 weight > 1 '
  1058. WRITE(NULOU,*)
  1059. & 'grid1_add, grid2_add, wts_map1, grid1_mask, grid2_mask',
  1060. & grid1_add, grid2_add, wts_map1(1,n),
  1061. & grid1_mask(grid1_add), grid2_mask(grid2_add)
  1062. endif
  1063. ENDIF
  1064. grid2_centroid_lat(grid2_add) =
  1065. & grid2_centroid_lat(grid2_add) + wts_map1(1,n)
  1066. ! if (num_maps > 1) then
  1067. ! if (wts_map2(1,n) < -.01) then
  1068. ! print *,'Map 2 weight < 0 '
  1069. ! PRINT *,
  1070. ! & 'grid1_add,grid2_add, wts_map2, grid1_mask, grid2_mask',
  1071. ! & grid1_add, grid2_add, wts_map2(1,n),
  1072. ! & grid1_mask(grid1_add), grid2_mask(grid2_add)
  1073. ! endif
  1074. ! if (norm_opt /= norm_opt_none .and. wts_map2(1,n) > 1.01) then
  1075. ! print *,'Map 2 weight < 0 '
  1076. ! PRINT *,
  1077. ! & 'grid1_add,grid2_add,wts_map2, grid1_mask,grid2_mask',
  1078. ! & grid1_add, grid2_add, wts_map2(1,n),
  1079. ! & grid1_mask(grid1_add), grid2_mask(grid2_add)
  1080. ! endif
  1081. ! grid1_centroid_lat(grid1_add) =
  1082. ! & grid1_centroid_lat(grid1_add) + wts_map2(1,n)
  1083. ! endif
  1084. end do
  1085. do n=1,grid2_size
  1086. select case(norm_opt)
  1087. case (norm_opt_dstarea)
  1088. norm_factor = grid2_frac(n)
  1089. case (norm_opt_frcarea)
  1090. norm_factor = one
  1091. case (norm_opt_none)
  1092. if (luse_grid2_area) then
  1093. norm_factor = grid2_area_in(n)
  1094. else
  1095. norm_factor = grid2_area(n)
  1096. endif
  1097. end select
  1098. if (abs(grid2_centroid_lat(n)-norm_factor) > .01) then
  1099. print *,
  1100. &'Error sum wts map1:grid2_add,grid2_centroid_lat,norm_factor='
  1101. &,n,grid2_centroid_lat(n),
  1102. &norm_factor,grid2_mask(n)
  1103. endif
  1104. end do
  1105. ! if (num_maps > 1) then
  1106. ! do n=1,grid1_size
  1107. ! select case(norm_opt)
  1108. ! case (norm_opt_dstarea)
  1109. ! norm_factor = grid1_frac(n)
  1110. ! case (norm_opt_frcarea)
  1111. ! norm_factor = one
  1112. ! case (norm_opt_none)
  1113. ! if (luse_grid1_area) then
  1114. ! norm_factor = grid1_area_in(n)
  1115. ! else
  1116. ! norm_factor = grid1_area(n)
  1117. ! endif
  1118. ! end select
  1119. ! if (abs(grid1_centroid_lat(n)-norm_factor) > .01) then
  1120. ! print *,
  1121. ! &'Error sum wts map2:grid1_add,grid1_centroid_lat,norm_factor='
  1122. ! &,n,grid1_centroid_lat(n),
  1123. ! &norm_factor,grid1_mask(n)
  1124. ! endif
  1125. ! end do
  1126. ! endif
  1127. !-----------------------------------------------------------------------
  1128. !
  1129. ! deallocate allocated arrays
  1130. !
  1131. !-----------------------------------------------------------------------
  1132. deallocate (grid1_centroid_lat, grid1_centroid_lon,
  1133. & grid2_centroid_lat, grid2_centroid_lon)
  1134. IF (nlogprt .GE. 2) THEN
  1135. WRITE (UNIT = nulou,FMT = *)' '
  1136. WRITE (UNIT = nulou,FMT = *)'Leaving routine remap_conserv'
  1137. CALL OASIS_FLUSH_SCRIP(nulou)
  1138. ENDIF
  1139. !-----------------------------------------------------------------------
  1140. end subroutine remap_conserv
  1141. !***********************************************************************
  1142. subroutine intersection(location,intrsct_lat,intrsct_lon,lcoinc,
  1143. & beglat, beglon, endlat, endlon, begseg,
  1144. & lbegin, lrevers)
  1145. !-----------------------------------------------------------------------
  1146. !
  1147. ! this routine finds the next intersection of a destination grid
  1148. ! line with the line segment given by beglon, endlon, etc.
  1149. ! a coincidence flag is returned if the segment is entirely
  1150. ! coincident with an ocean grid line. the cells in which to search
  1151. ! for an intersection must have already been restricted in the
  1152. ! calling routine.
  1153. !
  1154. !-----------------------------------------------------------------------
  1155. !-----------------------------------------------------------------------
  1156. !
  1157. ! intent(in):
  1158. !
  1159. !-----------------------------------------------------------------------
  1160. logical (kind=log_kind), intent(in) ::
  1161. & lbegin, ! flag for first integration along this segment
  1162. & lrevers ! flag whether segment integrated in reverse
  1163. real (kind=dbl_kind), intent(in) ::
  1164. & beglat, beglon, ! beginning lat/lon endpoints for segment
  1165. & endlat, endlon ! ending lat/lon endpoints for segment
  1166. real (kind=dbl_kind), dimension(2), intent(inout) ::
  1167. & begseg ! begin lat/lon of full segment
  1168. !-----------------------------------------------------------------------
  1169. !
  1170. ! intent(out):
  1171. !
  1172. !-----------------------------------------------------------------------
  1173. integer (kind=int_kind), intent(out) ::
  1174. & location ! address in destination array containing this
  1175. ! segment
  1176. logical (kind=log_kind), intent(out) ::
  1177. & lcoinc ! flag segments which are entirely coincident
  1178. ! with a grid line
  1179. real (kind=dbl_kind), intent(out) ::
  1180. & intrsct_lat, intrsct_lon ! lat/lon coords of next intersect.
  1181. !-----------------------------------------------------------------------
  1182. !
  1183. ! local variables
  1184. !
  1185. !-----------------------------------------------------------------------
  1186. integer (kind=int_kind) :: n, next_n, cell, srch_corners
  1187. ! for test of non-convexe cell
  1188. integer (kind=int_kind) :: next2_n, neg, pos
  1189. integer (kind=int_kind), save ::
  1190. & last_loc ! save location when crossing threshold
  1191. logical (kind=log_kind) ::
  1192. & loutside ! flags points outside grid
  1193. logical (kind=log_kind), save ::
  1194. & lthresh = .false. ! flags segments crossing threshold bndy
  1195. real (kind=dbl_kind) ::
  1196. & lon1, lon2, ! local longitude variables for segment
  1197. & lat1, lat2, ! local latitude variables for segment
  1198. & grdlon1, grdlon2, ! local longitude variables for grid cell
  1199. & grdlat1, grdlat2, ! local latitude variables for grid cell
  1200. & vec1_lat, vec1_lon, ! vectors and cross products used
  1201. & vec2_lat, vec2_lon, ! during grid search
  1202. & cross_product,
  1203. & eps, offset, ! small offset away from intersect
  1204. & s1, s2, determ, ! variables used for linear solve to
  1205. & mat1, mat2, mat3, mat4, rhs1, rhs2, ! find intersection
  1206. & rl_halfpi, rl_v2lonmpi2, rl_v2lonppi2
  1207. real (kind=dbl_kind), save ::
  1208. & intrsct_lat_off, intrsct_lon_off ! lat/lon coords offset
  1209. ! for next search
  1210. !-----------------------------------------------------------------------
  1211. !
  1212. ! initialize defaults, flags, etc.
  1213. !
  1214. !-----------------------------------------------------------------------
  1215. location = 0
  1216. lcoinc = .false.
  1217. intrsct_lat = endlat
  1218. intrsct_lon = endlon
  1219. if (num_srch_cells == 0) return
  1220. if (beglat > north_thresh .or. beglat < south_thresh) then
  1221. if (lthresh) location = last_loc
  1222. call pole_intersection(location,
  1223. & intrsct_lat,intrsct_lon,lcoinc,lthresh,
  1224. & beglat, beglon, endlat, endlon, begseg, lrevers)
  1225. if (lthresh) then
  1226. last_loc = location
  1227. intrsct_lat_off = intrsct_lat
  1228. intrsct_lon_off = intrsct_lon
  1229. endif
  1230. return
  1231. endif
  1232. loutside = .false.
  1233. if (lbegin) then
  1234. lat1 = beglat
  1235. lon1 = beglon
  1236. else
  1237. lat1 = intrsct_lat_off
  1238. lon1 = intrsct_lon_off
  1239. endif
  1240. lat2 = endlat
  1241. lon2 = endlon
  1242. if ((lon2-lon1) > three*pih) then
  1243. lon2 = lon2 - pi2
  1244. else if ((lon2-lon1) < -three*pih) then
  1245. lon2 = lon2 + pi2
  1246. endif
  1247. s1 = zero
  1248. !-----------------------------------------------------------------------
  1249. !
  1250. ! search for location of this segment in ocean grid using cross
  1251. ! product method to determine whether a point is enclosed by a cell
  1252. !
  1253. !-----------------------------------------------------------------------
  1254. call timer_start(12)
  1255. srch_corners = size(srch_corner_lat,DIM=1)
  1256. srch_loop: do
  1257. !***
  1258. !*** if last segment crossed threshold, use that location
  1259. !***
  1260. if (lthresh) then
  1261. do cell=1,num_srch_cells
  1262. if (srch_add(cell) == last_loc) then
  1263. location = last_loc
  1264. eps = tiny
  1265. exit srch_loop
  1266. endif
  1267. end do
  1268. endif
  1269. !***
  1270. !*** otherwise normal search algorithm
  1271. !***
  1272. cell_loop: do cell=1,num_srch_cells
  1273. corner_loop: do n=1,srch_corners
  1274. next_n = MOD(n,srch_corners) + 1
  1275. !***
  1276. !*** here we take the cross product of the vector making
  1277. !*** up each cell side with the vector formed by the vertex
  1278. !*** and search point. if all the cross products are
  1279. !*** positive, the point is contained in the cell.
  1280. !***
  1281. vec1_lat = srch_corner_lat(next_n,cell) -
  1282. & srch_corner_lat(n ,cell)
  1283. vec1_lon = srch_corner_lon(next_n,cell) -
  1284. & srch_corner_lon(n ,cell)
  1285. vec2_lat = lat1 - srch_corner_lat(n,cell)
  1286. vec2_lon = lon1 - srch_corner_lon(n,cell)
  1287. !***
  1288. !*** if endpoint coincident with vertex, offset
  1289. !*** the endpoint
  1290. !***
  1291. if (vec2_lat == 0 .and. vec2_lon == 0) then
  1292. lat1 = lat1 + 1.d-10*(lat2-lat1)
  1293. lon1 = lon1 + 1.d-10*(lon2-lon1)
  1294. vec2_lat = lat1 - srch_corner_lat(n,cell)
  1295. vec2_lon = lon1 - srch_corner_lon(n,cell)
  1296. ENDIF
  1297. !***
  1298. !*** check for 0,2pi crossings
  1299. !***
  1300. if (vec1_lon > pi) then
  1301. vec1_lon = vec1_lon - pi2
  1302. else if (vec1_lon < -pi) then
  1303. vec1_lon = vec1_lon + pi2
  1304. endif
  1305. if (vec2_lon > pi) then
  1306. vec2_lon = vec2_lon - pi2
  1307. else if (vec2_lon < -pi) then
  1308. vec2_lon = vec2_lon + pi2
  1309. endif
  1310. cross_product = vec1_lon*vec2_lat - vec2_lon*vec1_lat
  1311. !***
  1312. !*** if the cross product for a side is zero, the point
  1313. !*** lies exactly on the side or the side is degenerate
  1314. !*** (zero length). if degenerate, set the cross
  1315. !*** product to a positive number. otherwise perform
  1316. !*** another cross product between the side and the
  1317. !*** segment itself.
  1318. !*** if this cross product is also zero, the line is
  1319. !*** coincident with the cell boundary - perform the
  1320. !*** dot product and only choose the cell if the dot
  1321. !*** product is positive (parallel vs anti-parallel).
  1322. !***
  1323. if (cross_product == zero) then
  1324. if (vec1_lat /= zero .or. vec1_lon /= zero) then
  1325. vec2_lat = lat2 - lat1
  1326. vec2_lon = lon2 - lon1
  1327. if (vec2_lon > pi) then
  1328. vec2_lon = vec2_lon - pi2
  1329. else if (vec2_lon < -pi) then
  1330. vec2_lon = vec2_lon + pi2
  1331. endif
  1332. cross_product = vec1_lon*vec2_lat - vec2_lon*vec1_lat
  1333. else
  1334. cross_product = one
  1335. endif
  1336. if (cross_product == zero) then
  1337. lcoinc = .true.
  1338. cross_product = vec1_lon*vec2_lon + vec1_lat*vec2_lat
  1339. if (lrevers) cross_product = -cross_product
  1340. endif
  1341. endif
  1342. !***
  1343. !*** if cross product is less than zero, this cell
  1344. !*** doesn't work
  1345. !***
  1346. if (cross_product < zero) exit corner_loop
  1347. end do corner_loop
  1348. !***
  1349. !*** if cross products all positive, we found the location
  1350. !***
  1351. if (n > srch_corners) then
  1352. location = srch_add(cell)
  1353. !***
  1354. !*** if the beginning of this segment was outside the
  1355. !*** grid, invert the segment so the intersection found
  1356. !*** will be the first intersection with the grid
  1357. !***
  1358. if (loutside) then
  1359. !*** do a test to see if the cell really is outside
  1360. !*** or if it is a non-convexe cell
  1361. neg=0
  1362. pos=0
  1363. do n=1,srch_corners
  1364. next_n = MOD(n,srch_corners) + 1
  1365. next2_n = MOD(next_n,srch_corners) + 1
  1366. vec1_lat = srch_corner_lat(next_n,cell) -
  1367. & srch_corner_lat(n,cell)
  1368. vec1_lon = srch_corner_lon(next_n,cell) -
  1369. & srch_corner_lon(n,cell)
  1370. vec2_lat = srch_corner_lat(next2_n,cell) -
  1371. & srch_corner_lat(next_n,cell)
  1372. vec2_lon = srch_corner_lon(next2_n,cell) -
  1373. & srch_corner_lon(next_n,cell)
  1374. if (vec1_lon > three*pih) then
  1375. vec1_lon = vec1_lon - pi2
  1376. else if (vec1_lon < -three*pih) then
  1377. vec1_lon = vec1_lon + pi2
  1378. endif
  1379. if (vec2_lon > three*pih) then
  1380. vec2_lon = vec2_lon - pi2
  1381. else if (vec2_lon < -three*pih) then
  1382. vec2_lon = vec2_lon + pi2
  1383. endif
  1384. cross_product=
  1385. & vec1_lat*vec2_lon - vec2_lat*vec1_lon
  1386. if (cross_product < zero) then
  1387. neg=neg+1
  1388. else if (cross_product > zero) then
  1389. pos=pos+1
  1390. endif
  1391. enddo
  1392. !*** the cell is non-convexe if not all cross_products
  1393. !*** have the same signe
  1394. if (neg/=0 .and. pos/=0) then
  1395. loutside=.false.
  1396. IF (nlogprt .ge. 2) THEN
  1397. write(nulou,*) 'The mesh ',srch_add(cell),
  1398. $ ' is non-convex'
  1399. write(nulou,*) 'srch_corner_lat=',
  1400. $ srch_corner_lat(:,cell)
  1401. write(nulou,*) 'srch_corner_lon=',
  1402. $ srch_corner_lon(:,cell)
  1403. CALL OASIS_FLUSH_SCRIP(nulou)
  1404. ENDIF
  1405. endif
  1406. endif
  1407. if (loutside) then
  1408. lat2 = beglat
  1409. lon2 = beglon
  1410. location = 0
  1411. eps = -tiny
  1412. else
  1413. eps = tiny
  1414. endif
  1415. exit srch_loop
  1416. endif
  1417. !***
  1418. !*** otherwise move on to next cell
  1419. !***
  1420. end do cell_loop
  1421. !***
  1422. !*** if still no cell found, the point lies outside the grid.
  1423. !*** take some baby steps along the segment to see if any
  1424. !*** part of the segment lies inside the grid.
  1425. !***
  1426. loutside = .true.
  1427. s1 = s1 + 0.001_dbl_kind
  1428. lat1 = beglat + s1*(endlat - beglat)
  1429. lon1 = beglon + s1*(lon2 - beglon)
  1430. !***
  1431. !*** reached the end of the segment and still outside the grid
  1432. !*** return no intersection
  1433. !***
  1434. if (s1 >= one) return
  1435. end do srch_loop
  1436. call timer_stop(12)
  1437. !-----------------------------------------------------------------------
  1438. !
  1439. ! now that a cell is found, search for the next intersection.
  1440. ! loop over sides of the cell to find intersection with side
  1441. ! must check all sides for coincidences or intersections
  1442. !
  1443. !-----------------------------------------------------------------------
  1444. call timer_start(13)
  1445. intrsct_loop: do n=1,srch_corners
  1446. next_n = mod(n,srch_corners) + 1
  1447. grdlon1 = srch_corner_lon(n ,cell)
  1448. grdlon2 = srch_corner_lon(next_n,cell)
  1449. grdlat1 = srch_corner_lat(n ,cell)
  1450. grdlat2 = srch_corner_lat(next_n,cell)
  1451. !***
  1452. !*** set up linear system to solve for intersection
  1453. !***
  1454. mat1 = lat2 - lat1
  1455. mat2 = grdlat1 - grdlat2
  1456. mat3 = lon2 - lon1
  1457. mat4 = grdlon1 - grdlon2
  1458. rhs1 = grdlat1 - lat1
  1459. rhs2 = grdlon1 - lon1
  1460. if (mat3 > pi) then
  1461. mat3 = mat3 - pi2
  1462. else if (mat3 < -pi) then
  1463. mat3 = mat3 + pi2
  1464. endif
  1465. if (mat4 > pi) then
  1466. mat4 = mat4 - pi2
  1467. else if (mat4 < -pi) then
  1468. mat4 = mat4 + pi2
  1469. endif
  1470. if (rhs2 > pi) then
  1471. rhs2 = rhs2 - pi2
  1472. else if (rhs2 < -pi) then
  1473. rhs2 = rhs2 + pi2
  1474. endif
  1475. determ = mat1*mat4 - mat2*mat3
  1476. !***
  1477. !*** if the determinant is zero, the segments are either
  1478. !*** parallel or coincident. coincidences were detected
  1479. !*** above so do nothing.
  1480. !*** if the determinant is non-zero, solve for the linear
  1481. !*** parameters s for the intersection point on each line
  1482. !*** segment.
  1483. !*** if 0<s1,s2<1 then the segment intersects with this side.
  1484. !*** return the point of intersection (adding a small
  1485. !*** number so the intersection is off the grid line).
  1486. !***
  1487. if (abs(determ) > 1.e-30) then
  1488. s1 = (rhs1*mat4 - mat2*rhs2)/determ
  1489. s2 = (mat1*rhs2 - rhs1*mat3)/determ
  1490. if (s2 >= zero .and. s2 <= one .and.
  1491. & s1 > zero. and. s1 <= one) then
  1492. !***
  1493. !*** recompute intersection based on full segment
  1494. !*** so intersections are consistent for both sweeps
  1495. !***
  1496. if (.not. loutside) then
  1497. mat1 = lat2 - begseg(1)
  1498. mat3 = lon2 - begseg(2)
  1499. rhs1 = grdlat1 - begseg(1)
  1500. rhs2 = grdlon1 - begseg(2)
  1501. else
  1502. mat1 = begseg(1) - endlat
  1503. mat3 = begseg(2) - endlon
  1504. rhs1 = grdlat1 - endlat
  1505. rhs2 = grdlon1 - endlon
  1506. endif
  1507. if (mat3 > pi) then
  1508. mat3 = mat3 - pi2
  1509. else if (mat3 < -pi) then
  1510. mat3 = mat3 + pi2
  1511. endif
  1512. if (rhs2 > pi) then
  1513. rhs2 = rhs2 - pi2
  1514. else if (rhs2 < -pi) then
  1515. rhs2 = rhs2 + pi2
  1516. endif
  1517. determ = mat1*mat4 - mat2*mat3
  1518. !***
  1519. !*** sometimes due to roundoff, the previous
  1520. !*** determinant is non-zero, but the lines
  1521. !*** are actually coincident. if this is the
  1522. !*** case, skip the rest.
  1523. !***
  1524. if (determ /= zero) then
  1525. s1 = (rhs1*mat4 - mat2*rhs2)/determ
  1526. s2 = (mat1*rhs2 - rhs1*mat3)/determ
  1527. offset = s1 + eps/determ
  1528. if (offset > one) offset = one
  1529. if (.not. loutside) then
  1530. intrsct_lat = begseg(1) + mat1*s1
  1531. intrsct_lon = begseg(2) + mat3*s1
  1532. intrsct_lat_off = begseg(1) + mat1*offset
  1533. intrsct_lon_off = begseg(2) + mat3*offset
  1534. else
  1535. intrsct_lat = endlat + mat1*s1
  1536. intrsct_lon = endlon + mat3*s1
  1537. intrsct_lat_off = endlat + mat1*offset
  1538. intrsct_lon_off = endlon + mat3*offset
  1539. endif
  1540. exit intrsct_loop
  1541. endif
  1542. endif
  1543. endif
  1544. !***
  1545. !*** no intersection this side, move on to next side
  1546. !***
  1547. end do intrsct_loop
  1548. call timer_stop(13)
  1549. !-----------------------------------------------------------------------
  1550. !
  1551. ! if the segment crosses a pole threshold, reset the intersection
  1552. ! to be the threshold latitude. only check if this was not a
  1553. ! threshold segment since sometimes coordinate transform can end
  1554. ! up on other side of threshold again.
  1555. !
  1556. !-----------------------------------------------------------------------
  1557. if (lthresh) then
  1558. if (intrsct_lat < north_thresh .or. intrsct_lat > south_thresh)
  1559. & lthresh = .false.
  1560. else if (lat1 > zero .and. intrsct_lat > north_thresh) then
  1561. intrsct_lat = north_thresh + tiny
  1562. intrsct_lat_off = north_thresh + eps*mat1
  1563. s1 = (intrsct_lat - begseg(1))/mat1
  1564. intrsct_lon = begseg(2) + s1*mat3
  1565. intrsct_lon_off = begseg(2) + (s1+eps)*mat3
  1566. last_loc = location
  1567. lthresh = .true.
  1568. else if (lat1 < zero .and. intrsct_lat < south_thresh) then
  1569. intrsct_lat = south_thresh - tiny
  1570. intrsct_lat_off = south_thresh + eps*mat1
  1571. s1 = (intrsct_lat - begseg(1))/mat1
  1572. intrsct_lon = begseg(2) + s1*mat3
  1573. intrsct_lon_off = begseg(2) + (s1+eps)*mat3
  1574. last_loc = location
  1575. lthresh = .true.
  1576. endif
  1577. !-----------------------------------------------------------------------
  1578. end subroutine intersection
  1579. !***********************************************************************
  1580. subroutine pole_intersection(location,
  1581. & intrsct_lat,intrsct_lon,lcoinc,lthresh,
  1582. & beglat, beglon, endlat, endlon, begseg, lrevers)
  1583. !-----------------------------------------------------------------------
  1584. !
  1585. ! this routine is identical to the intersection routine except
  1586. ! that a coordinate transformation (using a Lambert azimuthal
  1587. ! equivalent projection) is performed to treat polar cells more
  1588. ! accurately.
  1589. !
  1590. !-----------------------------------------------------------------------
  1591. !-----------------------------------------------------------------------
  1592. !
  1593. ! intent(in):
  1594. !
  1595. !-----------------------------------------------------------------------
  1596. real (kind=dbl_kind), intent(in) ::
  1597. & beglat, beglon, ! beginning lat/lon endpoints for segment
  1598. & endlat, endlon ! ending lat/lon endpoints for segment
  1599. real (kind=dbl_kind), dimension(2), intent(inout) ::
  1600. & begseg ! begin lat/lon of full segment
  1601. logical (kind=log_kind), intent(in) ::
  1602. & lrevers ! flag true if segment integrated in reverse
  1603. !-----------------------------------------------------------------------
  1604. !
  1605. ! intent(out):
  1606. !
  1607. !-----------------------------------------------------------------------
  1608. integer (kind=int_kind), intent(inout) ::
  1609. & location ! address in destination array containing this
  1610. ! segment -- also may contain last location on
  1611. ! entry
  1612. logical (kind=log_kind), intent(out) ::
  1613. & lcoinc ! flag segment coincident with grid line
  1614. logical (kind=log_kind), intent(inout) ::
  1615. & lthresh ! flag segment crossing threshold boundary
  1616. real (kind=dbl_kind), intent(out) ::
  1617. & intrsct_lat, intrsct_lon ! lat/lon coords of next intersect.
  1618. !-----------------------------------------------------------------------
  1619. !
  1620. ! local variables
  1621. !
  1622. !-----------------------------------------------------------------------
  1623. integer (kind=int_kind) :: n, next_n, cell, srch_corners
  1624. logical (kind=log_kind) :: loutside ! flags points outside grid
  1625. real (kind=dbl_kind) :: pi4, rns, ! north/south conversion
  1626. & x1, x2, ! local x variables for segment
  1627. & y1, y2, ! local y variables for segment
  1628. & begx, begy, ! beginning x,y variables for segment
  1629. & endx, endy, ! beginning x,y variables for segment
  1630. & begsegx, begsegy, ! beginning x,y variables for segment
  1631. & grdx1, grdx2, ! local x variables for grid cell
  1632. & grdy1, grdy2, ! local y variables for grid cell
  1633. & vec1_y, vec1_x, ! vectors and cross products used
  1634. & vec2_y, vec2_x, ! during grid search
  1635. & cross_product, eps, ! eps=small offset away from intersect
  1636. & s1, s2, determ, ! variables used for linear solve to
  1637. & mat1, mat2, mat3, mat4, rhs1, rhs2 ! find intersection
  1638. real (kind=dbl_kind), dimension(:,:), allocatable ::
  1639. & srch_corner_x, ! x of each corner of srch cells
  1640. & srch_corner_y ! y of each corner of srch cells
  1641. !***
  1642. !*** save last intersection to avoid roundoff during coord
  1643. !*** transformation
  1644. !***
  1645. logical (kind=log_kind), save :: luse_last = .false.
  1646. real (kind=dbl_kind), save ::
  1647. & intrsct_x, intrsct_y ! x,y for intersection
  1648. !***
  1649. !*** variables necessary if segment manages to hit pole
  1650. !***
  1651. integer (kind=int_kind), save ::
  1652. & avoid_pole_count = 0 ! count attempts to avoid pole
  1653. real (kind=dbl_kind), save ::
  1654. & avoid_pole_offset = tiny ! endpoint offset to avoid pole
  1655. !-----------------------------------------------------------------------
  1656. !
  1657. ! initialize defaults, flags, etc.
  1658. !
  1659. !-----------------------------------------------------------------------
  1660. if (.not. lthresh) location = 0
  1661. lcoinc = .false.
  1662. intrsct_lat = endlat
  1663. intrsct_lon = endlon
  1664. loutside = .false.
  1665. s1 = zero
  1666. !-----------------------------------------------------------------------
  1667. !
  1668. ! convert coordinates
  1669. !
  1670. !-----------------------------------------------------------------------
  1671. allocate(srch_corner_x(size(srch_corner_lat,DIM=1),
  1672. & size(srch_corner_lat,DIM=2)),
  1673. & srch_corner_y(size(srch_corner_lat,DIM=1),
  1674. & size(srch_corner_lat,DIM=2)))
  1675. if (beglat > zero) then
  1676. pi4 = quart*pi
  1677. rns = one
  1678. else
  1679. pi4 = -quart*pi
  1680. rns = -one
  1681. endif
  1682. if (luse_last) then
  1683. x1 = intrsct_x
  1684. y1 = intrsct_y
  1685. else
  1686. x1 = rns*two*sin(pi4 - half*beglat)*cos(beglon)
  1687. y1 = two*sin(pi4 - half*beglat)*sin(beglon)
  1688. luse_last = .true.
  1689. endif
  1690. x2 = rns*two*sin(pi4 - half*endlat)*cos(endlon)
  1691. y2 = two*sin(pi4 - half*endlat)*sin(endlon)
  1692. srch_corner_x = rns*two*sin(pi4 - half*srch_corner_lat)*
  1693. & cos(srch_corner_lon)
  1694. srch_corner_y = two*sin(pi4 - half*srch_corner_lat)*
  1695. & sin(srch_corner_lon)
  1696. begx = x1
  1697. begy = y1
  1698. endx = x2
  1699. endy = y2
  1700. begsegx = rns*two*sin(pi4 - half*begseg(1))*cos(begseg(2))
  1701. begsegy = two*sin(pi4 - half*begseg(1))*sin(begseg(2))
  1702. intrsct_x = endx
  1703. intrsct_y = endy
  1704. !-----------------------------------------------------------------------
  1705. !
  1706. ! search for location of this segment in ocean grid using cross
  1707. ! product method to determine whether a point is enclosed by a cell
  1708. !
  1709. !-----------------------------------------------------------------------
  1710. call timer_start(12)
  1711. srch_corners = size(srch_corner_lat,DIM=1)
  1712. srch_loop: do
  1713. !***
  1714. !*** if last segment crossed threshold, use that location
  1715. !***
  1716. if (lthresh) then
  1717. do cell=1,num_srch_cells
  1718. if (srch_add(cell) == location) then
  1719. eps = tiny
  1720. exit srch_loop
  1721. endif
  1722. end do
  1723. endif
  1724. !***
  1725. !*** otherwise normal search algorithm
  1726. !***
  1727. cell_loop: do cell=1,num_srch_cells
  1728. corner_loop: do n=1,srch_corners
  1729. next_n = MOD(n,srch_corners) + 1
  1730. !***
  1731. !*** here we take the cross product of the vector making
  1732. !*** up each cell side with the vector formed by the vertex
  1733. !*** and search point. if all the cross products are
  1734. !*** positive, the point is contained in the cell.
  1735. !***
  1736. vec1_x = srch_corner_x(next_n,cell) -
  1737. & srch_corner_x(n ,cell)
  1738. vec1_y = srch_corner_y(next_n,cell) -
  1739. & srch_corner_y(n ,cell)
  1740. vec2_x = x1 - srch_corner_x(n,cell)
  1741. vec2_y = y1 - srch_corner_y(n,cell)
  1742. !***
  1743. !*** if endpoint coincident with vertex, offset
  1744. !*** the endpoint
  1745. !***
  1746. if (vec2_x == 0 .and. vec2_y == 0) then
  1747. x1 = x1 + 1.d-10*(x2-x1)
  1748. y1 = y1 + 1.d-10*(y2-y1)
  1749. vec2_x = x1 - srch_corner_x(n,cell)
  1750. vec2_y = y1 - srch_corner_y(n,cell)
  1751. endif
  1752. cross_product = vec1_x*vec2_y - vec2_x*vec1_y
  1753. !***
  1754. !*** if the cross product for a side is zero, the point
  1755. !*** lies exactly on the side or the length of a side
  1756. !*** is zero. if the length is zero set det > 0.
  1757. !*** otherwise, perform another cross
  1758. !*** product between the side and the segment itself.
  1759. !*** if this cross product is also zero, the line is
  1760. !*** coincident with the cell boundary - perform the
  1761. !*** dot product and only choose the cell if the dot
  1762. !*** product is positive (parallel vs anti-parallel).
  1763. !***
  1764. if (cross_product == zero) then
  1765. if (vec1_x /= zero .or. vec1_y /= 0) then
  1766. vec2_x = x2 - x1
  1767. vec2_y = y2 - y1
  1768. cross_product = vec1_x*vec2_y - vec2_x*vec1_y
  1769. else
  1770. cross_product = one
  1771. endif
  1772. if (cross_product == zero) then
  1773. lcoinc = .true.
  1774. cross_product = vec1_x*vec2_x + vec1_y*vec2_y
  1775. if (lrevers) cross_product = -cross_product
  1776. endif
  1777. endif
  1778. !***
  1779. !*** if cross product is less than zero, this cell
  1780. !*** doesn't work
  1781. !***
  1782. if (cross_product < zero) exit corner_loop
  1783. end do corner_loop
  1784. !***
  1785. !*** if cross products all positive, we found the location
  1786. !***
  1787. if (n > srch_corners) then
  1788. location = srch_add(cell)
  1789. !***
  1790. !*** if the beginning of this segment was outside the
  1791. !*** grid, invert the segment so the intersection found
  1792. !*** will be the first intersection with the grid
  1793. !***
  1794. if (loutside) then
  1795. x2 = begx
  1796. y2 = begy
  1797. location = 0
  1798. eps = -tiny
  1799. else
  1800. eps = tiny
  1801. endif
  1802. exit srch_loop
  1803. endif
  1804. !***
  1805. !*** otherwise move on to next cell
  1806. !***
  1807. end do cell_loop
  1808. !***
  1809. !*** if no cell found, the point lies outside the grid.
  1810. !*** take some baby steps along the segment to see if any
  1811. !*** part of the segment lies inside the grid.
  1812. !***
  1813. loutside = .true.
  1814. s1 = s1 + 0.001_dbl_kind
  1815. x1 = begx + s1*(x2 - begx)
  1816. y1 = begy + s1*(y2 - begy)
  1817. !***
  1818. !*** reached the end of the segment and still outside the grid
  1819. !*** return no intersection
  1820. !***
  1821. if (s1 >= one) then
  1822. deallocate(srch_corner_x, srch_corner_y)
  1823. luse_last = .false.
  1824. return
  1825. endif
  1826. end do srch_loop
  1827. call timer_stop(12)
  1828. !-----------------------------------------------------------------------
  1829. !
  1830. ! now that a cell is found, search for the next intersection.
  1831. ! loop over sides of the cell to find intersection with side
  1832. ! must check all sides for coincidences or intersections
  1833. !
  1834. !-----------------------------------------------------------------------
  1835. call timer_start(13)
  1836. intrsct_loop: do n=1,srch_corners
  1837. next_n = mod(n,srch_corners) + 1
  1838. grdy1 = srch_corner_y(n ,cell)
  1839. grdy2 = srch_corner_y(next_n,cell)
  1840. grdx1 = srch_corner_x(n ,cell)
  1841. grdx2 = srch_corner_x(next_n,cell)
  1842. !***
  1843. !*** set up linear system to solve for intersection
  1844. !***
  1845. mat1 = x2 - x1
  1846. mat2 = grdx1 - grdx2
  1847. mat3 = y2 - y1
  1848. mat4 = grdy1 - grdy2
  1849. rhs1 = grdx1 - x1
  1850. rhs2 = grdy1 - y1
  1851. determ = mat1*mat4 - mat2*mat3
  1852. !***
  1853. !*** if the determinant is zero, the segments are either
  1854. !*** parallel or coincident or one segment has zero length.
  1855. !*** coincidences were detected above so do nothing.
  1856. !*** if the determinant is non-zero, solve for the linear
  1857. !*** parameters s for the intersection point on each line
  1858. !*** segment.
  1859. !*** if 0<s1,s2<1 then the segment intersects with this side.
  1860. !*** return the point of intersection (adding a small
  1861. !*** number so the intersection is off the grid line).
  1862. !***
  1863. if (abs(determ) > 1.e-30) then
  1864. s1 = (rhs1*mat4 - mat2*rhs2)/determ
  1865. s2 = (mat1*rhs2 - rhs1*mat3)/determ
  1866. if (s2 >= zero .and. s2 <= one .and.
  1867. & s1 > zero. and. s1 <= one) then
  1868. !***
  1869. !*** recompute intersection using entire segment
  1870. !*** for consistency between sweeps
  1871. !***
  1872. if (.not. loutside) then
  1873. mat1 = x2 - begsegx
  1874. mat3 = y2 - begsegy
  1875. rhs1 = grdx1 - begsegx
  1876. rhs2 = grdy1 - begsegy
  1877. else
  1878. mat1 = x2 - endx
  1879. mat3 = y2 - endy
  1880. rhs1 = grdx1 - endx
  1881. rhs2 = grdy1 - endy
  1882. endif
  1883. determ = mat1*mat4 - mat2*mat3
  1884. !***
  1885. !*** sometimes due to roundoff, the previous
  1886. !*** determinant is non-zero, but the lines
  1887. !*** are actually coincident. if this is the
  1888. !*** case, skip the rest.
  1889. !***
  1890. if (determ /= zero) then
  1891. s1 = (rhs1*mat4 - mat2*rhs2)/determ
  1892. s2 = (mat1*rhs2 - rhs1*mat3)/determ
  1893. if (.not. loutside) then
  1894. intrsct_x = begsegx + s1*mat1
  1895. intrsct_y = begsegy + s1*mat3
  1896. else
  1897. intrsct_x = endx + s1*mat1
  1898. intrsct_y = endy + s1*mat3
  1899. endif
  1900. !***
  1901. !*** convert back to lat/lon coordinates
  1902. !***
  1903. intrsct_lon = rns*atan2(intrsct_y,intrsct_x)
  1904. if (intrsct_lon < zero)
  1905. & intrsct_lon = intrsct_lon + pi2
  1906. if (abs(intrsct_x) > 1.d-10) then
  1907. intrsct_lat = (pi4 -
  1908. & asin(rns*half*intrsct_x/cos(intrsct_lon)))*two
  1909. else if (abs(intrsct_y) > 1.d-10) then
  1910. intrsct_lat = (pi4 -
  1911. & asin(half*intrsct_y/sin(intrsct_lon)))*two
  1912. else
  1913. intrsct_lat = two*pi4
  1914. endif
  1915. !***
  1916. !*** add offset in transformed space for next pass.
  1917. !***
  1918. if (s1 - eps/determ < one) then
  1919. intrsct_x = intrsct_x - mat1*(eps/determ)
  1920. intrsct_y = intrsct_y - mat3*(eps/determ)
  1921. else
  1922. if (.not. loutside) then
  1923. intrsct_x = endx
  1924. intrsct_y = endy
  1925. intrsct_lat = endlat
  1926. intrsct_lon = endlon
  1927. else
  1928. intrsct_x = begsegx
  1929. intrsct_y = begsegy
  1930. intrsct_lat = begseg(1)
  1931. intrsct_lon = begseg(2)
  1932. endif
  1933. endif
  1934. exit intrsct_loop
  1935. endif
  1936. endif
  1937. endif
  1938. !***
  1939. !*** no intersection this side, move on to next side
  1940. !***
  1941. end do intrsct_loop
  1942. call timer_stop(13)
  1943. deallocate(srch_corner_x, srch_corner_y)
  1944. !-----------------------------------------------------------------------
  1945. !
  1946. ! if segment manages to cross over pole, shift the beginning
  1947. ! endpoint in order to avoid hitting pole directly
  1948. ! (it is ok for endpoint to be pole point)
  1949. !
  1950. !-----------------------------------------------------------------------
  1951. if (abs(intrsct_x) < 1.e-10 .and. abs(intrsct_y) < 1.e-10 .and.
  1952. & (endx /= zero .and. endy /=0)) then
  1953. if (avoid_pole_count > 2) then
  1954. avoid_pole_count = 0
  1955. avoid_pole_offset = 10.*avoid_pole_offset
  1956. endif
  1957. cross_product = begsegx*(endy-begsegy) - begsegy*(endx-begsegx)
  1958. intrsct_lat = begseg(1)
  1959. if (cross_product*intrsct_lat > zero) then
  1960. intrsct_lon = beglon + avoid_pole_offset
  1961. begseg(2) = begseg(2) + avoid_pole_offset
  1962. else
  1963. intrsct_lon = beglon - avoid_pole_offset
  1964. begseg(2) = begseg(2) - avoid_pole_offset
  1965. endif
  1966. avoid_pole_count = avoid_pole_count + 1
  1967. luse_last = .false.
  1968. else
  1969. avoid_pole_count = 0
  1970. avoid_pole_offset = tiny
  1971. endif
  1972. !-----------------------------------------------------------------------
  1973. !
  1974. ! if the segment crosses a pole threshold, reset the intersection
  1975. ! to be the threshold latitude and do not reuse x,y intersect
  1976. ! on next entry. only check if did not cross threshold last
  1977. ! time - sometimes the coordinate transformation can place a
  1978. ! segment on the other side of the threshold again
  1979. !
  1980. !-----------------------------------------------------------------------
  1981. if (lthresh) then
  1982. if (intrsct_lat > north_thresh .or. intrsct_lat < south_thresh)
  1983. & lthresh = .false.
  1984. else if (beglat > zero .and. intrsct_lat < north_thresh) then
  1985. mat4 = endlat - begseg(1)
  1986. mat3 = endlon - begseg(2)
  1987. if (mat3 > pi) mat3 = mat3 - pi2
  1988. if (mat3 < -pi) mat3 = mat3 + pi2
  1989. intrsct_lat = north_thresh - tiny
  1990. s1 = (north_thresh - begseg(1))/mat4
  1991. intrsct_lon = begseg(2) + s1*mat3
  1992. luse_last = .false.
  1993. lthresh = .true.
  1994. else if (beglat < zero .and. intrsct_lat > south_thresh) then
  1995. mat4 = endlat - begseg(1)
  1996. mat3 = endlon - begseg(2)
  1997. if (mat3 > pi) mat3 = mat3 - pi2
  1998. if (mat3 < -pi) mat3 = mat3 + pi2
  1999. intrsct_lat = south_thresh + tiny
  2000. s1 = (south_thresh - begseg(1))/mat4
  2001. intrsct_lon = begseg(2) + s1*mat3
  2002. luse_last = .false.
  2003. lthresh = .true.
  2004. endif
  2005. !***
  2006. !*** if reached end of segment, do not use x,y intersect
  2007. !*** on next entry
  2008. !***
  2009. if (intrsct_lat == endlat .and. intrsct_lon == endlon) then
  2010. luse_last = .false.
  2011. endif
  2012. !-----------------------------------------------------------------------
  2013. end subroutine pole_intersection
  2014. !***********************************************************************
  2015. subroutine line_integral(weights, num_wts,
  2016. & in_phi1, in_phi2, theta1, theta2,
  2017. & grid1_lon, grid2_lon)
  2018. !-----------------------------------------------------------------------
  2019. !
  2020. ! this routine computes the line integral of the flux function
  2021. ! that results in the interpolation weights. the line is defined
  2022. ! by the input lat/lon of the endpoints.
  2023. !
  2024. !-----------------------------------------------------------------------
  2025. !-----------------------------------------------------------------------
  2026. !
  2027. ! intent(in):
  2028. !
  2029. !-----------------------------------------------------------------------
  2030. integer (kind=int_kind), intent(in) ::
  2031. & num_wts ! number of weights to compute
  2032. real (kind=dbl_kind), intent(in) ::
  2033. & in_phi1, in_phi2, ! longitude endpoints for the segment
  2034. & theta1, theta2, ! latitude endpoints for the segment
  2035. & grid1_lon, ! reference coordinates for each
  2036. & grid2_lon ! grid (to ensure correct 0,2pi interv.
  2037. !-----------------------------------------------------------------------
  2038. !
  2039. ! intent(out):
  2040. !
  2041. !-----------------------------------------------------------------------
  2042. real (kind=dbl_kind), dimension(2*num_wts), intent(out) ::
  2043. & weights ! line integral contribution to weights
  2044. !-----------------------------------------------------------------------
  2045. !
  2046. ! local variables
  2047. !
  2048. !-----------------------------------------------------------------------
  2049. real (kind=dbl_kind) :: dphi, sinth1, sinth2, costh1, costh2, fac,
  2050. & phi1, phi2, phidiff1, phidiff2
  2051. real (kind=dbl_kind) :: f1, f2, fint
  2052. !-----------------------------------------------------------------------
  2053. !
  2054. ! weights for the general case based on a trapezoidal approx to
  2055. ! the integrals.
  2056. !
  2057. !-----------------------------------------------------------------------
  2058. sinth1 = SIN(theta1)
  2059. sinth2 = SIN(theta2)
  2060. costh1 = COS(theta1)
  2061. costh2 = COS(theta2)
  2062. dphi = in_phi1 - in_phi2
  2063. if (dphi > pi) then
  2064. dphi = dphi - pi2
  2065. else if (dphi < -pi) then
  2066. dphi = dphi + pi2
  2067. endif
  2068. dphi = half*dphi
  2069. !-----------------------------------------------------------------------
  2070. !
  2071. ! the first weight is the area overlap integral. the second and
  2072. ! fourth are second-order latitude gradient weights.
  2073. !
  2074. !-----------------------------------------------------------------------
  2075. weights( 1) = dphi*(sinth1 + sinth2)
  2076. weights(num_wts+1) = dphi*(sinth1 + sinth2)
  2077. weights( 2) = dphi*(costh1 + costh2 + (theta1*sinth1 +
  2078. & theta2*sinth2))
  2079. weights(num_wts+2) = dphi*(costh1 + costh2 + (theta1*sinth1 +
  2080. & theta2*sinth2))
  2081. !-----------------------------------------------------------------------
  2082. !
  2083. ! the third and fifth weights are for the second-order phi gradient
  2084. ! component. must be careful of longitude range.
  2085. !
  2086. !-----------------------------------------------------------------------
  2087. f1 = half*(costh1*sinth1 + theta1)
  2088. f2 = half*(costh2*sinth2 + theta2)
  2089. phi1 = in_phi1 - grid1_lon
  2090. if (phi1 > pi) then
  2091. phi1 = phi1 - pi2
  2092. else if (phi1 < -pi) then
  2093. phi1 = phi1 + pi2
  2094. endif
  2095. phi2 = in_phi2 - grid1_lon
  2096. if (phi2 > pi) then
  2097. phi2 = phi2 - pi2
  2098. else if (phi2 < -pi) then
  2099. phi2 = phi2 + pi2
  2100. endif
  2101. if ((phi2-phi1) < pi .and. (phi2-phi1) > -pi) then
  2102. weights(3) = dphi*(phi1*f1 + phi2*f2)
  2103. else
  2104. if (phi1 > zero) then
  2105. fac = pi
  2106. else
  2107. fac = -pi
  2108. endif
  2109. fint = f1 + (f2-f1)*(fac-phi1)/abs(dphi)
  2110. weights(3) = half*phi1*(phi1-fac)*f1 -
  2111. & half*phi2*(phi2+fac)*f2 +
  2112. & half*fac*(phi1+phi2)*fint
  2113. endif
  2114. phi1 = in_phi1 - grid2_lon
  2115. if (phi1 > pi) then
  2116. phi1 = phi1 - pi2
  2117. else if (phi1 < -pi) then
  2118. phi1 = phi1 + pi2
  2119. endif
  2120. phi2 = in_phi2 - grid2_lon
  2121. if (phi2 > pi) then
  2122. phi2 = phi2 - pi2
  2123. else if (phi2 < -pi) then
  2124. phi2 = phi2 + pi2
  2125. endif
  2126. if ((phi2-phi1) < pi .and. (phi2-phi1) > -pi) then
  2127. weights(num_wts+3) = dphi*(phi1*f1 + phi2*f2)
  2128. else
  2129. if (phi1 > zero) then
  2130. fac = pi
  2131. else
  2132. fac = -pi
  2133. endif
  2134. fint = f1 + (f2-f1)*(fac-phi1)/abs(dphi)
  2135. weights(num_wts+3) = half*phi1*(phi1-fac)*f1 -
  2136. & half*phi2*(phi2+fac)*f2 +
  2137. & half*fac*(phi1+phi2)*fint
  2138. endif
  2139. !-----------------------------------------------------------------------
  2140. end subroutine line_integral
  2141. !***********************************************************************
  2142. subroutine store_link_cnsrv(add1, add2, weights)
  2143. !-----------------------------------------------------------------------
  2144. !
  2145. ! this routine stores the address and weight for this link in
  2146. ! the appropriate address and weight arrays and resizes those
  2147. ! arrays if necessary.
  2148. !
  2149. !-----------------------------------------------------------------------
  2150. !-----------------------------------------------------------------------
  2151. !
  2152. ! input variables
  2153. !
  2154. !-----------------------------------------------------------------------
  2155. integer (kind=int_kind), intent(in) ::
  2156. & add1, ! address on grid1
  2157. & add2 ! address on grid2
  2158. real (kind=dbl_kind), dimension(:), intent(in) ::
  2159. & weights ! array of remapping weights for this link
  2160. !-----------------------------------------------------------------------
  2161. !
  2162. ! local variables
  2163. !
  2164. !-----------------------------------------------------------------------
  2165. integer (kind=int_kind) :: nlink, min_link, max_link ! link index
  2166. integer (kind=int_kind), dimension(:,:), allocatable, save ::
  2167. & link_add1, ! min,max link add to restrict search
  2168. & link_add2 ! min,max link add to restrict search
  2169. !-----------------------------------------------------------------------
  2170. !
  2171. ! if all weights are zero, do not bother storing the link
  2172. !
  2173. !-----------------------------------------------------------------------
  2174. !SV if (all(weights == zero)) return
  2175. !-----------------------------------------------------------------------
  2176. !
  2177. ! restrict the range of links to search for existing links
  2178. !
  2179. !-----------------------------------------------------------------------
  2180. if (first_call) then
  2181. if (.not. first_conserv) then
  2182. deallocate(link_add1, link_add2)
  2183. endif
  2184. allocate(link_add1(2,grid1_size), link_add2(2,grid2_size))
  2185. link_add1 = 0
  2186. link_add2 = 0
  2187. first_call = .false.
  2188. min_link = 1
  2189. max_link = 0
  2190. else
  2191. min_link = min(link_add1(1,add1),link_add2(1,add2))
  2192. max_link = max(link_add1(2,add1),link_add2(2,add2))
  2193. if (min_link == 0) then
  2194. min_link = 1
  2195. max_link = 0
  2196. endif
  2197. endif
  2198. !-----------------------------------------------------------------------
  2199. !
  2200. ! if the link already exists, add the weight to the current weight
  2201. ! arrays
  2202. !
  2203. !-----------------------------------------------------------------------
  2204. do nlink=min_link,max_link
  2205. if (add1 == grid1_add_map1(nlink)) then
  2206. if (add2 == grid2_add_map1(nlink)) then
  2207. wts_map1(:,nlink) = wts_map1(:,nlink) + weights(1:num_wts)
  2208. ! if (num_maps == 2) then
  2209. ! wts_map2(:,nlink) = wts_map2(:,nlink) +
  2210. ! & weights(num_wts+1:2*num_wts)
  2211. ! endif
  2212. return
  2213. endif
  2214. endif
  2215. end do
  2216. !-----------------------------------------------------------------------
  2217. !
  2218. ! if the link does not yet exist, increment number of links and
  2219. ! check to see if remap arrays need to be increased to accomodate
  2220. ! the new link. then store the link.
  2221. !
  2222. !-----------------------------------------------------------------------
  2223. num_links_map1 = num_links_map1 + 1
  2224. if (num_links_map1 > max_links_map1)
  2225. & call resize_remap_vars(1,resize_increment)
  2226. grid1_add_map1(num_links_map1) = add1
  2227. grid2_add_map1(num_links_map1) = add2
  2228. wts_map1 (:,num_links_map1) = weights(1:num_wts)
  2229. ! if (num_maps > 1) then
  2230. ! num_links_map2 = num_links_map2 + 1
  2231. ! if (num_links_map2 > max_links_map2)
  2232. ! & call resize_remap_vars(2,resize_increment)
  2233. !
  2234. ! grid1_add_map2(num_links_map2) = add1
  2235. ! grid2_add_map2(num_links_map2) = add2
  2236. ! wts_map2 (:,num_links_map2) = weights(num_wts+1:2*num_wts)
  2237. ! endif
  2238. if (link_add1(1,add1) == 0) link_add1(1,add1) = num_links_map1
  2239. if (link_add2(1,add2) == 0) link_add2(1,add2) = num_links_map1
  2240. link_add1(2,add1) = num_links_map1
  2241. link_add2(2,add2) = num_links_map1
  2242. !-----------------------------------------------------------------------
  2243. end subroutine store_link_cnsrv
  2244. !***********************************************************************
  2245. end module remap_conservative
  2246. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!