grid_type_ll.F90 110 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397
  1. !
  2. ! may 2002, Arjo Segers
  3. !
  4. ! 23 Oct 2013 - Ph. Le Sager - added '==' operator to compare grids,
  5. ! and '=' assignment to copy data instead of pointers,
  6. ! and initialization of TllGridInfo pointers (requires F95)
  7. !
  8. ! NOTES: (0) "lli" is commonly used in the code, and stands for LonLatInfo
  9. ! (1) if you declare an object of TllGridInfo type in a module, it must
  10. ! have the 'save' attribute (unless it is a pointer or allocatable array)
  11. ! (2) you must call DONE on all lli that have been initialized
  12. ! (either through a call to INIT or as a copy of another lli) to
  13. ! avoid memory leak.
  14. ! (3) because of the associated status of the pointers of a
  15. ! TllGridInfo type, an argument object of that type should never
  16. ! have the intent(out) attribute, but the intent(inout) instead
  17. !
  18. ! STAND ALONE VERSION FOR LAT/LON GRIDS
  19. !
  20. ! Apply factor over region.
  21. !
  22. ! use grid, only : TRegion
  23. !
  24. ! type(TllRegion) :: llreg
  25. !
  26. ! ! define region by either calling INIT or COPY (i.e. "=")
  27. ! call Init( llreg, west_deg, east_deg, south_deg, north_deg, status )
  28. !
  29. ! ! apply factor to data set within box, or to the complement;
  30. ! ! if a grid cell only partly covers the region, the factor
  31. ! ! is applied according to the area ratio;
  32. ! ! x is at least 2d, if it is 3d the factor is applied for all levels:
  33. ! call Region_Apply_Factor( lli, x, llreg, fac, status [,complement=.false.] )
  34. !
  35. ! ! done
  36. ! call Done( llreg, status )
  37. !
  38. module grid_type_ll
  39. implicit none
  40. ! --- in/out --------------------------------
  41. private
  42. public :: TllGridInfo
  43. public :: Init, Done
  44. public :: Check
  45. public :: operator(==), assignment(=)
  46. public :: AreaOper
  47. public :: InterpolFractions
  48. public :: Interpol
  49. public :: BalanceMassFluxes
  50. public :: CheckMassBalance
  51. public :: GetRefinement
  52. public :: Match
  53. public :: FillGrid
  54. public :: EquivLat
  55. ! ~~ region
  56. public :: TllRegion
  57. public :: Region_Apply_Factor
  58. ! --- const ---------------------------------
  59. character(len=*), parameter :: mname = 'grid_type_ll'
  60. ! --- types ---------------------------------
  61. ! *** location, size, etc
  62. type TllGridInfo
  63. character(len=32) :: name
  64. ! * radius
  65. real :: R ! m
  66. ! * spacing
  67. real :: dlon_deg, dlat_deg ! degrees
  68. real :: dlon, dlat ! radians
  69. ! * size
  70. integer :: im, nlon
  71. integer :: jm, nlat
  72. ! * coordinates of gridpoint (cell center)
  73. ! indices 1, 2, ...
  74. real, pointer :: lon_deg(:) => null() ! degrees
  75. real, pointer :: lat_deg(:) => null() ! degrees
  76. real, pointer :: lon(:) => null() ! rad
  77. real, pointer :: lat(:) => null() ! rad
  78. ! * boundaries in a rank-2 array:
  79. real, pointer :: lon_bounds_deg(:,:) => null() ! degrees
  80. real, pointer :: lat_bounds_deg(:,:) => null() ! degrees
  81. real, pointer :: lon_bounds(:,:) => null() ! rad
  82. real, pointer :: lat_bounds(:,:) => null() ! rad
  83. ! * coordinates of boundaries for cell around grid point;
  84. ! indices 0, 1, 2, ...
  85. real, pointer :: blon_deg(:) => null() ! degrees
  86. real, pointer :: blat_deg(:) => null() ! degrees
  87. real, pointer :: blon(:) => null() ! rad
  88. real, pointer :: blat(:) => null() ! rad
  89. ! * area for cell in certain row
  90. real, pointer :: area(:) => null() ! rad^2
  91. real, pointer :: area_m2(:) => null() ! m^2
  92. ! * cell length in m
  93. real, pointer :: dx(:) => null() ! m
  94. real, pointer :: bdx(:) => null() ! m
  95. real :: dy, bdy ! m
  96. end type TllGridInfo
  97. ! ~~ region
  98. type TllRegion
  99. ! region boundaries in degrees:
  100. real :: west_deg, east_deg, south_deg, north_deg
  101. ! idem in radians:
  102. real :: west, east, south, north
  103. end type TllRegion
  104. ! --- interfaces ----------------------------
  105. interface Init
  106. module procedure llgridinfo_Init
  107. module procedure llreg_Init
  108. end interface
  109. interface Done
  110. module procedure llgridinfo_Done
  111. module procedure llreg_Done
  112. end interface
  113. interface Check
  114. module procedure llgrid_Check_i
  115. module procedure llgrid_Check_r
  116. end interface
  117. interface AreaOper
  118. module procedure llgrid_AreaOper_2d
  119. module procedure llgrid_AreaOper_3d
  120. end interface
  121. interface InterpolFractions
  122. module procedure llgrid_InterpolFractions
  123. end interface
  124. interface Interpol
  125. module procedure llgrid_Eval_2d
  126. module procedure llgrid_Eval_3d
  127. end interface
  128. interface Match
  129. module procedure llgrid_Match
  130. end interface
  131. interface operator(==)
  132. module procedure llgrid_equal_llgrid
  133. end interface
  134. interface assignment(=)
  135. module procedure copy_llgrid
  136. end interface
  137. interface BalanceMassFluxes
  138. module procedure BalanceMassFluxes_sm
  139. module procedure BalanceMassFluxes_m
  140. end interface
  141. interface EquivLat
  142. module procedure llgrid_EquivLat
  143. module procedure llgrid_EquivLat_sort
  144. end interface
  145. ! ~~ region
  146. interface Region_Apply_Factor
  147. module procedure llreg_Region_Apply_Factor_2d
  148. module procedure llreg_Region_Apply_Factor_3d
  149. end interface
  150. contains
  151. ! ========================================================
  152. ! ===
  153. ! === Init, Done
  154. ! ===
  155. ! ========================================================
  156. !
  157. ! blat(j) +-------+
  158. ! | | |
  159. ! lat(j) |---o---|
  160. ! | | |
  161. ! +-------+
  162. ! lon(i)
  163. ! blon(i)
  164. !
  165. !--------------------------------------------------------------------------
  166. ! TM5 !
  167. !--------------------------------------------------------------------------
  168. !BOP
  169. !
  170. ! !IROUTINE: LLGRIDINFO_INIT
  171. !
  172. ! !DESCRIPTION: Initialize Longitude-Latitude Grid object
  173. !\\
  174. !\\
  175. ! !INTERFACE:
  176. !
  177. SUBROUTINE LLGridInfo_Init( lli, west_deg, dlon_deg, im, &
  178. south_deg, dlat_deg, jm, status, name )
  179. !
  180. ! !USES:
  181. !
  182. use Grid_Tools, only : ll_area
  183. use grid_tools, only : deg2rad, ae
  184. !
  185. ! !OUTPUT PARAMETERS:
  186. !
  187. type(TllGridInfo), intent(inout) :: lli
  188. integer, intent(out) :: status
  189. !
  190. ! !INPUT PARAMETERS:
  191. !
  192. real, intent(in) :: west_deg ! longitude center of 1st grid cell
  193. real, intent(in) :: dlon_deg ! spacing in degree
  194. integer, intent(in) :: im
  195. real, intent(in) :: south_deg ! latitude center of 1st grid cell
  196. real, intent(in) :: dlat_deg ! spacing in degree
  197. integer, intent(in) :: jm
  198. character(len=*), intent(in), optional :: name
  199. !
  200. ! !REVISION HISTORY:
  201. ! 1 Apr 2011 - P. Le Sager - some doc
  202. !
  203. ! !REMARKS: the 1st grid cell is the one at lower left (i.e. the further
  204. ! west and further south cell)
  205. !
  206. !EOP
  207. !------------------------------------------------------------------------
  208. !BOC
  209. integer :: i, j
  210. ! --- begin ---------------------------------
  211. if ( present(name) ) then
  212. lli%name = name
  213. else
  214. lli%name = 'anonymous'
  215. end if
  216. ! *** radius
  217. lli%R = ae
  218. ! *** grid spacing
  219. lli%dlon_deg = dlon_deg
  220. lli%dlon = dlon_deg*deg2rad
  221. lli%dlat_deg = dlat_deg
  222. lli%dlat = dlat_deg*deg2rad
  223. ! *** grid range
  224. lli%im = im
  225. lli%nlon = im
  226. lli%jm = jm
  227. lli%nlat = jm
  228. ! *** grid points
  229. ! * coor of grid points
  230. ! east-west
  231. if ( associated( lli%lon_deg) ) deallocate(lli%lon_deg)
  232. allocate( lli%lon_deg(im) )
  233. do i = 1, im
  234. lli%lon_deg(i) = west_deg + (i-1)*dlon_deg
  235. end do
  236. if ( associated( lli%lon) ) deallocate(lli%lon)
  237. allocate( lli%lon(im) )
  238. lli%lon = lli%lon_deg * deg2rad
  239. ! south-north
  240. if ( associated( lli%lat_deg) ) deallocate(lli%lat_deg)
  241. allocate( lli%lat_deg(jm) )
  242. do j = 1, jm
  243. lli%lat_deg(j) = south_deg + (j-1)*dlat_deg
  244. end do
  245. if ( associated( lli%lat) ) deallocate(lli%lat)
  246. allocate( lli%lat(jm) )
  247. lli%lat = lli%lat_deg * deg2rad
  248. ! *** cells with grid point in center;
  249. ! grid point at pole is at top of triangle !
  250. ! * bounds
  251. ! west-east
  252. if ( associated( lli%blon_deg) ) deallocate(lli%blon_deg)
  253. allocate( lli%blon_deg(0:im) )
  254. do i = 0, im
  255. lli%blon_deg(i) = west_deg + (i-0.5)*dlon_deg
  256. end do
  257. if ( associated( lli%blon) ) deallocate(lli%blon)
  258. allocate( lli%blon(0:im) )
  259. lli%blon = lli%blon_deg * deg2rad
  260. ! south-north
  261. if ( associated( lli%blat_deg) ) deallocate(lli%blat_deg)
  262. allocate( lli%blat_deg(0:jm) )
  263. do j = 0, jm
  264. lli%blat_deg(j) = south_deg + (j-0.5)*dlat_deg
  265. end do
  266. if ( lli%blat_deg(0) < -90.0 ) lli%blat_deg(0) = -90.0
  267. if ( lli%blat_deg(0) > 90.0 ) lli%blat_deg(0) = 90.0
  268. if ( lli%blat_deg(jm) < -90.0 ) lli%blat_deg(jm) = -90.0
  269. if ( lli%blat_deg(jm) > 90.0 ) lli%blat_deg(jm) = 90.0
  270. if ( associated( lli%blat) ) deallocate(lli%blat)
  271. allocate( lli%blat(0:jm) )
  272. lli%blat = lli%blat_deg * deg2rad
  273. ! * bounds in a rank-2 array:
  274. ! west-east
  275. if ( associated( lli%lon_bounds_deg) ) deallocate(lli%lon_bounds_deg)
  276. allocate( lli%lon_bounds_deg(2,im) )
  277. lli%lon_bounds_deg(1,:) = lli%blon_deg(0:im-1)
  278. lli%lon_bounds_deg(2,:) = lli%blon_deg(1:im)
  279. if ( associated( lli%lon_bounds) ) deallocate(lli%lon_bounds)
  280. allocate( lli%lon_bounds(2,im) )
  281. lli%lon_bounds = lli%lon_bounds_deg * deg2rad
  282. ! south-north
  283. if ( associated( lli%lat_bounds_deg) ) deallocate(lli%lat_bounds_deg)
  284. allocate( lli%lat_bounds_deg(2,jm) )
  285. lli%lat_bounds_deg(1,:) = lli%blat_deg(0:jm-1)
  286. lli%lat_bounds_deg(2,:) = lli%blat_deg(1:jm)
  287. if ( associated( lli%lat_bounds) ) deallocate(lli%lat_bounds)
  288. allocate( lli%lat_bounds(2,jm) )
  289. lli%lat_bounds = lli%lat_bounds_deg * deg2rad
  290. ! * area of cell in lat band
  291. ! rad^2 :
  292. if ( associated( lli%area) ) deallocate(lli%area)
  293. allocate( lli%area(jm) )
  294. do j = 1, jm
  295. lli%area(j) = ll_area( 0.0, lli%dlon, lli%blat(j-1), lli%blat(j) )
  296. end do
  297. ! m^2 :
  298. if ( associated( lli%area_m2) ) deallocate(lli%area_m2)
  299. allocate( lli%area_m2(jm) )
  300. lli%area_m2 = lli%area * lli%R**2
  301. ! * length in m
  302. ! east-west, mid latitude of cell
  303. if ( associated( lli%dx) ) deallocate(lli%dx)
  304. allocate( lli%dx(jm) )
  305. lli%dx = lli%dlon * lli%R * cos(lli%lat)
  306. ! east-west, boundaries
  307. if ( associated( lli%bdx) ) deallocate(lli%bdx)
  308. allocate( lli%bdx(0:jm) )
  309. lli%bdx = lli%dlon * lli%R * cos(lli%blat)
  310. ! north-south, the same for each longitude
  311. lli%dy = lli%dlat * lli%R
  312. lli%bdy = lli%dlat * lli%R
  313. ! ok
  314. status = 0
  315. END SUBROUTINE LLGRIDINFO_INIT
  316. !EOC
  317. !--------------------------------------------------------------------------
  318. ! TM5 !
  319. !--------------------------------------------------------------------------
  320. !BOP
  321. !
  322. ! !IROUTINE: COPY_LLGRID
  323. !
  324. ! !DESCRIPTION: make a copy of one LLI
  325. !\\
  326. !\\
  327. ! !INTERFACE:
  328. !
  329. SUBROUTINE COPY_LLGRID(tgt_grid, src_grid)
  330. !
  331. ! !INPUT/OUTPUT PARAMETERS:
  332. !
  333. type(TllGridInfo), intent(inout) :: tgt_grid
  334. !
  335. ! !INPUT PARAMETERS:
  336. !
  337. type(TllGridInfo), intent(in) :: src_grid
  338. !
  339. ! !REVISION HISTORY:
  340. ! 1 Nov 2013 - Ph. Le Sager -
  341. !
  342. ! !REMARKS:
  343. !
  344. !EOP
  345. !------------------------------------------------------------------------
  346. !BOC
  347. character(len=*), parameter :: rname = mname//'/copy_llgrid'
  348. integer :: status
  349. if (.not.(associated( src_grid%lon_deg ))) then
  350. write(*,*) " : WARNING : source InfoGrid is not initialized"
  351. write(*,*) " : no data to copy. Returning."
  352. return
  353. endif
  354. call llgridinfo_Init( tgt_grid, src_grid%lon_deg(1), src_grid%dlon_deg, src_grid%im, &
  355. src_grid%lat_deg(1), src_grid%dlat_deg, src_grid%jm, status, src_grid%name )
  356. if (status/=0) write (*,'("ERROR in ",a)') rname
  357. END SUBROUTINE COPY_LLGRID
  358. !EOC
  359. !--------------------------------------------------------------------------
  360. ! TM5 !
  361. !--------------------------------------------------------------------------
  362. !BOP
  363. !
  364. ! !FUNCTION: LLGRID_EQUAL_LLGRID
  365. !
  366. ! !DESCRIPTION: Compare two LLIs. Returns .true. if both have been
  367. ! initialized and describe the same grid.
  368. !\\
  369. !\\
  370. ! !INTERFACE:
  371. !
  372. LOGICAL FUNCTION LLGRID_EQUAL_LLGRID( lliA , lliB )
  373. !
  374. ! !INPUT PARAMETERS:
  375. !
  376. type(TllGridInfo), intent(in) :: lliA, lliB
  377. !
  378. ! !REVISION HISTORY:
  379. !
  380. ! 23 Oct 2013 - Ph. Le Sager - v0
  381. !
  382. ! !REMARKS:
  383. ! (1) If both grids are not initialized then .false. is return.
  384. !
  385. !EOP
  386. !------------------------------------------------------------------------
  387. !BOC
  388. character(len=*), parameter :: name = mname//'/LLGRID_EQUAL_LLGRID'
  389. ! -- begin
  390. ! This would be problematic if using F90 instead of F95
  391. if ((.not.(associated( lliA%lon_deg ))) .or. (.not.(associated( lliB%lon_deg )))) then
  392. ! write(gol,*)'WARNING : LL ggrid A not initialized'; call goPr
  393. llgrid_equal_llgrid = .false.
  394. return
  395. end if
  396. ! Just compare the inputs of llgridinfo_Init to ensure equivalence
  397. llgrid_equal_llgrid = &
  398. ( lliA%dlon_deg == lliB%dlon_deg ).and. &
  399. ( lliA%nlon == lliB%nlon ).and. &
  400. ( lliA%dlat_deg == lliB%dlat_deg ).and. &
  401. ( lliA%nlat == lliB%nlat ).and. &
  402. ( lliA%lon_deg(1) == lliB%lon_deg(1) ).and. &
  403. ( lliA%lat_deg(1) == lliB%lat_deg(1) )
  404. END FUNCTION LLGRID_EQUAL_LLGRID
  405. !EOC
  406. ! ===
  407. subroutine llgridinfo_Done( lli, status )
  408. ! --- in/out ---------------------------------
  409. type(TllGridInfo), intent(inout) :: lli
  410. integer, intent(out) :: status
  411. ! --- begin ---------------------------------
  412. if (associated( lli%lon_deg )) deallocate( lli%lon_deg )
  413. if (associated( lli%lat_deg )) deallocate( lli%lat_deg )
  414. if (associated( lli%lon )) deallocate( lli%lon )
  415. if (associated( lli%lat )) deallocate( lli%lat )
  416. if (associated( lli%blon_deg )) deallocate( lli%blon_deg )
  417. if (associated( lli%blat_deg )) deallocate( lli%blat_deg )
  418. if (associated( lli%blon )) deallocate( lli%blon )
  419. if (associated( lli%blat )) deallocate( lli%blat )
  420. if (associated( lli%lon_bounds_deg )) deallocate( lli%lon_bounds_deg )
  421. if (associated( lli%lat_bounds_deg )) deallocate( lli%lat_bounds_deg )
  422. if (associated( lli%lon_bounds )) deallocate( lli%lon_bounds )
  423. if (associated( lli%lat_bounds )) deallocate( lli%lat_bounds )
  424. if (associated( lli%area )) deallocate( lli%area )
  425. if (associated( lli%area_m2 )) deallocate( lli%area_m2 )
  426. if (associated( lli%dx )) deallocate( lli%dx )
  427. if (associated( lli%bdx )) deallocate( lli%bdx )
  428. status = 0
  429. end subroutine llgridinfo_Done
  430. ! =============================================================
  431. subroutine llgrid_Check_i( lli, nuv, ll, status )
  432. ! --- in/out ----------------------------------
  433. type(TllGridInfo), intent(in) :: lli
  434. character(len=*), intent(in) :: nuv
  435. integer, intent(in) :: ll(:,:)
  436. integer, intent(out) :: status
  437. ! --- const -----------------------------
  438. character(len=*), parameter :: rname = mname//'/llgrid_Check_i'
  439. ! --- begin ----------------------------------
  440. ! check shape of target grid:
  441. if ( ((nuv == 'n') .and. ((size(ll,1) /= lli%nlon ) .or. (size(ll,2) /= lli%nlat ))) .or. &
  442. ((nuv == 'u') .and. ((size(ll,1) /= lli%nlon+1) .or. (size(ll,2) /= lli%nlat ))) .or. &
  443. ((nuv == 'v') .and. ((size(ll,1) /= lli%nlon ) .or. (size(ll,2) /= lli%nlat+1))) ) then
  444. write (*,'("ERROR - target array does not match with grid definition:")')
  445. write (*,'("ERROR - lli : ",i3," x ",i3)') lli%nlon, lli%nlat
  446. write (*,'("ERROR - nuv : ",a )') nuv
  447. write (*,'("ERROR - ll : ",i3," x ",i3)') shape(ll)
  448. write (*,'("ERROR in ",a)') rname; status=1; return
  449. end if
  450. ! ok
  451. status = 0
  452. end subroutine llgrid_Check_i
  453. ! ***
  454. subroutine llgrid_Check_r( lli, nuv, ll, status )
  455. ! --- in/out ----------------------------------
  456. type(TllGridInfo), intent(in) :: lli
  457. character(len=*), intent(in) :: nuv
  458. real, intent(in) :: ll(:,:)
  459. integer, intent(out) :: status
  460. ! --- const -----------------------------
  461. character(len=*), parameter :: rname = mname//'/llgrid_Check_r'
  462. ! --- begin ----------------------------------
  463. ! check shape of target grid:
  464. if ( ((nuv == 'n') .and. ((size(ll,1) /= lli%nlon ) .or. (size(ll,2) /= lli%nlat ))) .or. &
  465. ((nuv == 'u') .and. ((size(ll,1) /= lli%nlon+1) .or. (size(ll,2) /= lli%nlat ))) .or. &
  466. ((nuv == 'v') .and. ((size(ll,1) /= lli%nlon ) .or. (size(ll,2) /= lli%nlat+1))) ) then
  467. write (*,'("ERROR - target array does not match with grid definition:")')
  468. write (*,'("ERROR - lli : ",i3," x ",i3)') lli%nlon, lli%nlat
  469. write (*,'("ERROR - nuv : ",a )') nuv
  470. write (*,'("ERROR - ll : ",i3," x ",i3)') shape(ll)
  471. write (*,'("ERROR in ",a)') rname; status=1; return
  472. end if
  473. ! ok
  474. status = 0
  475. end subroutine llgrid_Check_r
  476. ! =====================================================
  477. ! call AreaOper( lli, ll, '/' | '*' | '=', 'rad2' | 'm2' )
  478. subroutine llgrid_AreaOper_2d( lli, ll, oper, unit, status )
  479. ! --- in/out ----------------------------------
  480. type(TllGridInfo), intent(in) :: lli
  481. real, intent(inout) :: ll(:,:)
  482. character(len=*), intent(in) :: unit, oper
  483. integer, intent(out) :: status
  484. ! --- const -----------------------------
  485. character(len=*), parameter :: rname = mname//'/llgrid_AreaOper_2d'
  486. ! --- local --------------------------------
  487. integer :: j
  488. real :: cell_area
  489. ! --- begin ----------------------------------
  490. ! check ...
  491. if ( size(ll,2) /= lli%nlat ) then
  492. write (*,'("ERROR - unexpected size of ll grid:")')
  493. write (*,'("ERROR - shape(ll) : ",i4," x ",i4)') shape(ll)
  494. write (*,'("ERROR - lli%nlat : ",i4)') lli%nlat
  495. write (*,'("ERROR in ",a)') rname; status=1; return
  496. end if
  497. ! loop over latitudes:
  498. do j = 1, lli%nlat
  499. ! select correct area for cells in this row:
  500. select case ( unit )
  501. case ( 'rad2' )
  502. cell_area = lli%area(j)
  503. case ( 'm2' )
  504. cell_area = lli%area_m2(j)
  505. case default
  506. write (*,'("ERROR - unknown unit : ",a)') trim(unit)
  507. write (*,'("ERROR in ",a)') rname; status=1; return
  508. end select
  509. ! assign/mult/div by cell area:
  510. select case ( oper )
  511. case ( '=' )
  512. ll(:,j) = cell_area
  513. case ( '/' )
  514. ll(:,j) = ll(:,j) / cell_area
  515. case ( '*' )
  516. ll(:,j) = ll(:,j) * cell_area
  517. case default
  518. write (*,'("ERROR - unknown operation : ",a)') trim(oper)
  519. write (*,'("ERROR in ",a)') rname; status=1; return
  520. end select
  521. end do
  522. ! ok
  523. status = 0
  524. end subroutine llgrid_AreaOper_2d
  525. ! *
  526. subroutine llgrid_AreaOper_3d( lli, ll, oper, unit, status )
  527. ! --- in/out ----------------------------------
  528. type(TllGridInfo), intent(in) :: lli
  529. real, intent(inout) :: ll(:,:,:)
  530. character(len=*), intent(in) :: oper
  531. character(len=*), intent(in) :: unit
  532. integer, intent(out) :: status
  533. ! --- const -----------------------------
  534. character(len=*), parameter :: rname = mname//'/llgrid_AreaOper_3d'
  535. ! --- local --------------------------------
  536. integer :: l
  537. ! --- begin ----------------------------------
  538. ! loop over layers
  539. do l = 1, size(ll,3)
  540. ! apply 2d operator:
  541. call AreaOper( lli, ll(:,:,l), oper, unit, status )
  542. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  543. end do
  544. ! ok
  545. status = 0
  546. end subroutine llgrid_AreaOper_3d
  547. ! =====================================
  548. !
  549. ! Interpolation to (lon,lat) in deg.
  550. !
  551. subroutine llgrid_InterpolFractions( lli, lon, lat, ii, jj, ff )
  552. ! --- in/out ---------------------------
  553. type(TllGridInfo), intent(in) :: lli
  554. real, intent(in) :: lon, lat ! deg
  555. integer, intent(out) :: ii(4)
  556. integer, intent(out) :: jj(4)
  557. real, intent(out) :: ff(4)
  558. ! --- local -----------------------------
  559. real :: lonX, latX
  560. real :: ir
  561. integer :: i1, i2
  562. real :: i1f, i2f
  563. real :: jr
  564. integer :: j1, j2
  565. real :: j1f, j2f
  566. ! --- begin -----------------------------
  567. ! bring lon in [-180,180.0]
  568. lonX = modulo(lon,360.0)
  569. if ( lonX > 180.0 ) lonX = lonX - 360.0
  570. ! check lat
  571. latX = lat
  572. if ( latX < -90.0 .or. latX > 90.0 ) then
  573. write (*,'("ERROR - invalid lat (deg) :",f12.4)') latX
  574. write (*,'("ERROR in ",a)') 'llgrid_InterpolFractions'; stop
  575. end if
  576. !
  577. ! 1 2
  578. ! 3 4
  579. !
  580. ! i fractions ; circular
  581. !
  582. ! *
  583. ! [----+----][----+----] .. [----+----]
  584. ! ir 1.0 2.0 120.0
  585. !
  586. ir = ( lonX - lli%lon_deg(1) ) / lli%dlon_deg + 1.0
  587. i1 = floor(ir)
  588. i2 = i1 + 1
  589. !
  590. i2f = ( ir - i1 ) / ( i2 - i1 )
  591. i1f = 1.0 - i2f
  592. !
  593. if ( i1 < 1 ) i1 = lli%nlon
  594. if ( i2 > lli%nlon ) i2 = 1
  595. ! j fractions ; constant in half cells at poles
  596. jr = ( latX - lli%lat_deg(1) ) / lli%dlat_deg + 1.0
  597. j1 = floor(jr)
  598. j2 = j1 + 1
  599. !
  600. if ( j1 < 1 ) then
  601. j2f = ( jr - 0.5 ) / ( j2 - 0.5 )
  602. j1f = 1.0 - j2f
  603. else if ( j2 > lli%nlat ) then
  604. j2f = ( jr - j1 ) / ( lli%nlat+0.5 - j1 )
  605. j1f = 1.0 - j2f
  606. else
  607. j2f = ( jr - j1 ) / ( j2 - j1 )
  608. j1f = 1.0 - j2f
  609. end if
  610. ! fill output
  611. !
  612. ! j2 3 4
  613. ! j1 1 2
  614. !
  615. ! i1 i2
  616. !
  617. ii = (/ i1, i2, i1, i2 /)
  618. jj = (/ j1, j1, j2, j2 /)
  619. ff = (/ i1f*j1f, i2f*j1f, i1f*j2f, i2f*j2f /)
  620. ! write (*,'(" ",2i5)') ii(3), ii(4)
  621. ! write (*,'(i4," ",f4.2," ",f4.2," ",i4)') jj(3),ff(3),ff(4),jj(4)
  622. ! write (*,'(i4," ",f4.2," ",f4.2," ",i4)') jj(1),ff(1),ff(2),jj(2)
  623. ! write (*,'(" ",2i5)') ii(1), ii(2)
  624. end subroutine llgrid_InterpolFractions
  625. ! ***
  626. subroutine llgrid_Eval_2d( lli, ll, lon, lat, res )
  627. ! --- in/out ---------------------------
  628. type(TllGridInfo), intent(in) :: lli
  629. real, intent(in) :: ll(:,:)
  630. real, intent(in) :: lon, lat ! deg
  631. real, intent(out) :: res
  632. integer :: status
  633. ! --- const -----------------------------
  634. character(len=*), parameter :: rname = mname//'/llgrid_Eval_2d'
  635. ! --- local -----------------------------
  636. integer :: ii(4)
  637. integer :: jj(4)
  638. real :: ff(4)
  639. integer :: k
  640. real :: value
  641. ! --- begin -----------------------------
  642. ! check ...
  643. call Check( lli, 'n', ll, status )
  644. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; stop; end if
  645. ! indices and fractions
  646. call InterpolFractions( lli, lon, lat, ii, jj, ff )
  647. ! init zero
  648. res = 0.0
  649. ! add contributions:
  650. do k = 1, 4
  651. ! handle poles
  652. if ( jj(k) < 1 ) then
  653. value = sum(ll(:,1))/lli%nlon
  654. else if ( jj(k) > lli%nlat ) then
  655. value = sum(ll(:,lli%nlat))/lli%nlon
  656. else
  657. value = ll(ii(k),jj(k))
  658. end if
  659. ! add fraction
  660. res = res + value * ff(k)
  661. end do
  662. end subroutine llgrid_Eval_2d
  663. ! ***
  664. subroutine llgrid_Eval_3d( lli, ll, lon, lat, res )
  665. ! --- in/out ---------------------------
  666. type(TllGridInfo), intent(in) :: lli
  667. real, intent(in) :: ll(:,:,:)
  668. real, intent(in) :: lon, lat ! deg
  669. real, intent(out) :: res(size(ll,3))
  670. integer :: status
  671. ! --- const -----------------------------
  672. character(len=*), parameter :: rname = mname//'/llgrid_Eval_3d'
  673. ! --- local -----------------------------
  674. integer :: ii(4)
  675. integer :: jj(4)
  676. real :: ff(4)
  677. integer :: k
  678. real :: value(size(ll,3))
  679. ! --- begin -----------------------------
  680. ! check ...
  681. call Check( lli, 'n', ll(:,:,1), status )
  682. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; stop; end if
  683. ! indices and fractions
  684. call InterpolFractions( lli, lon, lat, ii, jj, ff )
  685. ! init zero
  686. res = 0.0
  687. ! add contributions:
  688. do k = 1, 4
  689. ! handle poles
  690. if ( jj(k) < 1 ) then
  691. value = sum(ll(:,1,:),1) / lli%nlon
  692. else if ( jj(k) > lli%nlat ) then
  693. value = sum(ll(:,lli%nlat,:),1) / lli%nlon
  694. else
  695. value = ll(ii(k),jj(k),:)
  696. end if
  697. ! add fraction
  698. res = res + value * ff(k)
  699. end do
  700. end subroutine llgrid_Eval_3d
  701. ! =================================================================
  702. ! ===
  703. ! === match fine grid with coarse grid
  704. ! ===
  705. ! =================================================================
  706. subroutine GetRefinement( cgi, fgi, &
  707. refine_i, refine_j, &
  708. cg_i1, cg_i2, cg_j1, cg_j2, status )
  709. ! --- in/out ------------------------------
  710. type(TllGridInfo), intent(in) :: cgi
  711. type(TllGridInfo), intent(in) :: fgi
  712. integer, intent(out) :: refine_i, refine_j
  713. integer, intent(out) :: cg_i1, cg_i2, cg_j1, cg_j2
  714. integer, intent(out) :: status
  715. ! --- const -----------------------------
  716. character(len=*), parameter :: rname = mname//'/GetRefinement'
  717. ! --- local -----------------------------
  718. integer :: i, j
  719. ! --- begin -----------------------------
  720. ! *** determine refinement
  721. refine_i = nint( cgi%dlon_deg / fgi%dlon_deg )
  722. refine_j = nint( cgi%dlat_deg / fgi%dlat_deg )
  723. ! *** position of fine grid within coarse grid:
  724. ! search column in coarse grid with same west bound as fine grid:
  725. cg_i1 = 0
  726. do i = 1, cgi%im
  727. if ( cgi%blon_deg(i-1) == fgi%blon_deg(0) ) then
  728. cg_i1 = i
  729. exit
  730. end if
  731. end do
  732. if ( cg_i1 < 1 ) then
  733. write (*,'("ERROR - could not match west bound of fine grid:")')
  734. write (*,'("ERROR - cgi%blon : ",f12.4)') cgi%blon_deg
  735. write (*,'("ERROR - target : ",f12.4)') fgi%blon_deg(0)
  736. write (*,'("ERROR in ",a)') rname; status=1; return
  737. end if
  738. ! search column in coarse grid with same east bound as fine grid:
  739. cg_i2 = 0
  740. do i = 1, cgi%im
  741. if ( cgi%blon_deg(i) == fgi%blon_deg(fgi%im) ) then
  742. cg_i2 = i
  743. exit
  744. end if
  745. end do
  746. if ( cg_i2 < 1 ) then
  747. write (*,'("ERROR - could not match east bound of fine grid")')
  748. write (*,'("ERROR - cgi%blon : ",f12.4)') cgi%blon_deg
  749. write (*,'("ERROR - target : ",f12.4)') fgi%blon_deg(fgi%im)
  750. write (*,'("ERROR in ",a)') rname; status=1; return
  751. end if
  752. ! check ...
  753. if ( (cg_i2-cg_i1+1)*refine_i /= fgi%im ) then
  754. write (*,'("ERROR - i refinement not ok:")')
  755. write (*,'("ERROR - coarse cells : ",f12.4)') cg_i1, cg_i2
  756. write (*,'("ERROR - refinement : ",f12.4)') refine_i
  757. write (*,'("ERROR - fine cells : ",f12.4)') fgi%im
  758. write (*,'("ERROR in ",a)') rname; status=1; return
  759. end if
  760. ! search row in coarse grid with same south bound as fine grid:
  761. cg_j1 = 0
  762. do j = 1, cgi%jm
  763. if ( cgi%blat_deg(j-1) == fgi%blat_deg(0) ) then
  764. cg_j1 = j
  765. exit
  766. end if
  767. end do
  768. if ( cg_j1 < 1 ) then
  769. write (*,'("ERROR - could not match south bound of fine grid")')
  770. write (*,'("ERROR in ",a)') rname; status=1; return
  771. end if
  772. ! search row in coarse grid with same south bound as fine grid:
  773. cg_j2 = 0
  774. do j = 1, cgi%jm
  775. if ( cgi%blat_deg(j) == fgi%blat_deg(fgi%jm) ) then
  776. cg_j2 = j
  777. exit
  778. end if
  779. end do
  780. if ( cg_j2 < 1 ) then
  781. write (*,'("ERROR - could not match north bound of fine grid")')
  782. write (*,'("ERROR in ",a)') rname; status=1; return
  783. end if
  784. ! check ...
  785. if ( (cg_j2-cg_j1+1)*refine_j /= fgi%jm ) then
  786. write (*,'("ERROR - j refinement not ok:")')
  787. write (*,'("ERROR - coarse cells : ",2i5)') cg_j1, cg_j2
  788. write (*,'("ERROR - refinement : ",i5)') refine_j
  789. write (*,'("ERROR - fine cells : ",i5)') fgi%jm
  790. write (*,'("ERROR in ",a)') rname; status=1; return
  791. end if
  792. ! ok
  793. status = 0
  794. end subroutine GetRefinement
  795. ! ***
  796. ! Relate fine grid and coarse grid:
  797. !
  798. ! call Match_cell( action, key, cgi, cg, fgi, fg )
  799. !
  800. ! 1. The coarse grid covers the same area as the fine grid:
  801. !
  802. ! action:
  803. ! 'combine' : fill coarse grid by combining cells of fine grid
  804. ! key:
  805. ! 'sum' : sum values in fine grid
  806. ! 'aver' : aver values in fine grid
  807. ! 'area-aver' : idem, weighted with area
  808. !
  809. ! 2. The fine grid is a subset of the coarse grid:
  810. !
  811. ! action:
  812. ! 'subset' : fill fine grid as a subset of coarse grid
  813. ! key:
  814. ! not used
  815. !
  816. ! 3. The fine grid is a zooming area of the coarse grid:
  817. !
  818. ! action:
  819. ! 'match' : adjust values in fine grid to match coarse grid
  820. ! key:
  821. ! 'sum' : sum values in fine grid
  822. ! 'aver' : aver values in fine grid
  823. ! 'area-aver' : idem, weighted with area
  824. !
  825. subroutine llgrid_Match( key, nuv, pgi, pg, tgi, tg, status )
  826. ! --- in/out ------------------------------
  827. ! character(len=*), intent(in) :: action
  828. character(len=*), intent(in) :: key
  829. character(len=1), intent(in) :: nuv
  830. type(TllGridInfo), intent(in) :: pgi
  831. real, intent(in) :: pg(pgi%im,pgi%jm)
  832. type(TllGridInfo), intent(in) :: tgi
  833. real, intent(inout) :: tg(tgi%im,tgi%jm)
  834. integer, intent(out) :: status
  835. ! --- const ---------------------------------
  836. character(len=*), parameter :: rname = mname//'/llgrid_Match'
  837. ! --- begin -----------------------------
  838. ! call nuv specific routine
  839. select case ( nuv )
  840. case ( 'n' )
  841. call Match_cell( key, pgi, pg, tgi, tg, status )
  842. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  843. case ( 'u' )
  844. call Match_u( key, pgi, pg, tgi, tg, status )
  845. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  846. case ( 'v' )
  847. call Match_v( key, pgi, pg, tgi, tg, status )
  848. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  849. case default
  850. write (*,'("ERROR - unsupported nuv `",a,"`")') nuv
  851. write (*,'("ERROR in ",a)') rname; status=1; return
  852. end select
  853. ! ok
  854. status = 0
  855. end subroutine llgrid_Match
  856. ! ***
  857. subroutine Match_cell( key, pgi, pg, tgi, tg, status )
  858. ! --- in/out ------------------------------
  859. ! character(len=*), intent(in) :: action
  860. character(len=*), intent(in) :: key
  861. type(TllGridInfo), intent(in) :: pgi
  862. real, intent(in) :: pg(pgi%im,pgi%jm)
  863. type(TllGridInfo), intent(in) :: tgi
  864. real, intent(inout) :: tg(tgi%im,tgi%jm)
  865. integer, intent(out) :: status
  866. ! --- const ---------------------------------
  867. character(len=*), parameter :: rname = mname//'/Match_cell'
  868. ! --- local -----------------------------
  869. integer :: refine_i, refine_j
  870. integer :: cg_i1, cg_i2, cg_j1, cg_j2
  871. integer :: ci, cj
  872. integer :: fg_i1, fg_i2, fg_j1, fg_j2
  873. integer :: fi, fj
  874. real :: fsum
  875. ! --- begin -----------------------------
  876. ! select case ( action )
  877. !
  878. ! !
  879. ! ! match fine grid with coarse cells:
  880. ! !
  881. ! case ( 'match' )
  882. ! determine refinement
  883. call GetRefinement( pgi, tgi, refine_i, refine_j, cg_i1, cg_i2, cg_j1, cg_j2, status )
  884. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  885. ! loop over cells in coarse grid covering fine grid:
  886. do cj = cg_j1, cg_j2
  887. do ci = cg_i1, cg_i2
  888. fg_i1 = (ci-cg_i1)*refine_i + 1 ; fg_i2 = fg_i1-1 + refine_i
  889. fg_j1 = (cj-cg_j1)*refine_j + 1 ; fg_j2 = fg_j1-1 + refine_j
  890. ! sum over cells in fine grid:
  891. select case ( key )
  892. case ( 'sum' )
  893. fsum = sum( tg(fg_i1:fg_i2,fg_j1:fg_j2) )
  894. ! distribute difference equally over all cells in fine grid:
  895. ! (/6,4/) + ( 14 - 10 )/ 2 = (/8,6/)
  896. tg(fg_i1:fg_i2,fg_j1:fg_j2) = tg(fg_i1:fg_i2,fg_j1:fg_j2) + (pg(ci,cj)-fsum)/(refine_j*refine_i)
  897. ! cmk corrected: divide by (refine_i * refine_j)
  898. case ( 'aver' )
  899. fsum = sum( tg(fg_i1:fg_i2,fg_j1:fg_j2) )/(refine_i*refine_j)
  900. ! add difference in averages to all cells in fine grid:
  901. ! (/6,4/) + ( 7 - 5 ) = (/8,6/)
  902. tg(fg_i1:fg_i2,fg_j1:fg_j2) = tg(fg_i1:fg_i2,fg_j1:fg_j2) + (pg(ci,cj)-fsum)
  903. case ( 'area-aver' )
  904. fsum = 0.0
  905. do fj = fg_j1, fg_j2
  906. fsum = fsum + sum(tg(fg_i1:fg_i2,fj))*tgi%area(fj)
  907. end do
  908. fsum = fsum / pgi%area(cj)
  909. ! add difference in averages to all cells in fine grid:
  910. ! (/6,4/) + ( 7 - 5 ) = (/8,6/)
  911. tg(fg_i1:fg_i2,fg_j1:fg_j2) = tg(fg_i1:fg_i2,fg_j1:fg_j2) + (pg(ci,cj)-fsum)
  912. case default
  913. write (*,'("ERROR - unsupported key for match action:")')
  914. ! write (*,'("ERROR - action : ",a)') trim(action)
  915. write (*,'("ERROR - key : ",a)') trim(key)
  916. write (*,'("ERROR in ",a)') rname; status=1; return
  917. end select
  918. ! ! match fine grid with coarse cell:
  919. ! if ( fsum == 0.0 ) then
  920. ! if ( abs(pg(ci,cj)) > 1.0e-5 ) then
  921. ! write (*,'("ERROR - zero sum over coarse cell (",i3,",",i3,")")') ci, cj
  922. ! write (*,'("ERROR - coarse cell : ",es12.4)') pg(ci,cj)
  923. ! write (*,'("ERROR - refine : ",2i6)') refine_i, refine_j
  924. ! write (*,'("ERROR - fine grid : ",es12.4)') tg(fg_i1:fg_i2,fg_j1:fg_j2)
  925. ! write (*,'("ERROR in ",a)') rname; status=1; return
  926. ! end if
  927. ! else
  928. ! ! scale towards value of coarse grid:
  929. ! tg(fg_i1:fg_i2,fg_j1:fg_j2) = tg(fg_i1:fg_i2,fg_j1:fg_j2) * pg(ci,cj)/fsum
  930. ! end if
  931. end do
  932. end do
  933. ! !
  934. ! ! fine grid is subset of coarse grid:
  935. ! !
  936. ! case ( 'subset' )
  937. !
  938. ! ! determine refinement
  939. ! call GetRefinement( pgi, tgi, refine_i, refine_j, cg_i1, cg_i2, cg_j1, cg_j2 )
  940. !
  941. ! if ( (refine_i /= 1) .or. (refine_j /= 1) ) then
  942. ! write (*,'("ERROR - for this action the fine grid should a subset of a coarse grid:")')
  943. ! write (*,'("ERROR - action : ",a)') trim(action)
  944. ! write (*,'("ERROR - refinement : ",2i6)') refine_i, refine_j
  945. ! write (*,'("ERROR in ",a)') rname; status=1; return
  946. ! end if
  947. !
  948. ! ! loop over cells in coarse grid covering fine grid:
  949. ! do cj = cg_j1, cg_j2
  950. ! do ci = cg_i1, cg_i2
  951. !
  952. ! fg_i1 = (ci-cg_i1) + 1
  953. ! fg_j1 = (cj-cg_j1) + 1
  954. !
  955. ! ! fine grid is subset of coarse grid
  956. ! tg(fg_i1,fg_j1) = pg(ci,cj)
  957. !
  958. ! end do
  959. ! end do
  960. !
  961. ! !
  962. ! ! collect cells in fine grid to coarse grid
  963. ! !
  964. ! case ( 'combine' )
  965. !
  966. ! ! determine refinement
  967. ! ! NOTE: parent grid is fine now, target is coarse !
  968. ! call GetRefinement( tgi, pgi, refine_i, refine_j, cg_i1, cg_i2, cg_j1, cg_j2 )
  969. !
  970. ! if ( (cg_i1 /= 1) .or. (cg_i2 /= tgi%im) .or. &
  971. ! (cg_j1 /= 1) .or. (cg_j2 /= tgi%jm) ) then
  972. ! write (*,'("ERROR - for this action the fine grid should cover the complete coarse grid:")')
  973. ! write (*,'("ERROR - action : ",a)') trim(action)
  974. ! write (*,'("ERROR - covered : [",i4,",",i4,"] x [",i4,",","]")') cg_i1,cg_i2,cg_j1,cg_j2
  975. ! write (*,'("ERROR - of : ",2i5)') tgi%im, tgi%jm
  976. ! write (*,'("ERROR in ",a)') rname; status=1; return
  977. ! end if
  978. !
  979. ! ! loop over cells in coarse grid covering fine grid:
  980. ! do cj = cg_j1, cg_j2
  981. ! do ci = cg_i1, cg_i2
  982. !
  983. ! fg_i1 = (ci-cg_i1)*refine_i + 1 ; fg_i2 = fg_i1-1 + refine_i
  984. ! fg_j1 = (cj-cg_j1)*refine_j + 1 ; fg_j2 = fg_j1-1 + refine_j
  985. !
  986. ! ! sum over cells in fine grid:
  987. ! select case ( key )
  988. ! case ( 'sum' )
  989. ! fsum = sum( pg(fg_i1:fg_i2,fg_j1:fg_j2) )
  990. ! case ( 'aver' )
  991. ! fsum = sum( pg(fg_i1:fg_i2,fg_j1:fg_j2) )/(refine_i*refine_j)
  992. ! case ( 'area-aver' )
  993. ! fsum = 0.0
  994. ! do fj = fg_j1, fg_j2
  995. ! fsum = fsum + sum(pg(fg_i1:fg_i2,fj))*pgi%area(fj)
  996. ! end do
  997. ! fsum = fsum / tgi%area(cj)
  998. ! case default
  999. ! write (*,'("ERROR - unsupported key for match action:")')
  1000. ! write (*,'("ERROR - action : ",a)') trim(action)
  1001. ! write (*,'("ERROR - key : ",a)') trim(key)
  1002. ! write (*,'("ERROR in ",a)') rname; status=1; return
  1003. ! end select
  1004. !
  1005. ! ! collect cells in fine parent grid to target coarse grid
  1006. ! tg(ci,cj) = fsum
  1007. !
  1008. ! end do
  1009. ! end do
  1010. !
  1011. ! case default
  1012. ! write (*,'("ERROR - unknown action `",a,"`")') trim(action)
  1013. ! write (*,'("ERROR in ",a)') rname; status=1; return
  1014. ! end select
  1015. ! ok
  1016. status = 0
  1017. end subroutine Match_cell
  1018. ! ***
  1019. ! flux through east/west boundaries
  1020. subroutine Match_u( key, pgi, pg, tgi, tg, status )
  1021. ! --- in/out ------------------------------
  1022. ! character(len=*), intent(in) :: action
  1023. character(len=*), intent(in) :: key
  1024. type(TllGridInfo), intent(in) :: pgi
  1025. real, intent(in) :: pg(0:pgi%im,pgi%jm)
  1026. type(TllGridInfo), intent(in) :: tgi
  1027. real, intent(inout) :: tg(0:tgi%im,tgi%jm)
  1028. integer, intent(out) :: status
  1029. ! --- const ---------------------------------
  1030. character(len=*), parameter :: rname = mname//'/Match_u'
  1031. ! --- local -----------------------------
  1032. integer :: refine_i, refine_j
  1033. integer :: cg_i1, cg_i2, cg_j1, cg_j2
  1034. integer :: ci, cj
  1035. integer :: fg_i, fg_j1, fg_j2
  1036. integer :: fi, fj
  1037. real :: fsum
  1038. ! --- begin -----------------------------
  1039. ! select case ( action )
  1040. !
  1041. ! !
  1042. ! ! match fine grid with coarse cells:
  1043. ! !
  1044. ! case ( 'match' )
  1045. ! determine refinement
  1046. call GetRefinement( pgi, tgi, refine_i, refine_j, cg_i1, cg_i2, cg_j1, cg_j2, status )
  1047. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  1048. ! loop over cells in coarse grid covering fine grid:
  1049. do cj = cg_j1, cg_j2
  1050. do ci = cg_i1-1, cg_i2
  1051. fg_i = (ci-(cg_i1-1))*refine_i
  1052. fg_j1 = (cj-cg_j1)*refine_j + 1 ; fg_j2 = fg_j1-1 + refine_j
  1053. ! sum over cells in fine grid:
  1054. select case ( key )
  1055. case ( 'sum' )
  1056. fsum = sum( tg(fg_i,fg_j1:fg_j2) )
  1057. ! distribute difference equally over all cells in fine grid:
  1058. ! (/6,4/) + ( 14 - 10 )/ 2 = (/8,6/)
  1059. tg(fg_i,fg_j1:fg_j2) = tg(fg_i,fg_j1:fg_j2) + (pg(ci,cj)-fsum)/refine_j
  1060. case ( 'aver' )
  1061. fsum = sum( tg(fg_i,fg_j1:fg_j2) )/(refine_j)
  1062. ! add difference in averages to all cells in fine grid:
  1063. ! (/6,4/) + ( 7 - 5 ) = (/8,6/)
  1064. tg(fg_i,fg_j1:fg_j2) = tg(fg_i,fg_j1:fg_j2) + (pg(ci,cj)-fsum)
  1065. case default
  1066. write (*,'("ERROR - unsupported key for match action:")')
  1067. ! write (*,'("ERROR - action : ",a)') trim(action)
  1068. write (*,'("ERROR - key : ",a)') trim(key)
  1069. write (*,'("ERROR in ",a)') rname; status=1; return
  1070. end select
  1071. ! ! match fine grid with coarse cell:
  1072. ! if ( fsum == 0.0 ) then
  1073. ! if ( pg(ci,cj) /= 0.0 ) then
  1074. ! write (*,'("ERROR - zero sum over coarse cell (",i3,",",i3,")")') ci, cj
  1075. ! write (*,'("ERROR - coarse cell : ",es12.4)') pg(ci,cj)
  1076. ! write (*,'("ERROR - refine : ",2i6)') refine_i, refine_j
  1077. ! write (*,'("ERROR - target grid : ",es12.4)') tg(fg_i,fg_j1:fg_j2)
  1078. ! write (*,'("ERROR in ",a)') rname; status=1; return
  1079. ! end if
  1080. ! else
  1081. ! ! scale towards value of coarse grid:
  1082. ! tg(fg_i,fg_j1:fg_j2) = tg(fg_i,fg_j1:fg_j2)/fsum * pg(ci,cj)
  1083. ! end if
  1084. end do
  1085. end do
  1086. ! !
  1087. ! ! fine grid is subset of coarse grid:
  1088. ! !
  1089. ! case ( 'subset' )
  1090. !
  1091. ! ! determine refinement
  1092. ! call GetRefinement( pgi, tgi, refine_i, refine_j, cg_i1, cg_i2, cg_j1, cg_j2 )
  1093. !
  1094. ! if ( (refine_i /= 1) .or. (refine_j /= 1) ) then
  1095. ! write (*,'("ERROR - for this action the fine grid should a subset of a coarse grid:")')
  1096. ! write (*,'("ERROR - action : ",a)') trim(action)
  1097. ! write (*,'("ERROR - refinement : ",2i6)') refine_i, refine_j
  1098. ! write (*,'("ERROR in ",a)') rname; status=1; return
  1099. ! end if
  1100. !
  1101. ! ! loop over cells in coarse grid covering fine grid:
  1102. ! do cj = cg_j1, cg_j2
  1103. ! do ci = cg_i1-1, cg_i2
  1104. !
  1105. ! fg_i = (ci-(cg_i1-1))
  1106. ! fg_j1 = (cj-cg_j1) + 1
  1107. !
  1108. ! ! fine grid is subset of coarse grid
  1109. ! tg(fg_i,fg_j1) = pg(ci,cj)
  1110. !
  1111. ! end do
  1112. ! end do
  1113. !
  1114. ! !
  1115. ! ! collect cells in fine grid to coarse grid
  1116. ! !
  1117. ! case ( 'combine' )
  1118. !
  1119. ! ! determine refinement
  1120. ! ! NOTE: parent grid is fine, targer is coarse !
  1121. ! call GetRefinement( tgi, pgi, refine_i, refine_j, cg_i1, cg_i2, cg_j1, cg_j2 )
  1122. !
  1123. ! if ( (cg_i1 /= 1) .or. (cg_i2 /= tgi%im) .or. &
  1124. ! (cg_j1 /= 1) .or. (cg_j2 /= tgi%jm) ) then
  1125. ! write (*,'("ERROR - for this action the fine grid should cover the complete coarse grid:")')
  1126. ! write (*,'("ERROR - action : ",a)') trim(action)
  1127. ! write (*,'("ERROR - covered : [",i4,",",i4,"] x [",i4,",","]")') cg_i1,cg_i2,cg_j1,cg_j2
  1128. ! write (*,'("ERROR - of : ",2i5)') tgi%im, tgi%jm
  1129. ! write (*,'("ERROR in ",a)') rname; status=1; return
  1130. ! end if
  1131. !
  1132. ! ! loop over cells in coarse grid covering fine grid:
  1133. ! do cj = cg_j1, cg_j2
  1134. ! do ci = cg_i1-1, cg_i2
  1135. !
  1136. ! fg_i = (ci-(cg_i1-1))*refine_i
  1137. ! fg_j1 = (cj-cg_j1)*refine_j + 1 ; fg_j2 = fg_j1-1 + refine_j
  1138. !
  1139. ! ! sum over cells in fine grid:
  1140. ! select case ( key )
  1141. ! case ( 'sum' )
  1142. ! fsum = sum( pg(fg_i,fg_j1:fg_j2) )
  1143. ! case ( 'aver' )
  1144. ! fsum = sum( pg(fg_i,fg_j1:fg_j2) )/(refine_j)
  1145. ! case default
  1146. ! write (*,'("ERROR - unsupported key for match action:")')
  1147. ! write (*,'("ERROR - action : ",a)') trim(action)
  1148. ! write (*,'("ERROR - key : ",a)') trim(key)
  1149. ! write (*,'("ERROR in ",a)') rname; status=1; return
  1150. ! end select
  1151. !
  1152. ! ! collect cells in fine parent grid to target coarse grid
  1153. ! tg(ci,cj) = fsum
  1154. !
  1155. ! end do
  1156. ! end do
  1157. !
  1158. ! case default
  1159. ! write (*,'("ERROR - unknown action `",a,"`")') trim(action)
  1160. ! write (*,'("ERROR in ",a)') rname; status=1; return
  1161. ! end select
  1162. ! ok
  1163. status = 0
  1164. end subroutine Match_u
  1165. ! ***
  1166. ! flux through north/south boundaries
  1167. subroutine Match_v( key, pgi, pg, tgi, tg, status )
  1168. ! --- in/out ------------------------------
  1169. ! character(len=*), intent(in) :: action
  1170. character(len=*), intent(in) :: key
  1171. type(TllGridInfo), intent(in) :: pgi
  1172. real, intent(in) :: pg(pgi%im,0:pgi%jm)
  1173. type(TllGridInfo), intent(in) :: tgi
  1174. real, intent(inout) :: tg(tgi%im,0:tgi%jm)
  1175. integer, intent(out) :: status
  1176. ! --- const ---------------------------------
  1177. character(len=*), parameter :: rname = mname//'/Match_v'
  1178. ! --- local -----------------------------
  1179. integer :: refine_i, refine_j
  1180. integer :: cg_i1, cg_i2, cg_j1, cg_j2
  1181. integer :: ci, cj
  1182. integer :: fg_i1, fg_i2, fg_j
  1183. integer :: fi, fj
  1184. real :: fsum
  1185. ! --- begin -----------------------------
  1186. ! select case ( action )
  1187. !
  1188. ! !
  1189. ! ! match fine grid with coarse cells:
  1190. ! !
  1191. ! case ( 'match' )
  1192. ! determine refinement
  1193. call GetRefinement( pgi, tgi, refine_i, refine_j, cg_i1, cg_i2, cg_j1, cg_j2, status )
  1194. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  1195. ! loop over cells in coarse grid covering fine grid:
  1196. do cj = cg_j1-1, cg_j2
  1197. do ci = cg_i1, cg_i2
  1198. fg_i1 = (ci-cg_i1)*refine_i + 1 ; fg_i2 = fg_i1-1 + refine_i
  1199. fg_j = (cj-(cg_j1-1))*refine_j
  1200. ! sum over cells in fine grid:
  1201. select case ( key )
  1202. case ( 'sum' )
  1203. fsum = sum( tg(fg_i1:fg_i2,fg_j) )
  1204. ! distribute difference equally over all cells in fine grid:
  1205. ! (/6,4/) + ( 14 - 10 )/ 2 = (/8,6/)
  1206. tg(fg_i1:fg_i2,fg_j) = tg(fg_i1:fg_i2,fg_j) + (pg(ci,cj)-fsum)/refine_i
  1207. case ( 'aver' )
  1208. fsum = sum( tg(fg_i1:fg_i2,fg_j) )/(refine_i)
  1209. ! add difference in averages to all cells in fine grid:
  1210. ! (/6,4/) + ( 7 - 5 ) = (/8,6/)
  1211. tg(fg_i1:fg_i2,fg_j) = tg(fg_i1:fg_i2,fg_j) + (pg(ci,cj)-fsum)
  1212. case default
  1213. write (*,'("ERROR - unsupported key for match action:")')
  1214. ! write (*,'("ERROR - action : ",a)') trim(action)
  1215. write (*,'("ERROR - key : ",a)') trim(key)
  1216. write (*,'("ERROR in ",a)') rname; status=1; return
  1217. end select
  1218. ! ! match fine grid with coarse cell:
  1219. ! if ( fsum == 0.0 ) then
  1220. ! if ( pg(ci,cj) /= 0.0 ) then
  1221. ! write (*,'("ERROR - zero sum over coarse cell (",i3,",",i3,")")') ci, cj
  1222. ! write (*,'("ERROR - coarse cell : ",es12.4)') pg(ci,cj)
  1223. ! write (*,'("ERROR - refine : ",2i6)') refine_i, refine_j
  1224. ! write (*,'("ERROR - fine grid : ",es12.4)') tg(fg_i1:fg_i2,fg_j)
  1225. ! write (*,'("ERROR in ",a)') rname; status=1; return
  1226. ! end if
  1227. ! else
  1228. ! ! scale towards value of coarse grid:
  1229. ! tg(fg_i1:fg_i2,fg_j) = tg(fg_i1:fg_i2,fg_j)/fsum * pg(ci,cj)
  1230. ! end if
  1231. end do
  1232. end do
  1233. ! !
  1234. ! ! fine grid is subset of coarse grid:
  1235. ! !
  1236. ! case ( 'subset' )
  1237. !
  1238. ! ! determine refinement
  1239. ! call GetRefinement( pgi, tgi, refine_i, refine_j, cg_i1, cg_i2, cg_j1, cg_j2 )
  1240. !
  1241. ! if ( (refine_i /= 1) .or. (refine_j /= 1) ) then
  1242. ! write (*,'("ERROR - for this action the fine grid should a subset of a coarse grid:")')
  1243. ! write (*,'("ERROR - action : ",a)') trim(action)
  1244. ! write (*,'("ERROR - refinement : ",2i6)') refine_i, refine_j
  1245. ! write (*,'("ERROR in ",a)') rname; status=1; return
  1246. ! end if
  1247. !
  1248. ! ! loop over cells in coarse grid covering fine grid:
  1249. ! do cj = cg_j1-1, cg_j2
  1250. ! do ci = cg_i1, cg_i2
  1251. !
  1252. ! fg_i1 = (ci-cg_i1) + 1
  1253. ! fg_j = (cj-(cg_j1-1))
  1254. !
  1255. ! ! fine grid is subset of coarse grid
  1256. ! tg(fg_i1,fg_j) = pg(ci,cj)
  1257. !
  1258. ! end do
  1259. ! end do
  1260. !
  1261. ! !
  1262. ! ! collect cells in fine grid to coarse grid
  1263. ! !
  1264. ! case ( 'combine' )
  1265. !
  1266. ! ! determine refinement
  1267. ! ! NOTE: parent grid is fine, target is coarse !
  1268. ! call GetRefinement( tgi, pgi, refine_i, refine_j, cg_i1, cg_i2, cg_j1, cg_j2 )
  1269. !
  1270. ! if ( (cg_i1 /= 1) .or. (cg_i2 /= tgi%im) .or. &
  1271. ! (cg_j1 /= 1) .or. (cg_j2 /= tgi%jm) ) then
  1272. ! write (*,'("ERROR - for this action the fine grid should cover the complete coarse grid:")')
  1273. ! write (*,'("ERROR - action : ",a)') trim(action)
  1274. ! write (*,'("ERROR - covered : [",i4,",",i4,"] x [",i4,",","]")') cg_i1,cg_i2,cg_j1,cg_j2
  1275. ! write (*,'("ERROR - of : ",2i5)') tgi%im, tgi%jm
  1276. ! write (*,'("ERROR in ",a)') rname; status=1; return
  1277. ! end if
  1278. !
  1279. ! ! loop over cells in coarse grid covering fine grid:
  1280. ! do cj = cg_j1-1, cg_j2
  1281. ! do ci = cg_i1, cg_i2
  1282. !
  1283. ! fg_i1 = (ci-cg_i1)*refine_i + 1 ; fg_i2 = fg_i1-1 + refine_i
  1284. ! fg_j = (cj-(cg_j1-1))*refine_j
  1285. !
  1286. ! ! sum over cells in fine grid:
  1287. ! select case ( key )
  1288. ! case ( 'sum' )
  1289. ! fsum = sum( pg(fg_i1:fg_i2,fg_j) )
  1290. ! case ( 'aver' )
  1291. ! fsum = sum( pg(fg_i1:fg_i2,fg_j) )/(refine_i)
  1292. ! case default
  1293. ! write (*,'("ERROR - unsupported key for match action:")')
  1294. ! write (*,'("ERROR - action : ",a)') trim(action)
  1295. ! write (*,'("ERROR - key : ",a)') trim(key)
  1296. ! write (*,'("ERROR in ",a)') rname; status=1; return
  1297. ! end select
  1298. !
  1299. ! ! collect cells in fine parent grid to target coarse grid
  1300. ! tg(ci,cj) = fsum
  1301. !
  1302. ! end do
  1303. ! end do
  1304. !
  1305. ! case default
  1306. ! write (*,'("ERROR - unknown action `",a,"`")') trim(action)
  1307. ! write (*,'("ERROR in ",a)') rname; status=1; return
  1308. ! end select
  1309. ! ok
  1310. status = 0
  1311. end subroutine Match_v
  1312. ! ========================================================
  1313. ! ===
  1314. ! === fill grid from other grid
  1315. ! ===
  1316. ! ========================================================
  1317. !
  1318. ! NUV
  1319. !
  1320. ! Key to identify data positions:
  1321. ! 'n' : value valid for cell (center) ll(1:nlon ,1:nlat )
  1322. ! 'u' : value valid for east/west boundaries ll(1:nlon+1,1:nlat )
  1323. ! 'v' : value valid for north/south boundaries ll(1:nlon ,1:nlat+1)
  1324. !
  1325. ! ROUTINES
  1326. !
  1327. ! call FillGrid( lli, nuv, ll, lliX, nuvX, llX, combkey, status [,llX_w] )
  1328. !
  1329. ! Fill ll (defined by lli,nuv) with values from llX (defined by lliX,nuvX)
  1330. !
  1331. ! Coverage of lli by lliX :
  1332. ! o lliX is larger than or equal to lli -> all cells in ll changed
  1333. ! o lliX is smaller than lli -> only part of ll is changed
  1334. !
  1335. ! Create new ll from llX:
  1336. ! o llX is superset -> copy values from llX into ll
  1337. ! o llX is fine -> fill ll by combining cells in llX
  1338. ! (average/sum/etc given the combine key)
  1339. !
  1340. ! Combine keys:
  1341. !
  1342. ! 'sum' : sum_i llX_i
  1343. !
  1344. ! 'aver' : sum_i llX_i / sum_i i
  1345. !
  1346. ! 'area-aver' : sum_i llX_i A_i / sum_i A_i
  1347. !
  1348. ! 'weight' : sum_i llX_i llX_w_i / sum_i llX_w_i
  1349. ! (only for nuv='n')
  1350. !
  1351. ! Return status:
  1352. ! 0 : ok
  1353. ! -1 : only part of ll is filled
  1354. !
  1355. !
  1356. ! AdjustGrid NOT IMPLEMENTED YET
  1357. !
  1358. ! Adjust ll given llX:
  1359. ! o llX is coarse -> adjust ll such that average/sum/.. of lli matches
  1360. !
  1361. ! 15 Dec 2010 - P. Le Sager - added fix for 'mass-aver' (always
  1362. ! understood as area-averaged)
  1363. !
  1364. subroutine FillGrid( lli, nuv, ll, lliX, nuvX, llX, combkey, status, llX_w )
  1365. use dims, only : okdebug
  1366. use GO, only : gol, goPr
  1367. ! --- in/out --------------------------------
  1368. type(TllGridInfo), intent(in) :: lli
  1369. character(len=*), intent(in) :: nuv
  1370. real, intent(out) :: ll(:,:)
  1371. type(TllGridInfo), intent(in) :: lliX
  1372. character(len=*), intent(in) :: nuvX
  1373. real, intent(in) :: llX(:,:)
  1374. character(len=*), intent(in) :: combkey
  1375. integer, intent(out) :: status
  1376. real, intent(in), optional :: llX_w(:,:)
  1377. ! --- const ---------------------------------
  1378. character(len=*), parameter :: rname = mname//'/FillGrid'
  1379. ! --- local ---------------------------------
  1380. character(len=10) :: action
  1381. integer :: di, dj
  1382. integer :: i1, i2, j1, j2
  1383. integer :: js, je
  1384. integer :: i, j
  1385. integer :: i1X, i2X, j1X, j2X
  1386. integer :: iX, jX
  1387. integer :: diX, djX, nX
  1388. real :: res, resw
  1389. integer :: ia, ib, ja, jb
  1390. integer :: iaX, ibX, jaX, jbX
  1391. real :: llX_ab
  1392. real, allocatable :: wwX(:,:)
  1393. logical :: wwdiv
  1394. logical :: only_part_of_ll
  1395. ! --- begin ---------------------------------
  1396. ! check input ...
  1397. if ( nuv /= nuvX ) then
  1398. write (*,'("ERROR - nuv keys should be equal:")') combkey
  1399. write (*,'("ERROR - nuv : `",a,"`")') nuv
  1400. write (*,'("ERROR - nuvX : `",a,"`")') nuvX
  1401. write (*,'("ERROR in ",a)') rname; status=1; return
  1402. end if
  1403. ! determine how lliX is related to lli:
  1404. ! i1, i2, j1, j2 : cell ranges in lli covered by cells of lliX
  1405. ! i1X, i2X, j1X, j2X : cell ranges in lliX covering cells of lliX
  1406. ! action : 'copy', 'combine'
  1407. call Relate( lli , i1 , i2 , j1 , j2 , &
  1408. lliX, i1X, i2X, j1X, j2X, &
  1409. action, status )
  1410. select case ( status )
  1411. case ( -1 )
  1412. only_part_of_ll = .true.
  1413. case ( 0 )
  1414. only_part_of_ll = .false.
  1415. case default
  1416. write (*,'("ERROR in ",a)') rname; return
  1417. end select
  1418. ! IF(okdebug)THEN
  1419. ! WRITE(gol,'(a," : action = ",a)') rname, action; CALL goPr
  1420. ! ENDIF
  1421. ! what to do with cells in llX?
  1422. select case ( action )
  1423. !
  1424. ! * copy
  1425. !
  1426. ! 'copy' : lli and lliX define same resolution;
  1427. ! the cells from llX area [i1X,i2X] x [j1X,j2X]
  1428. ! should be copied into ll area [i1,i2] x [j1,j2]
  1429. case ( 'copy' )
  1430. select case ( nuv )
  1431. case ( 'n' )
  1432. ! loop over (selection of) cells of target grid lli:
  1433. !$OMP PARALLEL &
  1434. !$OMP default (none) &
  1435. !$OMP shared (i1, i2, j1, j2, i1x, j1x, llx, ll) &
  1436. !$OMP private (i, j, js, je, ix, jx)
  1437. do j = j1, j2
  1438. do i = i1, i2
  1439. ! source cell in llX:
  1440. iX = i1X + i-i1
  1441. jX = j1X + j-j1
  1442. ! copy cell:
  1443. ll(i,j) = llX(iX,jX)
  1444. end do
  1445. end do
  1446. !$OMP END PARALLEL
  1447. case ( 'u' )
  1448. ! loop over (selection of) cells of target grid lli:
  1449. do j = j1, j2
  1450. do i = i1, i2+1
  1451. ! source cell in llX:
  1452. iX = i1X + i-i1
  1453. jX = j1X + j-j1
  1454. ! copy cell:
  1455. ll(i,j) = llX(iX,jX)
  1456. end do
  1457. end do
  1458. case ( 'v' )
  1459. ! loop over (selection of) cells of target grid lli:
  1460. do j = j1, j2+1
  1461. do i = i1, i2
  1462. ! source cell in llX:
  1463. iX = i1X + i-i1
  1464. jX = j1X + j-j1
  1465. ! copy cell:
  1466. ll(i,j) = llX(iX,jX)
  1467. end do
  1468. end do
  1469. case default
  1470. write (*,'("ERROR - unsupported nuv `",a,"`")') nuv
  1471. write (*,'("ERROR - action : `",a,"`")') action
  1472. write (*,'("ERROR in ",a)') rname; status=1; return
  1473. end select
  1474. !
  1475. ! * combine
  1476. !
  1477. ! 'combine' : lliX defines a fine resolution;
  1478. ! the cells from llX area [i1X,i2X] x [j1X,j2X]
  1479. ! should be combined and copied into ll area [i1,i2] x [j1,j2]
  1480. case ( 'combine' )
  1481. ! resolution of fine cells (lliX) in cell of lli,
  1482. ! for example 3 x 2 :
  1483. diX = (i2X-i1X+1) / (i2-i1+1)
  1484. djX = (j2X-j1X+1) / (j2-j1+1)
  1485. nX = diX * djX
  1486. select case ( nuv )
  1487. case ( 'n' )
  1488. !
  1489. ! set weight:
  1490. !
  1491. ! 'weight' : (sum_i f_i w_i) / (sum_i w_i)
  1492. !
  1493. ! 'sum' : (sum_i f_i) : w = 1.0
  1494. ! 'aver' : (sum_i f_i) / (sum_i) : w = 1.0, wwdiv
  1495. ! 'area-aver' : (sum_i f_i A_i) / (sum_i A_i) : w = A_i, wwdiv
  1496. ! same size as input grid:
  1497. allocate( wwX(size(llX,1),size(llX,2)) )
  1498. ! weight provided as argument ?
  1499. if ( combkey == 'weight' ) then
  1500. if ( .not. present(llX_w) ) then
  1501. write (*,'("ERROR - combkey `weight` but llX_w not present ...")')
  1502. write (*,'("ERROR in ",a)') rname; status=1; return
  1503. end if
  1504. if ( any( shape(llX_w) /= shape(llX) ) ) then
  1505. write (*,'("ERROR - weight should have shape of input grid:")')
  1506. write (*,'("ERROR - shape(llX_w) : `",2i6)') shape(llX_w)
  1507. write (*,'("ERROR - shape(llX) : `",2i6)') shape(llX)
  1508. write (*,'("ERROR in ",a)') rname; status=1; return
  1509. end if
  1510. wwX = llX_w
  1511. wwdiv = .true.
  1512. else
  1513. if ( present(llX_w) ) then
  1514. write (*,'("ERROR - llX_w pressent but no combkey `weight` ...")')
  1515. write (*,'("ERROR in ",a)') rname; status=1; return
  1516. end if
  1517. ! fill weight given combkey:
  1518. select case ( combkey )
  1519. case ( 'sum' )
  1520. wwX = 1.0
  1521. wwdiv = .false.
  1522. case ( 'aver' )
  1523. wwX = 1.0
  1524. wwdiv = .true.
  1525. case ( 'area-aver','mass-aver' )
  1526. call AreaOper( lliX, wwX, '=', 'm2', status )
  1527. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  1528. wwdiv = .true.
  1529. case default
  1530. write (*,'("ERROR - unsupported combkey `",a,"`")') combkey
  1531. write (*,'("ERROR - nuv : `",a,"`")') nuv
  1532. write (*,'("ERROR - action : `",a,"`")') action
  1533. write (*,'("ERROR in ",a)') rname; status=1; return
  1534. end select
  1535. end if
  1536. ! loop over (selection of) cells of target grid lli:
  1537. !$OMP PARALLEL &
  1538. !$OMP default (none) &
  1539. !$OMP shared (i1, i2, j1, j2, i1x, j1x, djx, dix, llx, wwx, wwdiv, &
  1540. !$OMP ll) &
  1541. !$OMP private (i, j, js, je, res, resw, ix, jx)
  1542. do j = j1, j2
  1543. do i = i1, i2
  1544. ! start with zero result:
  1545. res = 0.0
  1546. resw = 0.0
  1547. ! loop over source cells in llX:
  1548. do jX = j1X + (j-j1)*djX, j1X + (j-j1+1)*djX-1
  1549. do iX = i1X + (i-i1)*diX, i1X + (i-i1+1)*diX-1
  1550. res = res + llX(iX,jX) * wwX(iX,jX)
  1551. resw = resw + wwX(iX,jX)
  1552. end do
  1553. end do
  1554. ! fill result:
  1555. if ( wwdiv ) then
  1556. ll(i,j) = res / resw
  1557. else
  1558. ll(i,j) = res
  1559. end if
  1560. end do
  1561. end do
  1562. !$OMP END PARALLEL
  1563. ! clear
  1564. deallocate( wwX )
  1565. case ( 'u' )
  1566. ! loop over (selection of) cells of target grid lli:
  1567. do j = j1, j2
  1568. do i = i1, i2+1
  1569. ! start with zero result:
  1570. res = 0.0
  1571. ! loop over points on east/west boundary in llX:
  1572. iX = i1X + (i-i1)*diX
  1573. do jX = j1X + (j-j1)*djX, j1X + (j-j1+1)*djX-1
  1574. ! add contribution of this llX cell:
  1575. select case ( combkey )
  1576. case ( 'sum' )
  1577. res = res + llX(iX,jX)
  1578. case ( 'aver', 'area-aver','mass-aver' )
  1579. res = res + llX(iX,jX)/real(djX)
  1580. case default
  1581. write (*,'("ERROR - unsupported combkey `",a,"`")') combkey
  1582. write (*,'("ERROR - nuv : `",a,"`")') nuv
  1583. write (*,'("ERROR - action : `",a,"`")') action
  1584. write (*,'("ERROR in ",a)') rname; status=1; return
  1585. end select
  1586. end do
  1587. ! fill result:
  1588. ll(i,j) = res
  1589. end do
  1590. end do
  1591. case ( 'v' )
  1592. ! loop over (selection of) cells of target grid lli:
  1593. do j = j1, j2+1
  1594. do i = i1, i2
  1595. ! start with zero result:
  1596. res = 0.0
  1597. ! loop over points on north/south boundary in llX:
  1598. jX = j1X + (j-j1)*djX
  1599. do iX = i1X + (i-i1)*diX, i1X + (i-i1+1)*diX-1
  1600. ! add contribution of this llX cell:
  1601. select case ( combkey )
  1602. case ( 'sum' )
  1603. res = res + llX(iX,jX)
  1604. case ( 'aver', 'area-aver','mass-aver' )
  1605. res = res + llX(iX,jX)/real(diX)
  1606. case default
  1607. write (*,'("ERROR - unsupported combkey `",a,"`")') combkey
  1608. write (*,'("ERROR - nuv : `",a,"`")') nuv
  1609. write (*,'("ERROR - action : `",a,"`")') action
  1610. write (*,'("ERROR in ",a)') rname; status=1; return
  1611. end select
  1612. end do
  1613. ! fill result:
  1614. ll(i,j) = res
  1615. end do
  1616. end do
  1617. case default
  1618. write (*,'("ERROR - unsupported nuv `",a,"`")') nuv
  1619. write (*,'("ERROR - action : `",a,"`")') action
  1620. write (*,'("ERROR in ",a)') rname; status=1; return
  1621. end select
  1622. !
  1623. ! * distribute
  1624. !
  1625. ! lliX defines a coarse resolution;
  1626. ! the cells from llX area [i1X,i2X] x [j1X,j2X]
  1627. ! should be sampled onto ll area [i1,i2] x [j1,j2]
  1628. !
  1629. ! Note: it is not possible to produce weighted distributions
  1630. ! to have different values within a coarse grid,
  1631. ! for example based on area, since what to do with a cell with
  1632. ! zero area ?
  1633. case ( 'distribute' )
  1634. ! resolution of fine cells (lli) in cell of lliX,
  1635. ! for example 3 x 2 :
  1636. di = (i2-i1+1) / (i2X-i1X+1)
  1637. dj = (j2-j1+1) / (j2X-j1X+1)
  1638. select case ( nuv )
  1639. case ( 'n' )
  1640. ! loop over (selection of) coarse cells in coarse source grid lliX:
  1641. do jX = j1X, j2X
  1642. do iX = i1X, i2X
  1643. ! loop over cells in fine target grid covered by coarse cell:
  1644. do j = j1 + (jX-j1X)*dj, j1 + (jX-j1X)*dj + dj-1
  1645. do i = i1 + (iX-i1X)*di, i1 + (iX-i1X)*di + di-1
  1646. ! copy or take fraction of coarse value:
  1647. select case ( combkey )
  1648. case ( 'sum' )
  1649. ! coarse cell is sum of finer; take fraction:
  1650. !ll(i,j) = llX(iX,jX) / real(di*dj)
  1651. ! coarse cell is sum of finer; take area fractions:
  1652. ll(i,j) = llX(iX,jX) * lli%area(j) / lliX%area(jX)
  1653. case ( 'aver', 'area-aver', 'weight','mass-aver')
  1654. ! coarse cell is aver of finer; take all the same:
  1655. ll(i,j) = llX(iX,jX)
  1656. case default
  1657. write (*,'("ERROR - unsupported combkey `",a,"`")') combkey
  1658. write (*,'("ERROR - nuv : `",a,"`")') nuv
  1659. write (*,'("ERROR - action : `",a,"`")') action
  1660. write (*,'("ERROR in ",a)') rname; status=1; return
  1661. end select
  1662. end do
  1663. end do
  1664. end do
  1665. end do
  1666. case ( 'u' )
  1667. !
  1668. ! coarse iaX ibX
  1669. ! | | |
  1670. ! | | | | | | | | |
  1671. ! fine ia ib
  1672. ! i
  1673. !
  1674. ! loop over (selection of) u boundaries of target grid lli:
  1675. do j = j1, j2
  1676. do i = i1, i2+1
  1677. ! coarse cell in j direction:
  1678. jX = j1X + floor(real(j-j1)/real(dj))
  1679. ! left and right bound in fine grid that are covered by coarse bound:
  1680. ia = i1 + floor(real(i-i1)/real(di))*di
  1681. ib = i1 + ceiling(real(i-i1)/real(di))*di
  1682. ! corresponding coarse boundaries:
  1683. iaX = i1X + (ia-i1)/di
  1684. ibX = i1X + (ib-i1)/di
  1685. ! interpolation in i direction of surounding lliX boundaries:
  1686. if ( iaX == ibX ) then
  1687. llX_ab = llX(iaX,jX)
  1688. else
  1689. llX_ab = llX(iaX,jX) * real(ib-i)/real(di) + &
  1690. llX(ibX,jX) * real(i-ia)/real(di)
  1691. end if
  1692. ! copy or take fraction of coarse value:
  1693. select case ( combkey )
  1694. case ( 'sum' )
  1695. ! coarse cell is sum of finer; take fraction:
  1696. ll(i,j) = llX_ab / real(dj)
  1697. case ( 'aver', 'area-aver','mass-aver' )
  1698. ! coarse cell is aver of finer; take all the same:
  1699. ll(i,j) = llX_ab
  1700. case default
  1701. write (*,'("ERROR - unsupported combkey `",a,"`")') combkey
  1702. write (*,'("ERROR - nuv : `",a,"`")') nuv
  1703. write (*,'("ERROR - action : `",a,"`")') action
  1704. write (*,'("ERROR in ",a)') rname; status=1; return
  1705. end select
  1706. end do
  1707. end do
  1708. case ( 'v' )
  1709. !
  1710. ! coarse fine
  1711. !
  1712. ! --
  1713. ! jaX -- -- ja
  1714. ! -- j
  1715. ! --
  1716. ! jbX -- -- jb
  1717. ! --
  1718. !
  1719. ! loop over (selection of) u boundaries of target grid lli:
  1720. do i = i1, i2
  1721. do j = j1, j2+1
  1722. ! coarse cell in i direction:
  1723. iX = i1X + floor(real(i-i1)/real(di))
  1724. ! left and right bound in fine grid that are covered by coarse bound:
  1725. ja = j1 + floor(real(j-j1)/real(dj))*dj
  1726. jb = j1 + ceiling(real(j-j1)/real(dj))*dj
  1727. ! corresponding coarse boundaries:
  1728. jaX = j1X + (ja-j1)/dj
  1729. jbX = j1X + (jb-j1)/dj
  1730. ! interpolation in j direction of surounding lliX boundaries:
  1731. if ( jaX == jbX ) then
  1732. llX_ab = llX(iX,jaX)
  1733. else
  1734. llX_ab = llX(iX,jaX) * real(jb-j)/real(dj) + &
  1735. llX(iX,jbX) * real(j-ja)/real(dj)
  1736. end if
  1737. ! copy or take fraction of coarse value:
  1738. select case ( combkey )
  1739. case ( 'sum' )
  1740. ! coarse cell is sum of finer; take fraction:
  1741. ll(i,j) = llX_ab / real(di)
  1742. case ( 'aver', 'area-aver','mass-aver' )
  1743. ! coarse cell is aver of finer; take all the same:
  1744. ll(i,j) = llX_ab
  1745. case default
  1746. write (*,'("ERROR - unsupported combkey `",a,"`")') combkey
  1747. write (*,'("ERROR - nuv : `",a,"`")') nuv
  1748. write (*,'("ERROR - action : `",a,"`")') action
  1749. write (*,'("ERROR in ",a)') rname; status=1; return
  1750. end select
  1751. end do
  1752. end do
  1753. case default
  1754. write (*,'("ERROR - unsupported nuv `",a,"`")') nuv
  1755. write (*,'("ERROR - action : `",a,"`")') action
  1756. write (*,'("ERROR in ",a)') rname; status=1; return
  1757. end select
  1758. !
  1759. ! * error ....
  1760. !
  1761. case default
  1762. write (*,'("ERROR - unsupported action `",a,"`")') action
  1763. write (*,'("ERROR - lliX lon : ",f7.2,f6.2,i4)') lliX%lon_deg(1), lliX%dlon_deg, lliX%nlon
  1764. write (*,'("ERROR - lat : ",f7.2,f6.2,i4)') lliX%lat_deg(1), lliX%dlat_deg, lliX%nlat
  1765. write (*,'("ERROR - lli lon : ",f7.2,f6.2,i4)') lli%lon_deg(1), lli%dlon_deg, lli%nlon
  1766. write (*,'("ERROR - lat : ",f7.2,f6.2,i4)') lli%lat_deg(1), lli%dlat_deg, lli%nlat
  1767. write (*,'("ERROR in ",a)') rname; status=1; return
  1768. end select
  1769. ! ok
  1770. if ( only_part_of_ll ) then
  1771. status = -1
  1772. else
  1773. status = 0
  1774. end if
  1775. end subroutine FillGrid
  1776. !
  1777. ! determine how lliX is related to lli:
  1778. ! i1, i2, j1, j2 : cell ranges in lli covered by cells of lliX
  1779. ! i1X, i2X, j1X, j2X : cell ranges in lliX covering cells of lliX
  1780. ! action : 'copy', 'combine'
  1781. !
  1782. subroutine Relate( lli , i1 , i2 , j1 , j2 , &
  1783. lliX, i1X, i2X, j1X, j2X, &
  1784. action, status )
  1785. ! --- in/out --------------------------------
  1786. type(TllGridInfo), intent(in) :: lli
  1787. integer, intent(out) :: i1, i2, j1, j2
  1788. type(TllGridInfo), intent(in) :: lliX
  1789. integer, intent(out) :: i1X, i2X, j1X, j2X
  1790. character(len=10), intent(out) :: action
  1791. integer, intent(out) :: status
  1792. ! --- const ---------------------------------
  1793. character(len=*), parameter :: name = mname//'/Relate'
  1794. ! --- local ---------------------------------
  1795. real :: dlon, dlonX
  1796. integer :: nlon, nlonX
  1797. real :: dlat, dlatX
  1798. integer :: nlat, nlatX
  1799. real :: west, westX
  1800. real :: east, eastX
  1801. real :: south, southX
  1802. real :: north, northX
  1803. real :: r, rX
  1804. logical :: only_part_of_ll
  1805. ! --- begin ---------------------------------
  1806. ! shorthands ...
  1807. dlon = lli%dlon_deg ; dlonX = lliX%dlon_deg
  1808. nlon = lli%nlon ; nlonX = lliX%nlon
  1809. dlat = lli%dlat_deg ; dlatX = lliX%dlat_deg
  1810. nlat = lli%nlat ; nlatX = lliX%nlat
  1811. west = lli%blon_deg(0) ; westX = lliX%blon_deg(0)
  1812. east = lli%blon_deg(nlon) ; eastX = lliX%blon_deg(nlonX)
  1813. south = lli%blat_deg(0) ; southX = lliX%blat_deg(0)
  1814. north = lli%blat_deg(nlat) ; northX = lliX%blat_deg(nlatX)
  1815. ! same spacing ?
  1816. if ( (dlonX == dlon) .and. (dlatX == dlat) ) then
  1817. ! cells from lliX should be copied to lli
  1818. action = 'copy'
  1819. else if ( (dlonX <= dlon) .and. (dlatX <= dlat) ) then
  1820. ! cells from lliX should be combined:
  1821. action = 'combine'
  1822. else if ( (dlonX >= dlon) .and. (dlatX >= dlat) ) then
  1823. ! distribute coarse cells of lliX over fine cells of lli:
  1824. action = 'distribute'
  1825. else
  1826. write (*,'("ERROR - do not know how to relate grids:")')
  1827. write (*,'("ERROR - lli dlon,dlat :",2f10.4)') dlon , dlat
  1828. write (*,'("ERROR - lliX dlon,dlat :",2f10.4)') dlonX, dlatX
  1829. write (*,'("ERROR in ",a)') name; status=1; return
  1830. end if
  1831. ! assume by default that all is filled
  1832. only_part_of_ll = .false.
  1833. ! west boundary
  1834. r = abs(west - westX) / dlon
  1835. rX = abs(west - westX) / dlonX
  1836. ! relate lliX to lli:
  1837. if ( (westX <= west) .and. (rX == nint(rX)) .and. (nint(rX)+1 <= nlonX) ) then
  1838. ! at this side, all of lli is covered by lliX:
  1839. i1 = 1
  1840. i1X = nint(rX) + 1
  1841. else if ( (westX > west) .and. (r == nint(r)) .and. (nint(r)+1 <= nlon) ) then
  1842. ! at this side, only a part of lli is covered by lliX:
  1843. i1 = nint(r) + 1
  1844. i1X = 1
  1845. only_part_of_ll = .true.
  1846. else
  1847. write (*,'("ERROR - do not know how to relate west bounds:")')
  1848. write (*,'("ERROR - lli bound, spacing, number :",2f10.4,i6)') west , dlon , nlon
  1849. write (*,'("ERROR - lliX bound, spacing, number :",2f10.4,i6)') westX, dlonX, nlonX
  1850. write (*,'("ERROR in ",a)') name; status=1; return
  1851. end if
  1852. ! east boundary
  1853. r = abs(east - eastX) / dlon
  1854. rX = abs(east - eastX) / dlonX
  1855. ! relate lliX to lli:
  1856. if ( (eastX >= east) .and. (rX == nint(rX)) .and. (nlonX-nint(rX) >= 1) ) then
  1857. ! at this side, all of lli is covered by lliX:
  1858. i2 = nlon
  1859. i2X = nlonX - nint(rX)
  1860. else if ( (eastX < east) .and. (r == nint(r)) .and. (nlon-nint(r) >= 1) ) then
  1861. ! at this side, only a part of lli is covered by lliX:
  1862. i2 = nlon - nint(r)
  1863. i2X = nlonX
  1864. only_part_of_ll = .true.
  1865. else
  1866. write (*,'("ERROR - do not know how to relate east bounds:")')
  1867. write (*,'("ERROR - lli bound, spacing, number :",2f10.4,i6)') east , dlon , nlon
  1868. write (*,'("ERROR - lliX bound, spacing, number :",2f10.4,i6)') eastX, dlonX, nlonX
  1869. write (*,'("ERROR in ",a)') name; status=1; return
  1870. end if
  1871. ! south boundary
  1872. r = abs(south - southX) / dlat
  1873. rX = abs(south - southX) / dlatX
  1874. ! relate lliX to lli:
  1875. if ( (southX <= south) .and. (rX == nint(rX)) .and. (nint(rX)+1 <= nlatX) ) then
  1876. ! at this side, all of lli is covered by lliX:
  1877. j1 = 1
  1878. j1X = nint(rX) + 1
  1879. else if ( (southX > south) .and. (r == nint(r)) .and. (nint(r)+1 <= nlat) ) then
  1880. ! at this side, only a part of lli is covered by lliX:
  1881. j1 = nint(r) + 1
  1882. j1X = 1
  1883. only_part_of_ll = .true.
  1884. else
  1885. write (*,'("ERROR - do not know how to relate south bounds:")')
  1886. write (*,'("ERROR - lli bound, spacing, number :",2f10.4,i6)') south , dlat , nlat
  1887. write (*,'("ERROR - lliX bound, spacing, number :",2f10.4,i6)') southX, dlatX, nlatX
  1888. write (*,'("ERROR in ",a)') name; status=1; return
  1889. end if
  1890. ! north boundary
  1891. r = abs(north - northX) / dlat
  1892. rX = abs(north - northX) / dlatX
  1893. ! relate lliX to lli:
  1894. if ( (northX >= north) .and. (rX == nint(rX)) .and. (nlatX-nint(rX) >= 1) ) then
  1895. ! at this side, all of lli is covered by lliX:
  1896. j2 = nlat
  1897. j2X = nlatX - nint(rX)
  1898. else if ( (northX < north) .and. (r == nint(r)) .and. (nlat-nint(r) >= 1) ) then
  1899. ! at this side, only a part of lli is covered by lliX:
  1900. j2 = nlat - nint(r)
  1901. j2X = nlatX
  1902. only_part_of_ll = .true.
  1903. else
  1904. write (*,'("ERROR - do not know how to relate north bounds:")')
  1905. write (*,'("ERROR - lli bound, spacing, number :",2f10.4,i6)') north , dlat , nlat
  1906. write (*,'("ERROR - lliX bound, spacing, number :",2f10.4,i6)') northX, dlatX, nlatX
  1907. write (*,'("ERROR in ",a)') name; status=1; return
  1908. end if
  1909. ! ok
  1910. if ( only_part_of_ll ) then
  1911. status = -1
  1912. else
  1913. status = 0
  1914. end if
  1915. end subroutine Relate
  1916. ! ========================================================
  1917. ! ===
  1918. ! === grid data operations
  1919. ! ===
  1920. ! ========================================================
  1921. ! subroutine Divergence_ll( lli, u, v, div )
  1922. !
  1923. ! ! --- in/out -------------------------------
  1924. !
  1925. ! type(TllGridInfo), intent(in) :: lli
  1926. ! type(TllGrid), intent(in) :: u, v
  1927. ! type(TllGrid), intent(out) :: div
  1928. !
  1929. ! ! --- local --------------------------------
  1930. !
  1931. ! integer :: i, j
  1932. ! integer :: im1, ip1
  1933. !
  1934. ! real :: wuim1(0:lme)
  1935. ! real :: wuip1(0:lme)
  1936. ! real :: wvjm1(0:lme)
  1937. ! real :: wvjp1(0:lme)
  1938. !
  1939. ! ! --- begin ---------------------------------
  1940. !
  1941. ! if ( lli%i1 == lli%im ) then
  1942. ! stop 'at least grid of 2 columns'
  1943. ! end if
  1944. !
  1945. ! if ( lli%j1 == lli%jm ) then
  1946. ! stop 'at least grid of 2 rows'
  1947. ! end if
  1948. !
  1949. ! stop 'circular ?'
  1950. !
  1951. ! do j = lli%j1, lli%jm
  1952. !
  1953. ! do i = lli%i1, lli%im
  1954. !
  1955. ! if ( j==lli%j1 .or. j==lli%jm ) then
  1956. !
  1957. ! div%d(i,j) = 0.0
  1958. !
  1959. ! else
  1960. !
  1961. ! if ( i==lli%i1 ) then
  1962. ! im1 = lli%im
  1963. ! ip1 = i + 1
  1964. ! else if ( i==lli%im ) then
  1965. ! im1 = lli%im
  1966. ! ip1 = i + 1
  1967. ! else
  1968. ! im1 = i - 1
  1969. ! ip1 = i + 1
  1970. ! end if
  1971. !
  1972. ! wuim1 = wu(im1,j,:)
  1973. ! wuip1 = wu(ip1,j,:)
  1974. !
  1975. ! wvjm1 = wv(i,j-1,:)
  1976. ! wvjp1 = wv(i,j+1,:)
  1977. !
  1978. ! dphi2 = eclon(2) - eclon(0)
  1979. ! dlat2 = eclat(j+1) - eclat(j-1)
  1980. !
  1981. ! qam(i,j,:) = ( wuip1 - wuim1 ) / (ceclat(j)*dphi2*ae) + &
  1982. ! ( wvjp1 - wvjm1 ) / (dlat2*ae)
  1983. !
  1984. ! end if
  1985. !
  1986. ! end do
  1987. ! end do
  1988. !
  1989. ! end subroutine divergence_uv
  1990. ! ==================================================================
  1991. !
  1992. ! mass flux balance
  1993. !
  1994. ! ==================================================================
  1995. !
  1996. ! (copied from TMPP;
  1997. ! code should be cleaned ..)
  1998. !
  1999. !
  2000. ! lli : fine grid definition
  2001. ! cgi : coarse grid covering fine grid.
  2002. !
  2003. ! On input, fine grid fields pu/pv/pw should match with
  2004. ! their coarse grid equivalents.
  2005. !
  2006. subroutine BalanceMassFluxes_sm( lli, lme, pu, pv, ww, dmdt, cgi, b_ec, status )
  2007. ! --- in/out -------------------------------------
  2008. type(TllGridInfo), intent(in) :: lli
  2009. integer, intent(in) :: lme
  2010. real,intent(inout) :: pu(0:lli%im,lli%jm,lme)
  2011. real,intent(inout) :: pv(lli%im,0:lli%jm,lme)
  2012. real, intent(in) :: ww(lli%im,lli%jm,lme)
  2013. real, intent(in) :: dmdt(lli%im,lli%jm)
  2014. type(TllGridInfo), intent(in) :: cgi
  2015. real, intent(in) :: b_ec(0:lme)
  2016. integer, intent(out) :: status
  2017. ! --- const -----------------------------
  2018. character(len=*), parameter :: rname = mname//'/BalanceMassFluxes_sm'
  2019. ! --- local ----------------------------------
  2020. integer :: refine_i, refine_j
  2021. integer :: cg_i1, cg_i2, cg_j1, cg_j2
  2022. integer :: ci, cj
  2023. integer :: fg_i1, fg_i2, fg_j1, fg_j2
  2024. integer :: fi, fj
  2025. integer :: i,j,l
  2026. integer :: ifail
  2027. real :: massc(lli%im,lli%jm)
  2028. real :: dm(lli%im,lli%jm)
  2029. real, allocatable :: cqu(:,:), cqv(:,:)
  2030. ! --- begin -----------------------------------
  2031. !print *, '<pascha_zoom>'
  2032. !print *, ' correct layers 1 to',lme,' with (eta dp/deta) and dps/dt '
  2033. ! determine refinement
  2034. call GetRefinement( cgi, lli, refine_i, refine_j, cg_i1, cg_i2, cg_j1, cg_j2, status )
  2035. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  2036. ! correction fluxes:
  2037. allocate( cqu(0:refine_i,refine_j) )
  2038. allocate( cqv(refine_i,0:refine_j) )
  2039. do l = 1, lme
  2040. ! total horizontal massconvergence
  2041. massc = 0.0
  2042. massc = massc + sum(pu(1:lli%im ,:,1:l),3) ! leaving through east
  2043. massc = massc - sum(pu(0:lli%im-1,:,1:l),3) ! enter through west
  2044. massc = massc + sum(pv(:,1:lli%jm ,1:l),3) ! leaving through north
  2045. massc = massc - sum(pv(:,0:lli%jm-1,1:l),3) ! enter through south
  2046. ! set difference
  2047. dm = (-massc) - ww(:,:,l) - b_ec(l)*dmdt
  2048. ! loop over cells in coarse grid covering fine grid:
  2049. do cj = cg_j1, cg_j2
  2050. do ci = cg_i1, cg_i2
  2051. fg_i1 = (ci-cg_i1)*refine_i + 1 ; fg_i2 = fg_i1-1 + refine_i
  2052. fg_j1 = (cj-cg_j1)*refine_j + 1 ; fg_j2 = fg_j1-1 + refine_j
  2053. ! do FFT
  2054. call SolvePoissonEq_zoom( refine_i, refine_j, &
  2055. dm(fg_i1:fg_i2,fg_j1:fg_j2), &
  2056. cqu, cqv, status )
  2057. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  2058. ! add corrections to original flux:
  2059. pu(fg_i1-1:fg_i2,fg_j1 :fg_j2,l) = pu(fg_i1-1:fg_i2,fg_j1 :fg_j2,l) + cqu
  2060. pv(fg_i1 :fg_i2,fg_j1-1:fg_j2,l) = pv(fg_i1 :fg_i2,fg_j1-1:fg_j2,l) + cqv
  2061. end do
  2062. end do
  2063. end do
  2064. ! done
  2065. deallocate( cqu )
  2066. deallocate( cqv )
  2067. ! ok
  2068. status = 0
  2069. end subroutine BalanceMassFluxes_sm
  2070. ! ***
  2071. !
  2072. ! pw : vertical flux in direction of increasing level
  2073. !
  2074. subroutine BalanceMassFluxes_m( lli, pu, pv, pw, dm_dt, cgi, dt_sec, status )
  2075. ! --- in/out -------------------------------------
  2076. type(TllGridInfo), intent(in) :: lli
  2077. real,intent(inout) :: pu(:,:,:)
  2078. real,intent(inout) :: pv(:,:,:)
  2079. real, intent(in) :: pw(:,:,:)
  2080. real, intent(in) :: dm_dt(:,:,:)
  2081. type(TllGridInfo), intent(in) :: cgi
  2082. real, intent(in) :: dt_sec
  2083. integer, intent(out) :: status
  2084. ! --- const -----------------------------
  2085. character(len=*), parameter :: rname = mname//'/BalanceMassFluxes_m'
  2086. ! --- local ----------------------------------
  2087. integer :: refine_i, refine_j
  2088. integer :: cg_i1, cg_i2, cg_j1, cg_j2
  2089. integer :: ci, cj
  2090. integer :: fg_i1, fg_i2, fg_j1, fg_j2
  2091. integer :: fi, fj
  2092. integer :: i,j,l
  2093. integer :: nlev
  2094. real :: massc(lli%im,lli%jm)
  2095. real :: dm(lli%im,lli%jm)
  2096. real, allocatable :: cqu(:,:), cqv(:,:)
  2097. ! --- begin -----------------------------------
  2098. ! number of levels
  2099. nlev = size(pu,3)
  2100. ! check ...
  2101. if ( (size(pu ,1) /= lli%nlon+1) .or. (size(pu ,2) /= lli%nlat ) .or. &
  2102. (size(pv ,1) /= lli%nlon ) .or. (size(pv ,2) /= lli%nlat+1) .or. &
  2103. (size(pw ,1) /= lli%nlon ) .or. (size(pw ,2) /= lli%nlat ) .or. &
  2104. (size(dm_dt,1) /= lli%nlon ) .or. (size(dm_dt,2) /= lli%nlat ) .or. &
  2105. (size(pv ,3) /= nlev) .or. (size(pw,3) /= nlev+1) .or. &
  2106. (size(dm_dt,3) /= nlev) ) then
  2107. write (*,'("ERROR - input arrays do not match with grid definition or levels:")')
  2108. write (*,'("ERROR - lli : ",i3," x ",i3)') lli%nlon, lli%nlat
  2109. write (*,'("ERROR - pu : ",i3," x ",i3," x ",i3)') shape(pu)
  2110. write (*,'("ERROR - pv : ",i3," x ",i3," x ",i3)') shape(pv)
  2111. write (*,'("ERROR - pw : ",i3," x ",i3," x ",i3)') shape(pw)
  2112. write (*,'("ERROR - dm_dt : ",i3," x ",i3," x ",i3)') shape(dm_dt)
  2113. write (*,'("ERROR in ",a)') rname; status=1; return
  2114. end if
  2115. ! determine refinement:
  2116. ! refine_i, refine_j
  2117. ! cg_i1, cg_i2, cg_j1, cg_j2 : cells in coarse grid cgi covering fine grid lli:
  2118. call GetRefinement( cgi, lli, refine_i, refine_j, cg_i1, cg_i2, cg_j1, cg_j2, status )
  2119. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  2120. !
  2121. ! determine how lliX (finer?) is related to lli:
  2122. ! i1, i2, j1, j2 : cell ranges in lli covered by cells of lliX
  2123. ! i1X, i2X, j1X, j2X : cell ranges in lliX covering cells of lliX
  2124. ! action : 'copy', 'combine' to map lliX to lli
  2125. !
  2126. !
  2127. !subroutine Relate( lli , i1 , i2 , j1 , j2 , &
  2128. ! lliX, i1X, i2X, j1X, j2X, &
  2129. ! action, status )
  2130. ! correction fluxes:
  2131. allocate( cqu(0:refine_i,refine_j) )
  2132. allocate( cqv(refine_i,0:refine_j) )
  2133. ! loop over levels
  2134. do l = 1, nlev
  2135. ! total horizontal mass convergence
  2136. massc = 0.0
  2137. massc = massc + pu(1:lli%im ,:,l) ! enter through west
  2138. massc = massc - pu(2:lli%im+1,:,l) ! leaving through east
  2139. massc = massc + pv(:,1:lli%jm ,l) ! enter through south
  2140. massc = massc - pv(:,2:lli%jm+1,l) ! leaving through north
  2141. massc = massc + pw(:,:,l ) ! enter through bottom
  2142. massc = massc - pw(:,:,l+1) ! leaving through top
  2143. ! set difference
  2144. dm = massc - dm_dt(:,:,l)
  2145. ! loop over cells in coarse grid covering fine grid:
  2146. do cj = cg_j1, cg_j2
  2147. do ci = cg_i1, cg_i2
  2148. fg_i1 = (ci-cg_i1)*refine_i + 1 ; fg_i2 = fg_i1-1 + refine_i
  2149. fg_j1 = (cj-cg_j1)*refine_j + 1 ; fg_j2 = fg_j1-1 + refine_j
  2150. ! do FFT
  2151. call SolvePoissonEq_zoom( refine_i, refine_j, &
  2152. dm(fg_i1:fg_i2,fg_j1:fg_j2), &
  2153. cqu, cqv, status )
  2154. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  2155. ! add corrections to original flux:
  2156. pu(fg_i1:fg_i2+1,fg_j1:fg_j2 ,l) = pu(fg_i1:fg_i2+1,fg_j1:fg_j2 ,l) + cqu
  2157. pv(fg_i1:fg_i2 ,fg_j1:fg_j2+1,l) = pv(fg_i1:fg_i2 ,fg_j1:fg_j2+1,l) + cqv
  2158. end do ! loop over coarse cells i
  2159. end do ! loop over coarse cells j
  2160. end do ! loop over levels
  2161. ! done
  2162. deallocate( cqu )
  2163. deallocate( cqv )
  2164. ! ok
  2165. status = 0
  2166. end subroutine BalanceMassFluxes_m
  2167. ! ***
  2168. subroutine CheckMassBalance( lli, pu, pv, sp1, sp2, dt, &
  2169. rms_max, mav_max, status )
  2170. use Binas, only : grav
  2171. ! --- in/out -------------------------------------
  2172. type(TllGridInfo), intent(in) :: lli
  2173. real,intent(inout) :: pu(:,:,:)
  2174. real,intent(inout) :: pv(:,:,:)
  2175. real, intent(in) :: sp1(:,:)
  2176. real, intent(in) :: sp2(:,:)
  2177. real, intent(in) :: dt
  2178. real, intent(in) :: rms_max
  2179. real, intent(in) :: mav_max
  2180. integer, intent(out) :: status
  2181. ! --- const -----------------------------
  2182. character(len=*), parameter :: rname = mname//'/CheckMassBalance'
  2183. ! --- local ----------------------------------
  2184. real :: dmuv_dt(lli%im,lli%jm)
  2185. real :: dmsp_dt(lli%im,lli%jm)
  2186. real :: dm_dt_diff(lli%im,lli%jm)
  2187. real :: rms_diff
  2188. real :: mav_diff
  2189. ! --- begin -----------------------------------
  2190. ! check ...
  2191. if ( (size(pu ,1) /= lli%nlon+1) .or. (size(pu ,2) /= lli%nlat ) .or. &
  2192. (size(pv ,1) /= lli%nlon ) .or. (size(pv ,2) /= lli%nlat+1) .or. &
  2193. (size(sp1,1) /= lli%nlon ) .or. (size(sp1,2) /= lli%nlat ) .or. &
  2194. (size(sp2,1) /= lli%nlon ) .or. (size(sp2,2) /= lli%nlat ) .or. &
  2195. (size(pu,3) /= size(pv,3)) ) then
  2196. write (*,'("ERROR - input arrays do not match with grid definition or levels:")')
  2197. write (*,'("ERROR - lli : ",i3," x ",i3)') lli%nlon, lli%nlat
  2198. write (*,'("ERROR - pu : ",i3," x ",i3," x ",i3)') shape(pu)
  2199. write (*,'("ERROR - pv : ",i3," x ",i3," x ",i3)') shape(pv)
  2200. write (*,'("ERROR - sp1 : ",i3," x ",i3)') shape(sp1)
  2201. write (*,'("ERROR - sp2 : ",i3," x ",i3)') shape(sp2)
  2202. write (*,'("ERROR in ",a)') rname; status=1; return
  2203. end if
  2204. ! total horizontal mass convergence (kg/s)
  2205. dmuv_dt = 0.0
  2206. dmuv_dt = dmuv_dt + sum(pu(1:lli%nlon ,:,:),3) ! enter through west
  2207. dmuv_dt = dmuv_dt - sum(pu(2:lli%nlon+1,:,:),3) ! leaving through east
  2208. dmuv_dt = dmuv_dt + sum(pv(:,1:lli%nlat ,:),3) ! enter through south
  2209. dmuv_dt = dmuv_dt - sum(pv(:,2:lli%nlat+1,:),3) ! leaving through north
  2210. ! convert from kg/s to Pa/s
  2211. dmuv_dt = dmuv_dt * grav ! Pa/s/m2
  2212. call AreaOper( lli, dmuv_dt, '/', 'm2', status ) ! Pa/s
  2213. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  2214. ! same according to surface pressures:
  2215. dmsp_dt = ( sp2 - sp1 ) / dt
  2216. ! imbalance relative to average surface pressure:
  2217. dm_dt_diff = ( dmuv_dt - dmsp_dt ) / ( (sp1+sp2)/2.0 )
  2218. ! statistics
  2219. rms_diff = sqrt( sum(dm_dt_diff**2) / size(dm_dt_diff) )
  2220. mav_diff = maxval( abs( dm_dt_diff ) )
  2221. ! check ...
  2222. if ( (rms_diff > rms_max) .or. (mav_diff > mav_max) ) then
  2223. write (*,'("ERROR - found relative surface pressure imbalance;")')
  2224. write (*,'("ERROR - difference [dmuv/dt]/[(sp1+sp2)/2] and [dsp/dt]/[(sp1+sp2)/2] :")')
  2225. write (*,'("ERROR - rms : ",es12.4," (",es12.4,")")') rms_diff, rms_max
  2226. write (*,'("ERROR - max abs. : ",es12.4," (",es12.4,")")') mav_diff, mav_max
  2227. write (*,'("ERROR in ",a)') rname; status=1; return
  2228. end if
  2229. ! ok
  2230. status = 0
  2231. end subroutine CheckMassBalance
  2232. ! ***
  2233. ! Return flux field (u,v) such that netto flux in a cell matches m:
  2234. !
  2235. ! du dv
  2236. ! -- + -- = M
  2237. ! dx dy
  2238. !
  2239. ! Fluxes at grid boundaries set to zero.
  2240. !
  2241. ! IN/OUT
  2242. ! input:
  2243. ! m(1:im,1:jm) : target netto flux
  2244. ! output:
  2245. ! u(0:im,1:jm) : u flux through cell boundaries
  2246. ! v(1:im,0:jm) : v vlux
  2247. !
  2248. !
  2249. ! +.......+.......+.......+.......+
  2250. ! : : : : :
  2251. ! : o : o : o : o :
  2252. ! : : : : :
  2253. ! jm +.......+---v---+---v---+---v---+---v---+.......+
  2254. ! : | | | | | :
  2255. ! : o u * u * u * u * u o :
  2256. ! : | | | | | :
  2257. ! : +.......+---v---+---v---+---v---+---v---+.......+
  2258. ! : | | | | | :
  2259. ! : o u * u * u * u * u o :
  2260. ! : | | | | | :
  2261. ! 1 +.......+---v---+---v---+---v---+---v---+.......+
  2262. ! : | | | | | :
  2263. ! : o u * u * u * u * u o :
  2264. ! : | | | | | :
  2265. ! j = 0 +.......+---v---+---v---+---v---+---v---+.......+
  2266. ! : : : : :
  2267. ! : o : o : o : o :
  2268. ! : : : : :
  2269. ! +.......+.......+.......+.......+
  2270. !
  2271. ! i= 0 1 2 .. im
  2272. !
  2273. ! * = m, Psi
  2274. ! o = Psi (periodic)
  2275. !
  2276. !
  2277. ! ALGORITHM
  2278. !
  2279. ! 1. Solve the Poisson equation:
  2280. !
  2281. ! d^2 d^2
  2282. ! ( ---- + ---- ) Psi = M
  2283. ! dx^2 dy^2
  2284. !
  2285. ! and return F = (u,v) = ( dPsi/dx, dPsi/dy )
  2286. ! The differential equations is actually a difference equation:
  2287. ! sum of fluxes is prescribed, we assume that the fluxes are differences
  2288. ! of a discrete potential Psi.
  2289. !
  2290. ! 2. The sollution is periodic in i and j.
  2291. ! To obtain the zero boundary conditions, substract the boundaries
  2292. ! from each row and column.
  2293. !
  2294. subroutine SolvePoissonEq_zoom( im, jm, m, u, v, status )
  2295. use Binas, only : pi
  2296. use grid_singleton, only : fftkind, fft
  2297. ! --- in/out -------------------------------------
  2298. integer, intent(in) :: im, jm
  2299. real, intent(in) :: m(im,jm)
  2300. real, intent(out) :: u(0:im,jm)
  2301. real, intent(out) :: v(im,0:jm)
  2302. integer, intent(out) :: status
  2303. ! --- const -----------------------------
  2304. character(len=*), parameter :: rname = mname//'/SolvePoissonEq_zoom'
  2305. ! --- local ----------------------------------
  2306. integer :: i,j
  2307. integer :: js, je
  2308. real :: fac(im,jm)
  2309. complex(fftkind) :: A(im,jm)
  2310. complex(fftkind) :: X(im,jm)
  2311. real :: psi(im,jm)
  2312. real :: row(im), col(jm)
  2313. ! --- begin -----------------------------------
  2314. ! precalculate cos/sin array fac
  2315. !$OMP PARALLEL &
  2316. !$OMP default (none) &
  2317. !$OMP shared (im, jm, fac) &
  2318. !$OMP private (i, j, js, je)
  2319. do j = 1, jm
  2320. do i=1,im
  2321. fac(i,j) = 2.0*(cos(2*pi*(i-1)/im)+cos(2*pi*(j-1)/jm)-2.)
  2322. end do
  2323. end do
  2324. !$OMP END PARALLEL
  2325. fac(1,1) = 1.0 !to avoid division by zero
  2326. ! do FFT
  2327. A = cmplx( m, 0.0 )
  2328. X = fft( A, stat=status )
  2329. if ( status /= 0 ) then
  2330. write (*,'("ERROR - from first fft; stat = ",i6)') status
  2331. write (*,'("ERROR in ",a)') rname; status=1; return
  2332. end if
  2333. ! compute fourier coefficients of correction potential
  2334. A = cmplx( real(X)/fac, -aimag(X)/fac )
  2335. A(1,1) = (0.0,0.0)
  2336. ! get correction potential
  2337. X = fft( A, stat=status )
  2338. if ( status /= 0 ) then
  2339. write (*,'("ERROR - from second fft; stat = ",i6)') status
  2340. write (*,'("ERROR in ",a)') rname; status=1; return
  2341. end if
  2342. psi = real( X )
  2343. ! correction flux in lon direction:
  2344. do j = 1, jm
  2345. !u(:,j) = (/ psi(1,j)-psi(im,j), psi(2:im,j)-psi(1:im-1,j), psi(1,j)-psi(im,j) /)
  2346. u(0 ,j) = psi(1 ,j)-psi(im ,j)
  2347. u(1:im-1,j) = psi(2:im,j)-psi(1:im-1,j)
  2348. u(im ,j) = psi(1 ,j)-psi(im ,j)
  2349. end do
  2350. ! substract flux over east/west boundary:
  2351. col = u(0,:)
  2352. do i = 0, im
  2353. u(i,:) = u(i,:) - col
  2354. end do
  2355. ! correction flux in lat direction;
  2356. do i = 1, im
  2357. !v(i,:) = (/ psi(i,1)-psi(i,jm), psi(i,2:jm)-psi(i,1:jm-1), psi(i,1)-psi(i,jm) /)
  2358. v(i,0 ) = psi(i,1 ) - psi(i,jm )
  2359. v(i,1:jm-1) = psi(i,2:jm) - psi(i,1:jm-1)
  2360. v(i,jm ) = psi(i,1 ) - psi(i,jm )
  2361. end do
  2362. ! substract flux over north/west boundary:
  2363. row = v(:,0)
  2364. do j = 0, jm
  2365. v(:,j) = v(:,j) - row
  2366. end do
  2367. ! Correction for flux over poles.
  2368. ! The equation is solved with a 2D Fourrier transform, which
  2369. ! assumes that the grid is part of an into infinity periodical
  2370. ! extended grid; the solution is thus periodic from east into west
  2371. ! but also from southpole into north pole (donut configuration).
  2372. ! To obtain a zero flux over the poles, first the orginal flux over
  2373. ! the poles is computed:
  2374. ! vpole = psi(:,1) - psi(:,jm)
  2375. ! This flux is substracted from each of the lat fluxes:
  2376. ! v(:,j) := v(:,j) - vpole
  2377. ! In this way, the netto mass convergence is maintained,
  2378. ! but (u,v) is not a potential flow anymore!
  2379. ! We will not bother about this small 'error', since we are dealing
  2380. ! with a correction to a much larger error.
  2381. end subroutine SolvePoissonEq_zoom
  2382. ! =================================================================
  2383. ! ===
  2384. ! === equivalent latitudes
  2385. ! ===
  2386. ! =================================================================
  2387. !
  2388. ! eqvlatb(1:jm+1) : bounds of eqv.lat. bins (/-90.0,..,90.0/)
  2389. !
  2390. ! inds(im,jm) : cell (i,j) is in eqvlatb( inds(i,j), inds(i,j)+1 )
  2391. !
  2392. subroutine llgrid_EquivLat( lli, ff, eqvlatb, inds )
  2393. use Binas, only : deg2rad, pi
  2394. use Num, only : Interval, Interp_Lin
  2395. use grid_tools, only : ll_area
  2396. ! --- in/out -----------------------------
  2397. type(TllGridInfo), intent(in) :: lli
  2398. real, intent(in) :: ff(:,:)
  2399. real, intent(out) :: eqvlatb(:)
  2400. integer, intent(out) :: inds(:,:)
  2401. integer :: status
  2402. ! --- const ------------------------------
  2403. character(len=*), parameter :: rname = mname//'/llgrid_EquivLat'
  2404. ! --- local ------------------------------
  2405. real :: fmin, fmax, f
  2406. integer :: nbins
  2407. real, allocatable :: bin_inds(:)
  2408. real, allocatable :: bin_fval(:)
  2409. real, allocatable :: bin_area(:)
  2410. real, allocatable :: bin_areacum(:)
  2411. real :: indf
  2412. real :: area_tot
  2413. real :: area_glob, area_south
  2414. integer :: ilast
  2415. integer :: i, j
  2416. ! --- begin ------------------------------
  2417. !if ( (maxval(lli%blon_deg)-minval(lli%blon_deg) < 360.0) .or. &
  2418. ! (maxval(lli%blat_deg)-minval(lli%blat_deg) < 180.0) ) then
  2419. ! write (*,'("ERROR - equivalent lats for global grids only yet")')
  2420. ! write (*,'("ERROR - lons : ",f8.2,"-",f8.2)') minval(lli%blon_deg), maxval(lli%blon_deg)
  2421. ! write (*,'("ERROR - lats : ",f8.2,"-",f8.2)') minval(lli%blat_deg), maxval(lli%blat_deg)
  2422. ! write (*,'("ERROR in ",a)') name; stop
  2423. !end if
  2424. call Check( lli, 'n', ff, status )
  2425. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; stop; end if
  2426. call Check( lli, 'n', inds, status )
  2427. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; stop; end if
  2428. ! for the moment ...
  2429. nbins = lli%jm
  2430. if ( size(eqvlatb) /= nbins+1 ) then
  2431. write (*,'("ERROR - routine returns jm+1 bounds of jm eqv.lat bins:")')
  2432. write (*,'("ERROR - size(eqvlatb) : ",i6)') size(eqvlatb)
  2433. write (*,'("ERROR - nbins+1 (=jm+1) : ",i6)') nbins+1
  2434. write (*,'("ERROR in ",a)') rname; stop
  2435. end if
  2436. ! number of bins, field values, total area
  2437. allocate( bin_inds(nbins) )
  2438. allocate( bin_fval(nbins) )
  2439. allocate( bin_area(nbins) )
  2440. allocate( bin_areacum(nbins) )
  2441. ! linear ax of values in field:
  2442. fmin = minval(ff)
  2443. fmax = maxval(ff)
  2444. do j = 1, nbins
  2445. bin_inds(j) = j*1.0
  2446. bin_fval(j) = fmin*(nbins-j)/real(nbins-1) + fmax*(j-1)/real(nbins-1)
  2447. end do
  2448. ! add weights for each cell to corresponding bin:
  2449. ilast = 0
  2450. bin_area = 0.0
  2451. do i = 1, lli%im
  2452. do j = 1, lli%jm
  2453. ! search index in bins:
  2454. call Interp_Lin( bin_fval, bin_inds, ff(i,j), indf, ilast, status )
  2455. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; stop; end if
  2456. ! store index:
  2457. inds(i,j) = nint(indf)
  2458. ! add area to corresponding bin:
  2459. bin_area(inds(i,j)) = bin_area(inds(i,j)) + lli%area(j) ! rad^2
  2460. end do
  2461. end do
  2462. ! total area:
  2463. area_tot = lli%im * sum(lli%area)
  2464. ! check ...
  2465. if ( (sum(bin_area)-area_tot)/area_tot > 0.01 ) then
  2466. write (*,'("ERROR - total area and areas in bins do not match:")')
  2467. write (*,'("ERROR - total area : ",es12.2)') area_tot
  2468. write (*,'("ERROR - collected area : ",es12.2)') sum(bin_area)
  2469. write (*,'("ERROR in ",a)') rname; stop
  2470. end if
  2471. ! cumulative bin area
  2472. bin_areacum(1) = bin_area(1)
  2473. do j = 2, nbins
  2474. bin_areacum(j) = bin_areacum(j-1) + bin_area(j)
  2475. end do
  2476. !
  2477. ! blat(nlat) ------------------------------- 90
  2478. ! | | \
  2479. ! |----------| |
  2480. ! |//////////| |
  2481. ! |----------| | glob
  2482. ! | | \ |
  2483. ! | | | south |
  2484. ! | | / /
  2485. ! blat(nlat) ------------------------------- -90
  2486. ! blon(0) blon(nlon)
  2487. ! global area and southern part (all in rad!)
  2488. area_glob = ll_area( 0.0, lli%blon(lli%nlon)-lli%blon(0), -0.5*pi, 0.5*pi ) ! rad^2
  2489. area_south = ll_area( 0.0, lli%blon(lli%nlon)-lli%blon(0), -0.5*pi, lli%blat(0) ) ! rad^2
  2490. ! convert cumulative ax to (part of) [-1,1]
  2491. bin_areacum = (area_south + bin_areacum ) / area_glob ! [ 0,1]
  2492. bin_areacum = -1.0 + 2.0*bin_areacum ! [-1,1]
  2493. where ( bin_areacum < -1.0 ) bin_areacum = -1.0
  2494. where ( bin_areacum > 1.0 ) bin_areacum = 1.0
  2495. ! convert to latitude:
  2496. eqvlatb(1) = lli%blat_deg(0) ! deg
  2497. do j = 1, nbins
  2498. eqvlatb(j+1) = asin( bin_areacum(j) ) / deg2rad
  2499. end do
  2500. !print *, 0, area_south/area_glob, eqvlatb(1)
  2501. !do j=1,nbins
  2502. ! print *, j, bin_areacum(j), eqvlatb(j+1)
  2503. !end do
  2504. !stop
  2505. ! done
  2506. deallocate( bin_inds )
  2507. deallocate( bin_fval )
  2508. deallocate( bin_area )
  2509. deallocate( bin_areacum )
  2510. end subroutine llgrid_EquivLat
  2511. !
  2512. ! eqvlat1, eqvlat2 : lower and upper bound of eqv.lat.
  2513. !
  2514. subroutine llgrid_EquivLat_sort( lli, ff, eqvlatb1, eqvlatb2, status )
  2515. use Binas, only : deg2rad, pi
  2516. use Num, only : Sort
  2517. use grid_tools, only : ll_area
  2518. ! --- in/out -----------------------------
  2519. type(TllGridInfo), intent(in) :: lli
  2520. real, intent(in) :: ff(:,:)
  2521. real, intent(out) :: eqvlatb1(:,:)
  2522. real, intent(out) :: eqvlatb2(:,:)
  2523. integer, intent(out) :: status
  2524. ! --- const ------------------------------
  2525. character(len=*), parameter :: rname = mname//'/llgrid_EquivLat_sort'
  2526. ! --- local ------------------------------
  2527. real :: ffsort(lli%nlon,lli%nlat)
  2528. integer :: ijsort(lli%nlon,lli%nlat,2)
  2529. real :: areacum
  2530. real :: bin_areacum(lli%nlon,lli%nlat,2)
  2531. real :: area_tot
  2532. real :: area_glob, area_south
  2533. integer :: i, j
  2534. integer :: is, js
  2535. ! --- begin ------------------------------
  2536. ! check input
  2537. call Check( lli, 'n', ff, status )
  2538. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  2539. ! sort input array
  2540. call Sort( ff, ffsort, ijsort, status )
  2541. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  2542. ! loop over sorted values to compute cumulative areas:
  2543. areacum = 0.0
  2544. do js = 1, lli%nlat
  2545. do is = 1, lli%nlon
  2546. ! original indices
  2547. i = ijsort(is,js,1)
  2548. j = ijsort(is,js,2)
  2549. ! store lower cumulative area:
  2550. bin_areacum(i,j,1) = areacum ! rad^2
  2551. ! add area of this cell:
  2552. areacum = areacum + lli%area(j) ! rad^2
  2553. ! store upper cumulative area:
  2554. bin_areacum(i,j,2) = areacum ! rad^2
  2555. end do
  2556. end do
  2557. ! total area:
  2558. area_tot = lli%nlon * sum(lli%area)
  2559. ! check ...
  2560. if ( (bin_areacum(lli%nlon,lli%nlat,2)-area_tot)/area_tot > 0.01 ) then
  2561. write (*,'("ERROR - total area and areas in bins do not match:")')
  2562. write (*,'("ERROR - total area : ",es12.2)') area_tot
  2563. write (*,'("ERROR - collected area : ",es12.2)') bin_areacum(lli%nlon,lli%nlat,2)
  2564. write (*,'("ERROR in ",a)') rname; status=1; return
  2565. end if
  2566. !
  2567. ! blat(nlat) ------------------------------- 90
  2568. ! | | \
  2569. ! |----------| |
  2570. ! |//////////| |
  2571. ! |----------| | glob
  2572. ! | | \ |
  2573. ! | | | south |
  2574. ! | | / /
  2575. ! blat(nlat) ------------------------------- -90
  2576. ! blon(0) blon(nlon)
  2577. ! global area and southern part (all in rad!)
  2578. area_glob = ll_area( 0.0, lli%blon(lli%nlon)-lli%blon(0), -0.5*pi, 0.5*pi ) ! rad^2
  2579. area_south = ll_area( 0.0, lli%blon(lli%nlon)-lli%blon(0), -0.5*pi, lli%blat(0) ) ! rad^2
  2580. ! convert cumulative ax to (part of) [-1,1]
  2581. bin_areacum = (area_south + bin_areacum ) / area_glob ! [ 0,1]
  2582. bin_areacum = -1.0 + 2.0*bin_areacum ! [-1,1]
  2583. ! adhoc truncations ...
  2584. where ( bin_areacum < -1.0 ) bin_areacum = -1.0
  2585. where ( bin_areacum > 1.0 ) bin_areacum = 1.0
  2586. ! convert to latitude:
  2587. eqvlatb1 = asin( bin_areacum(:,:,1) ) / deg2rad
  2588. eqvlatb2 = asin( bin_areacum(:,:,2) ) / deg2rad
  2589. ! ok
  2590. status = 0
  2591. end subroutine llgrid_EquivLat_sort
  2592. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2593. ! ~~~
  2594. ! ~~~ region box
  2595. ! ~~~
  2596. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2597. subroutine llreg_Init( llreg, west_deg, east_deg, south_deg, north_deg, status )
  2598. use Binas, only : deg2rad
  2599. ! --- in/out --------------------------------
  2600. type(TllRegion), intent(inout) :: llreg
  2601. real, intent(in) :: west_deg, east_deg, south_deg, north_deg
  2602. integer, intent(out) :: status
  2603. ! --- const --------------------------------
  2604. character(len=*), parameter :: rname = 'llreg_Init'
  2605. ! --- begin --------------------------------
  2606. ! store region boundaries:
  2607. llreg%west_deg = west_deg
  2608. llreg%east_deg = east_deg
  2609. llreg%south_deg = south_deg
  2610. llreg%north_deg = north_deg
  2611. ! idem in radians:
  2612. llreg%west = west_deg * deg2rad
  2613. llreg%east = east_deg * deg2rad
  2614. llreg%south = south_deg * deg2rad
  2615. llreg%north = north_deg * deg2rad
  2616. ! ok
  2617. status = 0
  2618. end subroutine llreg_Init
  2619. ! ***
  2620. subroutine llreg_Done( llreg, status )
  2621. ! --- in/out --------------------------------
  2622. type(TllRegion), intent(inout) :: llreg
  2623. integer, intent(out) :: status
  2624. ! --- const --------------------------------
  2625. character(len=*), parameter :: rname = 'llreg_Done'
  2626. ! --- begin --------------------------------
  2627. ! nothing to be done
  2628. ! ok
  2629. status = 0
  2630. end subroutine llreg_Done
  2631. ! ***
  2632. subroutine llreg_Region_Apply_Factor_2d( lli, x, llreg, fac, status, complement )
  2633. use grid_tools, only : ll_area_frac
  2634. ! --- in/out ---------------------------
  2635. type(TllGridInfo), intent(in) :: lli
  2636. real, intent(inout) :: x(:,:)
  2637. type(TllRegion), intent(in) :: llreg
  2638. real, intent(in) :: fac
  2639. integer, intent(out) :: status
  2640. logical, intent(in), optional :: complement
  2641. ! --- const --------------------------------
  2642. character(len=*), parameter :: rname = 'llreg_Region_Apply_Factor_2d'
  2643. ! --- local --------------------------------
  2644. logical :: do_complement
  2645. real :: frac
  2646. integer :: i, j
  2647. ! --- begin --------------------------------
  2648. ! apply to interior of region or to complement ?
  2649. do_complement = .false.
  2650. if ( present(complement) ) do_complement = complement
  2651. ! check ...
  2652. call Check( lli, 'n', x, status )
  2653. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  2654. ! loop over all cells in grid:
  2655. do j = 1, lli%nlat
  2656. do i = 1, lli%nlon
  2657. ! fraction of grid cell covered by region;
  2658. ! input to routine in radians:
  2659. frac = ll_area_frac( lli%blon(i-1), lli%blon(i), lli%blat(j-1), lli%blat(j), &
  2660. llreg%west , llreg%east , llreg%south , llreg%north )
  2661. ! apply to interior or to complement ?
  2662. if ( do_complement ) then
  2663. ! apply factor if cell is (partly) outside region box:
  2664. if ( frac < 1.0 ) then
  2665. x(i,j) = fac * ( 1.0 - frac ) * x(i,j)
  2666. end if
  2667. else
  2668. ! apply factor if cell is (partly) inside region box:
  2669. if ( frac > 0.0 ) then
  2670. x(i,j) = fac * frac * x(i,j)
  2671. end if
  2672. end if
  2673. end do ! i
  2674. end do ! j
  2675. ! ok
  2676. status = 0
  2677. end subroutine llreg_Region_Apply_Factor_2d
  2678. ! ***
  2679. subroutine llreg_Region_Apply_Factor_3d( lli, x, llreg, fac, status, complement )
  2680. use grid_tools, only : ll_area_frac
  2681. ! --- in/out ---------------------------
  2682. type(TllGridInfo), intent(in) :: lli
  2683. real, intent(inout) :: x(:,:,:)
  2684. type(TllRegion), intent(in) :: llreg
  2685. real, intent(in) :: fac
  2686. integer, intent(out) :: status
  2687. logical, intent(in), optional :: complement
  2688. ! --- const --------------------------------
  2689. character(len=*), parameter :: rname = 'llreg_Region_Apply_Factor_3d'
  2690. ! --- local --------------------------------
  2691. logical :: do_complement
  2692. real :: frac
  2693. integer :: i, j
  2694. ! --- begin --------------------------------
  2695. ! apply to interior of region or to complement ?
  2696. do_complement = .false.
  2697. if ( present(complement) ) do_complement = complement
  2698. ! check ...
  2699. call Check( lli, 'n', x(:,:,1), status )
  2700. if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
  2701. ! loop over all cells in grid:
  2702. do j = 1, lli%nlat
  2703. do i = 1, lli%nlon
  2704. ! fraction of grid cell covered by region;
  2705. ! input to routine in radians:
  2706. frac = ll_area_frac( lli%blon(i-1), lli%blon(i), lli%blat(j-1), lli%blat(j), &
  2707. llreg%west , llreg%east , llreg%south , llreg%north )
  2708. ! apply to interior or to complement ?
  2709. if ( do_complement ) then
  2710. ! apply factor if cell is (partly) outside region box:
  2711. if ( frac < 1.0 ) then
  2712. x(i,j,:) = fac * ( 1.0 - frac ) * x(i,j,:)
  2713. end if
  2714. else
  2715. ! apply factor if cell is (partly) inside region box:
  2716. if ( frac > 0.0 ) then
  2717. x(i,j,:) = fac * frac * x(i,j,:)
  2718. end if
  2719. end if
  2720. end do ! i
  2721. end do ! j
  2722. ! ok
  2723. status = 0
  2724. end subroutine llreg_Region_Apply_Factor_3d
  2725. end module grid_type_ll