12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824 |
- !
- ! NAME
- ! grid_interpol - from sh/gg/ll to gg/ll
- !
- ! HISTORY
- ! v1.?
- ! Original
- ! v1.1
- ! Bug fixed: southpole in gg -> ll
- !
- module Grid_Interpol
- implicit none
-
- ! --- in/out ------------------------------
-
- private
-
- public :: Interpol
- public :: NewInterpol
- public :: InterpolMask
- public :: Aver
- public :: IntArea
- public :: IntLat, IntLon
-
- !public :: ShTruncation, ShRefinement
- public :: Tgg2llFracs, Tll2ggFracs, Init, Done, FracSum
-
- ! --- const ----------------------------------
- character(len=*), parameter :: mname = 'grid_interpol'
- ! --- types -------------------------------
-
- type Tgg2llFracs
- integer :: nlon, nlat, np
- integer, pointer :: ncov(:,:)
- integer, pointer :: indx(:,:,:)
- real, pointer :: frac(:,:,:)
- real, pointer :: A_gg(:) ! m2
- real, pointer :: A_ll(:,:) ! m2
- end type Tgg2llFracs
-
-
- type Tll2ggFracs
- integer :: nlon, nlat, np
- integer, pointer :: ncov(:) ! (1:np)
- integer, pointer :: ii(:,:) ! (1:np,1:max(ncov(k)))
- integer, pointer :: jj(:,:) ! (1:np,1:max(ncov(k)))
- real, pointer :: ff(:,:) ! (1:np,1:max(ncov(k)))
- real, pointer :: A_gg(:) ! m2
- real, pointer :: A_ll(:,:) ! m2
- end type Tll2ggFracs
-
- ! --- interfaces --------------------------
-
- interface Init
- module procedure gg2ll_Init
- module procedure ll2gg_Init
- end interface
-
- interface Done
- module procedure gg2ll_Done
- module procedure ll2gg_Done
- end interface
-
- interface FracSum
- module procedure gg2ll_FracSum
- module procedure ll2gg_FracSum
- end interface
-
- interface Interpol
- module procedure Interpol_sh_gg
- module procedure Interpol_shi_gg
- module procedure Interpol_sh_ll
- module procedure Interpol_shi_ll
- module procedure Interpol_gg_ll
- module procedure Interpol_ll_gg
- end interface
- interface NewInterpol
- module procedure NewInterpol_shi_gg
- end interface
- interface Aver
- module procedure Aver_gg_ll
- module procedure Aver_sh_ll
- end interface
- interface IntArea
- module procedure IntArea_sh_ll_f
- module procedure IntArea_shi_ll_f
- module procedure IntArea_sh_ll_fgh
- module procedure IntArea_shi_ll_fgh
- module procedure IntArea_sh_ll_fh
- module procedure IntArea_shi_ll_fh
- end interface
- interface IntLat
- module procedure IntLat_sh_ll
- module procedure IntLat_shi_ll
- end interface
-
- interface IntLon
- module procedure IntLon_sh_ll
- module procedure IntLon_shi_ll
- end interface
-
-
-
- contains
-
- ! =========================================================
- ! ===
- ! === evaluate spectral fields
- ! ===
- ! =========================================================
-
-
- ! from spectral to reduced gausian grid
-
-
- subroutine Interpol_sh_gg( sh, ggi, gg, status )
-
- use Grid_Type_sh, only : TshGrid, Eval_Lons, Check
- use Grid_Type_gg, only : TggGridInfo, Check
-
- ! --- in/out ----------------------------------
-
- type(TshGrid), intent(in) :: sh
- type(TggGridInfo), intent(in) :: ggi
- real, intent(out) :: gg(ggi%np)
- integer, intent(out) :: status
-
- ! --- const --------------------------------
-
- character(len=*), parameter :: rname = mname//'/Interpol_sh_gg'
-
- ! --- local -----------------------------------
-
- !real, allocatable :: llgrid(:,:)
- real, allocatable :: llgrid(:)
- integer :: nlon
- integer :: jn !, js
-
- ! --- begin -----------------------------------
-
- call Check( sh )
- call Check( ggi, gg )
-
- !allocate( llgrid(maxval(ggi%nlon),2) )
- allocate( llgrid(maxval(ggi%nlon)) )
- ! northern rows:
- !do jn = 1, ggi%nlat/2
- do jn = 1, ggi%nlat
-
- ! southern row:
- !js = ggi%nlat + 1 - jn
-
- ! only if one of the rows is marked:
- !if ( ggi%latflag(jn) .or. ggi%latflag(js) ) then
- if ( ggi%latflag(jn) ) then
-
- nlon = ggi%nlon(jn)
- !call Eval_Lons( llgrid(1:nlon,1:2), sh, ggi%lat(jn), nlon, 0.0, nlon )
- !gg(ggi%i1(jn):ggi%im(jn)) = llgrid(1:nlon,1)
- !gg(ggi%i1(js):ggi%im(js)) = llgrid(1:nlon,2)
- call Eval_Lons( llgrid(1:nlon), sh, ggi%lat(jn), nlon, 0.0, nlon, status )
- gg(ggi%i1(jn):ggi%im(jn)) = llgrid(1:nlon)
- end if
-
- end do
-
- deallocate( llgrid )
-
- end subroutine Interpol_sh_gg
- ! *
-
- subroutine NewInterpol_shi_gg( shi, shc, ggi, gg, status )
-
- use Grid_Type_sh, only : TshGridInfo, Check, Eval_Lons
- use Grid_Type_sh, only : TshGrid, Init, Done, Set
- use Grid_Type_gg, only : TggGridInfo, Check
-
- ! --- in/out ----------------------------------
-
- type(TshGridInfo), intent(in) :: shi
- complex, intent(in) :: shc(shi%np)
- type(TggGridInfo), intent(in) :: ggi
- real, intent(out) :: gg(ggi%np)
- integer, intent(out) :: status
-
- ! --- const --------------------------------
-
- character(len=*), parameter :: rname = mname//'/NewInterpol_shi_gg'
-
- ! --- local -----------------------------------
-
- real, pointer :: llgrid(:)
- integer :: nlon
- integer :: jn !, js
-
- ! --- begin -----------------------------------
-
- allocate( llgrid(maxval(ggi%nlon)) )
- ! northern rows:
- !do jn = 1, ggi%nlat/2
- do jn = 1, ggi%nlat
-
- ! southern row:
- !js = ggi%nlat + 1 - jn
-
- ! only if one of the rows is marked:
- !if ( ggi%latflag(jn) .or. ggi%latflag(js) ) then
- if ( ggi%latflag(jn) ) then
-
- nlon = ggi%nlon(jn)
- !call Eval_Lons( llgrid(1:nlon,1:2), sh, ggi%lat(jn), nlon, 0.0, nlon )
- !gg(ggi%i1(jn):ggi%im(jn)) = llgrid(1:nlon,1)
- !gg(ggi%i1(js):ggi%im(js)) = llgrid(1:nlon,2)
- call Eval_Lons( shi, shc, ggi%lat(jn), nlon, 0.0, nlon, llgrid(1:nlon), status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- gg(ggi%i1(jn):ggi%im(jn)) = llgrid(1:nlon)
- end if
-
- end do
- ! done
- deallocate( llgrid )
-
- ! ok
- status = 0
-
- end subroutine NewInterpol_shi_gg
- ! *
-
-
- subroutine Interpol_shi_gg( shi, shc, ggi, gg, status )
-
- use Grid_Type_sh, only : TshGridInfo, Check, Eval_Lons
- use Grid_Type_sh, only : TshGrid, Init, Done, Set
- use Grid_Type_gg, only : TggGridInfo, Check
-
- ! --- in/out ----------------------------------
-
- type(TshGridInfo), intent(in) :: shi
- complex, intent(in) :: shc(shi%np)
- type(TggGridInfo), intent(in) :: ggi
- real, intent(out) :: gg(ggi%np)
- integer, intent(out) :: status
-
- ! --- const --------------------------------
-
- character(len=*), parameter :: rname = mname//'/Interpol_shi_gg'
-
- ! --- local -----------------------------------
-
- type(TshGrid) :: sh
-
- !real, allocatable :: llgrid(:,:)
- real, allocatable :: llgrid(:)
- integer :: nlon
- integer :: jn !, js
-
- ! --- begin -----------------------------------
-
- ! store input in old type grid:
- call Init( sh )
- call Set( sh, shi%T, shc )
- !allocate( llgrid(maxval(ggi%nlon),2) )
- allocate( llgrid(maxval(ggi%nlon)) )
- ! northern rows:
- !do jn = 1, ggi%nlat/2
- do jn = 1, ggi%nlat
-
- ! southern row:
- !js = ggi%nlat + 1 - jn
-
- ! only if one of the rows is marked:
- !if ( ggi%latflag(jn) .or. ggi%latflag(js) ) then
- if ( ggi%latflag(jn) ) then
-
- nlon = ggi%nlon(jn)
- !call Eval_Lons( llgrid(1:nlon,1:2), sh, ggi%lat(jn), nlon, 0.0, nlon )
- !gg(ggi%i1(jn):ggi%im(jn)) = llgrid(1:nlon,1)
- !gg(ggi%i1(js):ggi%im(js)) = llgrid(1:nlon,2)
- call Eval_Lons( llgrid(1:nlon), sh, ggi%lat(jn), nlon, 0.0, nlon, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- gg(ggi%i1(jn):ggi%im(jn)) = llgrid(1:nlon)
- end if
-
- end do
- ! done
- deallocate( llgrid )
- call Done( sh )
-
- ! ok
- status = 0
-
- end subroutine Interpol_shi_gg
-
- ! ===
-
-
- ! from sh to ll
-
- subroutine Interpol_sh_ll( sh, lli, ll, status )
-
- use Grid_Type_sh, only : TshGrid, Eval_Lons, Check
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -------------------------------
-
- type(TshGrid), intent(in) :: sh
- type(TllGridInfo), intent(in) :: lli
- real, intent(out) :: ll(lli%im,lli%jm)
- integer, intent(out) :: status
-
- ! --- const --------------------------------
-
- character(len=*), parameter :: rname = mname//'/Interpol_sh_ll'
-
- ! --- local --------------------------------
-
- integer :: j
-
- ! --- begin --------------------------------
-
- call Check( sh )
- call Check( lli, 'n', ll, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! loop over latitudes
- do j = 1, lli%jm
- ! evaluate at oposite latidutes:
- call Eval_Lons( ll(:,j), sh, lli%lat(j), int(360.0/lli%dlon_deg), &
- lli%lon(1), lli%im, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
-
- ! ok
- status = 0
- end subroutine Interpol_sh_ll
-
- ! *
-
-
- ! from shi/sh to ll
-
- subroutine Interpol_shi_ll( shi, shc, lli, ll, status )
-
- use Grid_Type_sh, only : TshGridInfo, Check, Eval_Lons
- use Grid_Type_sh, only : TshGrid, Init, Done, Set
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -------------------------------
-
- type(TshGridInfo), intent(in) :: shi
- complex, intent(in) :: shc(shi%np)
- type(TllGridInfo), intent(in) :: lli
- real, intent(out) :: ll(lli%im,lli%jm)
- integer, intent(out) :: status
-
- ! --- const --------------------------------
-
- character(len=*), parameter :: rname = mname//'/Interpol_shi_ll'
-
- ! --- local --------------------------------
-
- type(TshGrid) :: sh
- integer :: j
-
- ! --- begin --------------------------------
-
- ! store input in old type grid:
- call Init( sh )
- call Set( sh, shi%T, shc )
- ! check lat/lon arguments:
- call Check( lli, 'n', ll, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! loop over latitudes
- do j = 1, lli%jm
- ! evaluate spectral field:
- call Eval_Lons( ll(:,j), sh, lli%lat(j), int(360.0/lli%dlon_deg), &
- lli%lon(1), lli%im, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- ! done
- call Done( sh )
-
- ! ok
- status = 0
-
- end subroutine Interpol_shi_ll
-
-
-
- ! =========================================================
- ! ===
- ! === interpolate from gg
- ! ===
- ! =========================================================
-
- ! Return a logical array with size gg;
- ! true if a point is required for interpolation from gg to ll
- !
- ! Include 'depth' extra rows.
- !
- ! Also set flags in ggi for each row.
- !
-
- subroutine InterpolMask( ggi, gg, lli, depth )
-
- use Grid_Type_gg, only : TggGridInfo, Check
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -------------------------------
-
- type(TggGridInfo), intent(inout) :: ggi
- logical, intent(out) :: gg(ggi%np)
- type(TllGridInfo), intent(in) :: lli
- integer, intent(in) :: depth
-
- ! --- local --------------------------------
-
- integer :: j, jn, js
-
- ! --- begin ------------------------------
-
- ! note: gg lats from north to south!
- !print *, 'llilat:',lli%blat_deg(0), lli%blat_deg(lli%nlat)
-
- ! search south most gg lat outside lli
- js = 1
- do
- if ( js == ggi%nlat ) exit
- if ( ggi%lat(js) < lli%blat(0) ) exit
- js = js + 1
- end do
- js = min( ggi%nlat, js+depth )
-
- ! search north-most gg lat row outside lli
- jn = ggi%nlat
- do
- if ( jn == 1 ) exit
- if ( ggi%lat(jn) > lli%blat(lli%nlat) ) exit
- jn = jn - 1
- end do
- jn = max( 1, jn-depth )
-
- ! set all rows between js and jn to true:
- gg = .false.
- ggi%latflag = .false.
- do j = jn, js
- ggi%latflag(j) = .true.
- gg(ggi%i1(j):ggi%im(j)) = .true.
- end do
-
- end subroutine InterpolMask
-
-
- ! *************************************************************
-
- !
- ! Determine fraction of gg cell that covers a ll cell.
- !
- ! Returns three arrays:
- !
- ! integer :: ncov(im,jm)
- ! integer :: indx(im,jm,max_nconv)
- ! real :: frac(im,jm,max_nconv)
- !
- ! For an ll cell (i,j), 'ncov' gives the number of gg cells covering it.
- ! Their gg indices are stored in : indx(i,j,1:ncov(i,j)),
- ! corresponding fractions are in : frac(i,j,1:ncov(i,j)) .
- !
-
- subroutine gg2ll_Init( gg2ll, ggi, lli, status )
- use num, only : Interval
- use grid_tools, only : pi, ll_area_frac
- use grid_type_gg, only : TggGridInfo, AreaOper
- use grid_type_ll, only : TllGridInfo, AreaOper
- ! --- in/out ---------------------------
-
- type(Tgg2llFracs), intent(out) :: gg2ll
- type(TggGridInfo), intent(in) :: ggi
- type(TllGridInfo), intent(in) :: lli
- integer, intent(out) :: status
-
- ! --- const ---------------------------------
- character(len=*), parameter :: rname = mname//'/gg2ll_Init'
-
- ! --- local ----------------------------
-
- integer :: max_ncov_lon, max_ncov_lat, max_ncov
- integer :: i, j
- integer :: iflag
- integer :: gi, gi1, gi2
- integer :: gj, gj1, gj2
- integer :: nlon
- real :: gblon(0:ggi%nlon_reg)
- real :: west1, east1, south1, north1
- real :: west2, east2, south2, north2
- real :: frac
- integer :: ncov
-
- ! --- begin ----------------------------
-
- ! save dimension
- gg2ll%nlon = lli%nlon
- gg2ll%nlat = lli%nlat
- gg2ll%np = ggi%np
-
- ! estimate maximum number of gg cells covering an ll cell:
- max_ncov_lon = ceiling(lli%dlon/minval(ggi%dlon))
- max_ncov_lat = ceiling(lli%dlat/minval(ggi%dlat))
- max_ncov = (max_ncov_lon+1) * (max_ncov_lat+1)
-
- ! allocate arrays
- allocate( gg2ll%ncov(lli%nlon,lli%nlat) )
- allocate( gg2ll%indx(lli%nlon,lli%nlat,max_ncov) )
- allocate( gg2ll%frac(lli%nlon,lli%nlat,max_ncov) )
-
- ! zero by default:
- gg2ll%ncov = 0
- gg2ll%indx = 0
- gg2ll%frac = 0.0
-
- gj1 = 0
- gj2 = 0
-
- ! loop over ll cells from north to south (gg direction):
- do j = lli%nlat, 1, -1
- do i = 1, lli%nlon
-
- ! extract boundaries of ll cell:
- west2 = lli%blon(i-1)
- east2 = lli%blon(i)
- if ( east2 < 0.0 ) then
- west2 = west2 + 2*pi ! (0,2pi)
- east2 = east2 + 2*pi ! (0,2pi)
- end if
- south2 = lli%blat(j-1)
- north2 = lli%blat(j)
- ! search gg rows including north and south ll lat;
- ! negative lats to get increasing values ...
- call Interval( -ggi%blat, -north2 , gj1, iflag )
- if ( iflag /= 0 ) stop 'BUG IN gg2ll_Init : wrong iflag gj1'
- call Interval( -ggi%blat, -south2, gj2, iflag )
- if ( iflag /= 0 ) stop 'BUG IN gg2ll_Init : wrong iflag gj2'
-
- gi1 = 0
- gi2 = 0
- ! loop over gg lat rows:
- do gj = gj1, gj2
-
- ! boundary lons
- nlon = ggi%nlon(gj)
- do gi = 0, nlon
- gblon(gi) = (gi-0.5)*ggi%dlon(gj)
- end do
-
- ! search cells including west and east bound of ll cell
- if ( west2 < gblon(0) ) then
- call Interval( gblon(0:nlon), west2+2*pi, gi1, iflag )
- else if ( west2 > gblon(nlon) ) then
- call Interval( gblon(0:nlon), west2-2*pi, gi1, iflag )
- else
- call Interval( gblon(0:nlon), west2 , gi1, iflag )
- end if
- if ( iflag /= 0 ) then
- print *, 'gblon=', gblon(0:nlon)
- print *, 'west2=',west2
- print *, 'iflag=',iflag
- stop 'BUG IN gg2ll_Init : wrong iflag gi1'
- end if
- if ( east2 < gblon(0) ) then
- call Interval( gblon(0:nlon), east2+2*pi, gi2, iflag )
- else if ( east2 > gblon(nlon) ) then
- call Interval( gblon(0:nlon), east2-2*pi, gi2, iflag )
- else
- call Interval( gblon(0:nlon), east2 , gi2, iflag )
- end if
- if ( iflag /= 0 ) then
- print *, 'gblon=', gblon(0:nlon)
- print *, 'east2=',east2
- stop 'BUG IN gg2ll_Init : wrong iflag gi2'
- end if
-
- ! loop over all gg cells in current row:
- gi = gi1
- do
-
- ! extract boundaries of gg cell:
- west1 = (gi-1.5)*ggi%dlon(gj) ! (0,2pi)
- east1 = (gi-0.5)*ggi%dlon(gj) ! (0,2pi)
- south1 = ggi%blat(gj)
- north1 = ggi%blat(gj-1)
- ! shift if gg cell is right from [0,2pi]
- if ( west1 > east2 ) then
- west1 = west1 - 2*pi ! (0,2pi)
- east1 = east1 - 2*pi ! (0,2pi)
- end if
- ! determine covarage fraction:
- frac = ll_area_frac( west1, east1, south1, north1, &
- west2, east2, south2, north2 )
- ! fill fraction:
- if ( frac > 0.0 .and. frac <= 1.0 ) then
- ncov = gg2ll%ncov(i,j) + 1
- gg2ll%ncov(i,j) = ncov
- gg2ll%indx(i,j,ncov) = ggi%i1(gj)-1 + gi
- gg2ll%frac(i,j,ncov) = frac
- else if ( abs(frac) < 1.0e-4 ) then
- ! almost no coverage ...
- else if ( abs(frac-1.0) < 1.0e-4 ) then
- !print *, 'WARNING in module grid_interpol, gg2ll_Init'
- !print *, 'frac=',frac
- !print *, ' 1:', west1, east1, south1, north1
- !print *, ' 2:', west2, east2, south2, north2
- ncov = gg2ll%ncov(i,j) + 1
- gg2ll%ncov(i,j) = ncov
- gg2ll%indx(i,j,ncov) = ggi%i1(gj)-1 + gi
- gg2ll%frac(i,j,ncov) = 1.0
- else
- print *, 'ERROR in module grid_interpol, gg2ll_Init'
- print *, 'frac=',frac
- print *, ' 1:', west1, east1, south1, north1
- print *, ' 2:', west2, east2, south2, north2
- stop
- end if
- if ( gi == gi2 ) exit
- gi = gi + 1
- if ( gi == nlon+1 ) gi = 1
- end do
-
- end do
- end do
- end do
-
- ! store cell area's
- allocate( gg2ll%A_gg(ggi%np) )
- call AreaOper( ggi, gg2ll%A_gg, '=', 'm2' )
- allocate( gg2ll%A_ll(lli%nlon,lli%nlat) )
- call AreaOper( lli, gg2ll%A_ll, '=', 'm2', status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! ok
- status = 0
- end subroutine gg2ll_Init
-
-
- ! ***
-
-
- subroutine gg2ll_Done( gg2ll )
-
- ! --- in/out ---------------------------
-
- type(Tgg2llFracs), intent(inout) :: gg2ll
-
- ! --- begin ----------------------------
-
- ! deallocate arrays
- deallocate( gg2ll%ncov )
- deallocate( gg2ll%indx )
- deallocate( gg2ll%frac )
- deallocate( gg2ll%A_gg )
- deallocate( gg2ll%A_ll )
-
- end subroutine gg2ll_Done
- ! ***
-
- !
- ! ncov(i,j)
- ! ll(i,j) = sum gg(indx(i,j,k)) * frac(i,j,k)
- ! k=1
- !
-
- subroutine gg2ll_FracSum( gg2ll, gg, ll, status, key )
-
- ! --- in/out ---------------------------
-
- type(Tgg2llFracs), intent(in) :: gg2ll
- real, intent(in) :: gg(:)
- real, intent(out) :: ll(:,:)
- integer, intent(out) :: status
- character(len=*), intent(in), optional :: key
-
- ! --- const ----------------------------------
-
- character(len=*), parameter :: rname = mname//'/gg2ll_FracSum'
-
- ! --- local ----------------------------
- character(len=10) :: the_key
- integer :: i, j, k
- integer :: ncov, indx
- real :: fac
-
- ! --- begin ----------------------------
-
- the_key = 'none'
- if ( present(key) ) the_key = key
-
- if ( any(shape(gg2ll%ncov)/=shape(ll)) ) then
- write (*,'("ERROR - shapes of ll and gg2ll do not match:")')
- write (*,'("ERROR - ll : ",2i4)') shape(ll)
- write (*,'("ERROR - gg2ll : ",2i4)') shape(gg2ll%ncov)
- write (*,'("ERROR in ",a)') rname; status=1; return
- end if
- if ( minval(gg2ll%indx)<0 .or. maxval(gg2ll%indx)>size(gg) ) then
- write (*,'("ERROR - indices of gg array in gg2ll out of range:")')
- write (*,'("ERROR - gg : 1 - ",i4)') size(gg)
- write (*,'("ERROR - gg2ll : ",i4," - ",i4)') minval(gg2ll%indx), maxval(gg2ll%indx)
- write (*,'("ERROR in ",a)') rname; status=1; return
- end if
- if ( minval(gg2ll%frac)<0.0 .or. maxval(gg2ll%frac)>1.0 ) then
- write (*,'("ERROR - fraction in gg2ll out of range:")')
- write (*,'("ERROR - gg2ll: ",i4," - ",i4)') minval(gg2ll%frac), maxval(gg2ll%frac)
- write (*,'("ERROR in ",a)') rname; status=1; return
- end if
-
- ll = 0.0
- do j = 1, gg2ll%nlat
- do i = 1, gg2ll%nlon
- ncov = gg2ll%ncov(i,j)
- if ( ncov > 0 ) then
- do k = 1, ncov
- indx = gg2ll%indx(i,j,k)
- select case ( the_key )
- case ( 'none' )
- fac = 1.0
- case ( 'area-aver', 'area-sum' )
- fac = gg2ll%A_gg(indx)
- case default
- write (*,'("ERROR - key `",a,"` not supported")') trim(the_key)
- write (*,'("ERROR in ",a)') rname; status=1; return
- end select
- ll(i,j) = ll(i,j) + gg(indx) * fac * gg2ll%frac(i,j,k)
- end do
- end if
-
- select case ( the_key )
- case ( 'none', 'area-sum' )
- ! nothing to be done
- case ( 'area-aver' )
- ll(i,j) = ll(i,j) / gg2ll%A_ll(i,j)
- case default
- write (*,'("ERROR - key `",a,"` not supported")') trim(the_key)
- write (*,'("ERROR in ",a)') rname; status=1; return
- end select
- end do
- end do
-
- ! ok
- status = 0
-
- end subroutine gg2ll_FracSum
-
-
-
-
- ! *************************************************************
-
- !
- ! Determine fraction of gg cell that covers a ll cell.
- !
- ! Returns three arrays:
- !
- ! integer :: ncov(im,jm)
- ! integer :: indx(im,jm,max_nconv)
- ! real :: frac(im,jm,max_nconv)
- !
- ! For a gg cell 'k', 'ncov(k)' gives the number of ll cells covering it.
- ! Their ll indices are stored in : ii(k,1:ncov(k)), jj(k,1:ncov(k)) ;
- ! corresponding fractions are in : frac(k,1:ncov(k)) .
- !
-
- subroutine ll2gg_Init( ll2gg, lli, ggi, status )
- use num, only : Interval
- use grid_tools, only : pi, ll_area_frac
- use grid_type_gg, only : TggGridInfo, AreaOper
- use grid_type_ll, only : TllGridInfo, AreaOper
- ! --- in/out ---------------------------
-
- type(Tll2ggFracs), intent(out) :: ll2gg
- type(TllGridInfo), intent(in) :: lli
- type(TggGridInfo), intent(in) :: ggi
- integer, intent(out) :: status
-
- ! --- const ------------------------------------
-
- character(len=*), parameter :: rname = mname//'/ll2gg_Init'
-
- ! --- local ----------------------------
-
- integer :: max_ncov_lon, max_ncov_lat, max_ncov
- integer :: gi, gi1, gi2
- integer :: gj, gj1, gj2
- integer :: li, li1, li2
- integer :: lj, lj1, lj2
- real :: west2, east2, south2, north2
- real :: west1, east1, south1, north1
- integer :: iflag
- integer :: gp
- real :: frac
- integer :: ncov
-
- ! --- begin ----------------------------
-
- ! save dimension
- ll2gg%nlon = lli%nlon
- ll2gg%nlat = lli%nlat
- ll2gg%np = ggi%np
-
- ! estimate maximum number of ll cells covering a gg cell:
- max_ncov_lon = ceiling(maxval(ggi%dlon)/lli%dlon)
- max_ncov_lat = ceiling(maxval(ggi%dlat)/lli%dlat)
- max_ncov = (max_ncov_lon+1) * (max_ncov_lat+1)
-
- ! allocate arrays
- allocate( ll2gg%ncov(ggi%np) )
- allocate( ll2gg%ii(ggi%np,max_ncov) )
- allocate( ll2gg%jj(ggi%np,max_ncov) )
- allocate( ll2gg%ff(ggi%np,max_ncov) )
-
- ! zero by default:
- ll2gg%ncov = 0
- ll2gg%ii = 0
- ll2gg%jj = 0
- ll2gg%ff = 0.0
-
- ! index in gg arrays:
- gp = 0
-
- ! row range in ll grid:
- lj1 = 0
- lj2 = 0
- ! loop over gg rows:
- do gj = 1, ggi%nlat
-
- ! extract north/south boundaries of gg cell:
- north2 = ggi%blat(gj-1) ! [-pi,pi]
- south2 = ggi%blat(gj) ! [-pi,pi]
-
- ! search ll rows including north and south gg lat;
- call Interval( lli%blat, south2, lj1, iflag )
- if ( iflag /= 0 ) stop 'BUG IN ll2gg_Init : wrong iflag lj1'
- call Interval( lli%blat, north2, lj2, iflag )
- if ( iflag /= 0 ) stop 'BUG IN ll2gg_Init : wrong iflag lj2'
- ! loop over cells in row:
- do gi = 1, ggi%nlon(gj)
-
- ! next index in 1d row ...
- gp = gp + 1
-
- ! set east/west boundaries of gg cell:
- west2 = (gi-1.5) * ggi%dlon(gj) ! [0,2pi]
- east2 = (gi-0.5) * ggi%dlon(gj) ! [0,2pi]
- ! loop over ll lat rows:
- do lj = lj1, lj2
- ! search ll cells including west and east bound of gg cell
- if ( west2 > lli%blon(lli%nlon) ) then
- call Interval( lli%blon, west2-2*pi, li1, iflag )
- else
- call Interval( lli%blon, west2 , li1, iflag )
- end if
- if ( iflag /= 0 ) then
- print *, 'lli%blon=', lli%blon
- print *, 'west2=',west2
- print *, 'iflag=',iflag
- stop 'BUG IN ll2gg_Init : wrong iflag li1'
- end if
- if ( east2 > lli%blon(lli%nlon) ) then
- call Interval( lli%blon, east2-2*pi, li2, iflag )
- else
- call Interval( lli%blon, east2 , li2, iflag )
- end if
- if ( iflag /= 0 ) then
- print *, 'lli%blon=', lli%blon
- print *, 'east2=',east2
- print *, 'east2-2pi=',east2-2*pi
- stop 'BUG IN ll2gg_Init : wrong iflag li2'
- end if
-
- ! loop over ll lon cels:
- li = li1
- do
-
- ! extract boundaries of ll cell:
- west1 = lli%blon(li-1) ! [-pi,pi]
- east1 = lli%blon(li ) ! [-pi,pi]
- south1 = lli%blat(lj-1) ! [-pi,pi]
- north1 = lli%blat(lj ) ! [-pi,pi]
- ! shift if completely left from gg cell:
- if ( east1 < west2 ) then
- west1 = west1 + 2*pi
- east1 = east1 + 2*pi
- end if
- ! determine covarage fraction:
- frac = ll_area_frac( west1, east1, south1, north1, &
- west2, east2, south2, north2 )
- ! fill fraction:
- if ( frac > 0.0 .and. frac <= 1.0 ) then
- ncov = ll2gg%ncov(gp) + 1
- ll2gg%ncov(gp) = ncov
- ll2gg%ii(gp,ncov) = li
- ll2gg%jj(gp,ncov) = lj
- ll2gg%ff(gp,ncov) = frac
- else if ( abs(frac) < 1.0e-4 ) then
- ! almost no coverage ...
- else if ( abs(frac-1.0) < 1.0e-4 ) then
- !print *, 'WARNING in module grid_interpol, ll2gg_Init'
- !print *, 'frac=',frac
- !print *, ' 1:', west1, east1, south1, north1
- !print *, ' 2:', west2, east2, south2, north2
- ncov = ll2gg%ncov(gp) + 1
- ll2gg%ncov(gp) = ncov
- ll2gg%ii(gp,ncov) = li
- ll2gg%jj(gp,ncov) = lj
- ll2gg%ff(gp,ncov) = 1.0
- else
- print *, 'ERROR in module grid_interpol, ll2gg_Init'
- print *, 'frac=',frac
- print *, ' 1:', west1, east1, south1, north1
- print *, ' 2:', west2, east2, south2, north2
- stop
- end if
- if ( li == li2 ) exit
- li = li + 1
- if ( li == lli%nlon+1 ) li = 1
- end do ! ll i
- end do ! ll j
- end do ! gg i
- end do ! gg j
-
- ! store cell area's
- allocate( ll2gg%A_gg(ggi%np) )
- call AreaOper( ggi, ll2gg%A_gg, '=', 'm2' )
- !
- allocate( ll2gg%A_ll(lli%nlon,lli%nlat) )
- call AreaOper( lli, ll2gg%A_ll, '=', 'm2', status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! ok
- status = 0
- end subroutine ll2gg_Init
-
-
- ! ***
-
-
- subroutine ll2gg_Done( ll2gg )
-
- ! --- in/out ---------------------------
-
- type(Tll2ggFracs), intent(inout) :: ll2gg
-
- ! --- begin ----------------------------
-
- ! deallocate arrays
- deallocate( ll2gg%ncov )
- deallocate( ll2gg%ii )
- deallocate( ll2gg%jj )
- deallocate( ll2gg%ff )
- deallocate( ll2gg%A_gg )
- deallocate( ll2gg%A_ll )
-
- end subroutine ll2gg_Done
- ! ***
-
- !
- ! ncov(p)
- ! gg(p) = sum ll(ii(p,k),jj(p,k)) * ff(p,k)
- ! k=1
- !
-
- subroutine ll2gg_FracSum( ll2gg, ll, gg, key )
-
- ! --- in/out ---------------------------
-
- type(Tll2ggFracs), intent(in) :: ll2gg
- real, intent(in) :: ll(:,:)
- real, intent(out) :: gg(:)
- character(len=*), intent(in), optional :: key
-
- ! --- local ----------------------------
- character(len=10) :: the_key
- integer :: gp, i, j, k
- integer :: ncov
- real :: fac
-
- ! --- begin ----------------------------
-
- the_key = 'none'
- if ( present(key) ) the_key = key
-
- if ( size(ll2gg%ncov) /= size(gg) ) then
- print *, 'shapes of gg and ll2gg do not match:'
- print *, ' ll : ', size(gg)
- print *, ' ll2gg: ', size(ll2gg%ncov)
- stop 'FATAL ERROR IN ll2gg_FracSum'
- end if
- if ( minval(ll2gg%ii)<0 .or. maxval(ll2gg%ii)>size(ll,1) ) then
- print *, 'indices of ll array in ll2gg out of range:'
- print *, ' ll i : 1 - ', size(ll,1)
- print *, ' ll2gg: ', minval(ll2gg%ii),'-',maxval(ll2gg%ii)
- stop 'FATAL ERROR IN ll2gg_FracSum'
- end if
- if ( minval(ll2gg%jj)<0 .or. maxval(ll2gg%jj)>size(ll,2) ) then
- print *, 'indices of ll array in ll2gg out of range:'
- print *, ' ll j : 1 - ', size(ll,2)
- print *, ' ll2gg: ', minval(ll2gg%jj),'-',maxval(ll2gg%jj)
- stop 'FATAL ERROR IN ll2gg_FracSum'
- end if
- if ( minval(ll2gg%ff)<0.0 .or. maxval(ll2gg%ff)>1.0 ) then
- print *, 'fraction in ll2gg out of range:'
- print *, ' ll2gg: ', minval(ll2gg%ff),'-',maxval(ll2gg%ff)
- stop 'FATAL ERROR IN ll2gg_FracSum'
- end if
-
- ! init to zero:
- gg = 0.0
-
- ! loop over gg
- do gp = 1, ll2gg%np
- ncov = ll2gg%ncov(gp)
- if ( ncov > 0 ) then
- do k = 1, ncov
- i = ll2gg%ii(gp,k)
- j = ll2gg%jj(gp,k)
- select case ( the_key )
- case ( 'none' )
- fac = 1.0
- case ( 'area-aver', 'area-sum' )
- fac = ll2gg%A_ll(i,j)
- case default
- print *, 'Sorry, key "'//trim(the_key)//'" not supported.'
- stop 'BUG IN ll2gg_FracSum'
- end select
- !if (abs(ll(i,j))>0.0) then
- !print *, gp,':',gg(gp) ,'+', ll(i,j) ,'*', fac ,'*', ll2gg%ff(gp,k),'=',gg(gp) + ll(i,j) * fac * ll2gg%ff(gp,k)
- !endif
- gg(gp) = gg(gp) + ll(i,j) * fac * ll2gg%ff(gp,k)
- end do
- end if
- select case ( the_key )
- case ( 'none', 'area-sum' )
- ! nothing to be done
- !if (abs(gg(gp))>0.0) then
- !print *, ' '
- !endif
- case ( 'area-aver' )
- gg(gp) = gg(gp) / ll2gg%A_gg(gp)
- !if (abs(gg(gp))>0.0) then
- !print *, gp,':',gg(gp),'/',ll2gg%A_gg(gp),'=',gg(gp) / ll2gg%A_gg(gp)
- !print *, ' '
- !endif
- case default
- print *, 'Sorry, key "'//trim(the_key)//'" not supported.'
- stop 'BUG IN ll2gg_FracSum'
- end select
- end do ! gg cells
-
- end subroutine ll2gg_FracSum
-
-
-
-
- ! *************************************************************
-
- ! gg to ll
-
- subroutine Interpol_gg_ll( ggi, gg, lli, ll, status )
-
- use Binas, only : deg2rad
-
- use Num, only : Interp_Lin, CircInterp_Lin
- use Grid_Type_gg, only : TggGridInfo, Check
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -------------------------------
-
- type(TggGridInfo), intent(in) :: ggi
- real, intent(in) :: gg(ggi%np)
- type(TllGridInfo), intent(in) :: lli
- real, intent(out) :: ll(lli%im,lli%jm)
- integer, intent(out) :: status
-
- ! --- const ----------------------------------
-
- character(len=*), parameter :: rname = mname//'/Interpol_gg_ll'
-
- ! --- local --------------------------------
-
- integer :: nlon, nlon_max
- integer :: nlat
- integer :: i1, im
-
- real, allocatable :: lons(:)
- real, allocatable :: row(:)
-
- real, allocatable :: gl(:,:)
- real, allocatable :: gl_lat(:)
-
- integer :: i, j
- integer :: j1, jm
- integer :: ilast
-
- ! --- begin --------------------------------
-
- call Check( ggi, gg )
- call Check( lli, 'n', ll, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- nlat = ggi%nlat
- nlon_max = maxval(ggi%nlon)
-
- ! ll in lon, gg in lat
- allocate( gl(size(ll,1),0:nlat+1) ); gl = 0.0
- ! latitudes from south->north
- allocate( gl_lat(0:nlat+1) )
- gl_lat(0) = -90.0 * deg2rad ! south pole (rad)
- do j = 1, nlat
- gl_lat(nlat+1-j) = ggi%lat(j) ! rad
- end do
- gl_lat(nlat+1) = 90.0 * deg2rad ! north pole (rad)
- ! row in gg grid; doubled from -360.0 to 360.0
- allocate( lons(nlon_max) ); lons = 0.0
- allocate( row(nlon_max) ) ; row = 0.0
-
- ! select first and last Gaussian lat:
- j1 = nlat
- do
- if ( (j1 == 1) .or. (ggi%lat(j1) > maxval(lli%lat)) ) exit
- j1 = j1 - 1
- end do
- jm = 1
- do
- if ( (jm == nlat) .or. (ggi%lat(jm) < minval(lli%lat)) ) exit
- jm = jm + 1
- end do
- ! loop over Gaussian latitudes, from north to south!
- do j = j1, jm
- ! number of lon points at this latitude:
- nlon = ggi%nlon(j)
- ! start and end indices in grid point array
- i1 = ggi%i1(j)
- im = ggi%im(j)
- ! lons in [0,2pi)
- do i = 1, nlon
- lons(i) = (i-1)*360.0/nlon
- end do
- lons(1:nlon) = lons(1:nlon) * deg2rad
- ! grid values (doubled)
- row(1:nlon) = gg(i1:im)
-
- ! set north pole (j=1 in gg, j=nlat+1 in gl)
- if ( j == 1 ) then
- gl(:,nlat+1) = sum(row(1:nlon))/nlon
- end if
-
- ! set south pole
- if ( j == nlat ) then
- gl(:,0) = sum(row(1:nlon))/nlon
- end if
- ! Interpolate over lon (circular arrays);
- ! swap lats to ensure south -> north:
- ilast = 1
- do i = 1, lli%im
- call CircInterp_Lin( lons(1:nlon), 360.0*deg2rad, row(1:nlon), &
- lli%lon(i), gl(i,nlat+1-j), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- end do
- ! Linear interpolation over lat:
- ilast = 1
- do j = 1, lli%jm
- do i = 1, lli%im
- call Interp_Lin( gl_lat, gl(i,:), lli%lat(j), ll(i,j), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- end do
- ! free memory
- deallocate( gl )
- deallocate( gl_lat )
- deallocate( lons )
- deallocate( row )
-
- ! ok
- status = 0
- end subroutine Interpol_gg_ll
-
-
- ! =========================================================
- ! ===
- ! === interpolate from ll
- ! ===
- ! =========================================================
-
-
- ! ll to gg
- !
- ! First interpol in lat direction to Gaussian lats,
- ! then interpolate in lon direction.
-
- ! NOTE: MIPSpro compiler gives errors if argument names are the
- ! same as used for Interpol_gg_ll ...
-
- subroutine Interpol_ll_gg( lli, ll, xggi, xgg, status )
-
- use Binas, only : deg2rad
-
- use Num, only : Interp_Lin, CircInterp_Lin
- use Grid_Type_gg, only : TggGridInfo, Check
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -------------------------------
- type(TllGridInfo), intent(in) :: lli
- real, intent(in) :: ll(lli%im,lli%jm)
- type(TggGridInfo), intent(in) :: xggi
- real, intent(out) :: xgg(1:xggi%np)
- integer, intent(out) :: status
-
- ! --- const ----------------------------------
-
- character(len=*), parameter :: rname = mname//'/Interpol_ll_gg'
-
- ! --- local --------------------------------
-
- integer :: nlon
- integer :: nlat
- integer :: i, j
- integer :: i0
- integer :: ilast
-
- real :: dlon_deg
- real :: glat, glon
- real :: period
- real, allocatable :: row(:)
- ! --- begin --------------------------------
-
- call Check( xggi, xgg )
- call Check( lli, 'n', ll, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- nlat = xggi%nlat
-
- ! ll grid interpolated to gaussian lat:
- allocate( row(1:lli%im) )
- ! loop over Gaussian latitudes:
- do j = 1, nlat
-
- ! number of lon points at this latitude:
- nlon = xggi%nlon(j)
- ! current Gaussian lat
- glat = xggi%lat(j)
-
- !! error if ll grid does not cover this gaussian lat
- !if ( glat < minval(lli%lat) .or. glat > maxval(lli%lat) ) then
- ! write (*,'("ERROR - ll grid does not cover current gg latitude:")')
- ! write (*,'("ERROR - ll lat range : ",2f12.4)') minval(lli%lat), maxval(lli%lat)
- ! write (*,'("ERROR - gg latitude : ",f12.4)') glat
- ! write (*,'("ERROR in ",a)') rname; status=1
- !end if
- ! * interpolate ll grid to this gaussian lat:
- ! check for direction of ll lats:
- if ( lli%lat(1) < lli%lat(lli%jm) ) then
- ! 'normal' : grid stored from south to north
- ilast = 1
- do i = 1, lli%im
- call Interp_Lin( lli%lat, ll(i,:), glat, row(i), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- else
- ! grid stored from north to south; fake with negative lats:
- ilast = 1
- do i = 1, lli%im
- call Interp_Lin( -lli%lat, ll(i,:), -glat, row(i), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- end if
-
- ! base index of current row in xgg array:
- i0 = xggi%i1(j)-1
- ! interpolate from ll lons to lons in this xgg row:
- period = 360.0*deg2rad
- ilast = 1
- do i = 1, nlon
- ! curren lon in xgg grid:
- glon = (i-1)*xggi%dlon(j)
- ! periodic interpolation:
- call CircInterp_Lin( lli%lon, period, row, glon, xgg(i0+i), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- end do
- ! free memory
- deallocate( row )
-
- ! ok
- status = 0
- end subroutine Interpol_ll_gg
-
-
-
-
- ! =========================================================
- ! ===
- ! === area average gg
- ! ===
- ! =========================================================
-
-
- subroutine Aver_gg_ll( ggi, gg, lli, ll )
-
- use Binas, only : deg2rad
-
- use Num, only : IntervalQuad_Lin, IntervalQuad_Cos_Lin
- use Grid_Type_gg, only : TggGridInfo, Check
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -------------------------------
-
- type(TggGridInfo), intent(in) :: ggi
- real, intent(in) :: gg(ggi%np)
- type(TllGridInfo), intent(in) :: lli
- real, intent(out) :: ll(lli%im,lli%jm)
-
- integer :: status
-
- ! --- const ----------------------------------
-
- character(len=*), parameter :: rname = mname//'/ Aver_gg_ll'
-
- ! --- local --------------------------------
- integer :: nlon, nlon_max
- integer :: nlat
- integer :: i1, im
-
- real, allocatable :: lons(:)
- real, allocatable :: row(:)
-
- real, allocatable :: gl(:,:)
- real, allocatable :: gl_lat(:)
- real, allocatable :: gl_dim2(:)
-
- integer :: i, j
- integer :: ilast
-
- ! --- begin --------------------------------
- call Check( ggi, gg )
- call Check( lli, 'n', ll, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; stop; end if
-
- nlat = ggi%nlat
- nlon_max = maxval(ggi%nlon)
-
- ! ll in lon, gg in lat
- allocate( gl(size(ll,1),0:nlat+1) )
- allocate( gl_dim2(0:nlat+1) )
- ! latitudes from south->north
- allocate( gl_lat(0:nlat+1) )
- ! row in gg grid; doubled from -360.0 to 360.0
- allocate( lons(2*nlon_max) )
- allocate( row(2*nlon_max) )
- ! loop over Gaussian latitudes, from north to south!
- do j = 1, nlat
- ! number of lon points at this latitude:
- nlon = ggi%nlon(j)
- ! start and end indices in grid point array
- i1 = ggi%i1(j)
- im = ggi%im(j)
-
- ! lons from -360 to 360
- do i = 1, nlon
- lons(i) = -360.0 + (i-1)*360.0/nlon
- lons(nlon+i) = (i-1)*360.0/nlon
- end do
- lons(1:2*nlon) = lons(1:2*nlon) * deg2rad
- ! grid values (doubled)
- row(1:2*nlon) = (/ gg(i1:im), gg(i1:im) /)
- ! integrate over dlon assuming linear interpolation;
- ! swap lats to ensure south -> north;
- ! result in [g] rad
- ilast = 1
- do i = 1, lli%im
- call IntervalQuad_Lin( lons(1:2*nlon), row(1:2*nlon), &
- lli%blon(i-1), lli%blon(i), gl(i,nlat+1-j), &
- ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; stop; end if
- end do
- gl_lat(nlat+1-j) = ggi%lat(j) ! rad
- ! take care of poles (reverse lats);
- ! set polar value to average of surrounding points:
- if ( j == 1 ) then
- ! north pole
- gl_lat(nlat+1) = 90.0 * deg2rad
- gl(:,nlat+1) = lli%dlon * sum(gg(i1:im))/(im-i1+1)
- end if
- if ( j == nlat ) then
- ! south pole
- gl_lat(0) = -90.0 * deg2rad
- gl(:,0) = lli%dlon * sum(gg(i1:im))/(im-i1+1)
- end if
- end do
- ! integrate over dlat assuming linear interpolation;
- ! weight with cos(lat) to account for smaller cells near the poles,
- ! result in [g] rad^2
- ilast = 1
- do j = 1, lli%jm
- do i = 1, lli%im
- !>>> bsf15k bug fix >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- !call IntervalQuad_Cos_Lin( gl_lat, gl(i,:), lli%blat(j-1), lli%blat(j), ll(i,j), ilast )
- gl_dim2 = gl(i,:)
- call IntervalQuad_Cos_Lin( gl_lat, gl_dim2, lli%blat(j-1), lli%blat(j), &
- ll(i,j), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; stop; end if
- !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- end do
- end do
- ! area average; lli%area(j) for cells in row j in rad^2
- do j = 1, lli%jm
- ll(:,j) = ll(:,j) / lli%area(j)
- end do
- ! free memory
- deallocate( gl )
- deallocate( gl_dim2 )
- deallocate( gl_lat )
- deallocate( lons )
- deallocate( row )
- end subroutine Aver_gg_ll
-
- ! =========================================================
- ! ===
- ! === area average sh
- ! ===
- ! =========================================================
-
-
- ! Deterimine spectral truncation for area integration.
-
- integer function ShTruncation( T, dlon, dlat )
-
- ! --- in/out --------------------------
-
- integer, intent(in) :: T
- real, intent(in) :: dlon, dlat ! deg
-
- ! --- begin --------------------------
- !print *, 'WARNING - spectral fields are not truncated ...'
-
- ! o no truncation:
- ShTruncation = T
- ! o choose minium T based on grid resolution:
- !ShTruncation = min( T, ceiling( (360.0/min(dlon,dlat))/2 - 1 ) )
- !print *, 'WARNING - adhoc truncation of spectral fields for testing ...'
- !ShTruncation = 21
-
- end function ShTruncation
-
-
- ! Deterimine refinement for averaging spectral fields
- ! over distance 'cellspacing' in degrees.
- ! Cell is divided in number of intervals returned by this function.
-
- integer function ShRefinement( T, cellspacing )
-
- ! --- in/out ----------------------------------------
-
- integer, intent(in) :: T
- real, intent(in) :: cellspacing
-
- ! --- local -----------------------------------------
-
- real :: shres
- integer :: nstep
-
- ! --- beging -----------------------------------------
-
- ! o fixec number of intervals per cell
- !ShRefinement = 20
- !ShRefinement = 1
- !ShRefinement = nint( cellspacing * 2 )
- !write (*,'(" WARNING: ShRefinement = ",i4)') ShRefinement
-
- ! o resultion specified by spectral truncation
- ! truncation T <--> resolution 360.0/(2(T+1))
- ! nstep points within resolution implied by T
- shres = 360.0 / (2*(T+1))
- nstep = 2
- ShRefinement = max( 1, ceiling(nstep*cellspacing/shres) )
- end function ShRefinement
-
-
- ! ***********************************
-
-
- subroutine Aver_sh_ll( sh, lli, ll, status )
-
- use grid_tools, only : deg2rad, pi
-
- use Num, only : IntervalQuad_Lin, IntervalQuad_Cos_Lin
- use Grid_Type_sh, only : TshGrid, Check, Eval_Lons
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -------------------------------
-
- type(TshGrid), intent(in) :: sh
- type(TllGridInfo), intent(in) :: lli
- real, intent(out) :: ll(lli%im,lli%jm)
- integer, intent(out) :: status
-
- ! --- const ----------------------------------
-
- character(len=*), parameter :: rname = mname//'/Aver_sh_ll'
-
- ! --- local --------------------------------
-
- integer :: i, j, jf
- integer :: ilast
- integer :: nlon_fine
-
- integer :: T
- integer :: refinement_i, refinement_j
-
- real, allocatable :: llgrid(:)
- real, allocatable :: lons_fine(:), row_fine(:)
- real, allocatable :: llf(:,:), lat(:)
- ! --- begin --------------------------------
- call Check( sh )
- T = sh%T
- call Check( lli, 'n', ll, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; stop; end if
- ! determine refinement (5 points per sh resolution)
- refinement_i = ShRefinement( T, lli%dlon_deg )
- refinement_j = ShRefinement( T, lli%dlon_deg )
- ! number of lons in fine grid on complete circle:
- nlon_fine = 360.0/lli%dlon_deg * refinement_i
-
- ! store evaluation of spectral field:
- allocate( llgrid(nlon_fine) )
-
- ! lons on complete circle from westb+[0,2pi)
- allocate( row_fine(0:nlon_fine) )
- allocate( lons_fine(0:nlon_fine) )
- do i = 0, nlon_fine
- lons_fine(i) = i*2*pi/nlon_fine
- end do
- lons_fine = lli%blon(0) + lons_fine
-
- ! ll in lon, fine in lat
- allocate( llf(lli%im,0:refinement_j) )
- allocate( lat(0:refinement_j) )
- ! loop over latitudes in ll grid:
- do j = 1, lli%jm
-
- ! loop over latitudes in fine grid:
- do jf = 0, refinement_j
-
- ! latitude in fine grid:
- lat(jf) = lli%blat(j-1) + jf*lli%dlat/refinement_j
-
- ! evaluate row:
- ! (oposite latitudes, but use only one)
- call Eval_Lons( llgrid, sh, lat(jf), &
- nlon_fine, lons_fine(0), nlon_fine, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! copy result, cyclic:
- row_fine = (/ llgrid(:), llgrid(1) /)
- ! integral in lon direction assuming linear interpolation,
- ! result in [sh] rad
- ilast = 1
- do i = 1, lli%im
- call IntervalQuad_Lin( lons_fine, row_fine, lli%blon(i-1), lli%blon(i), llf(i,jf), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
-
- end do
- ! integral in lat direction;
- ! weight with cos(lat) to account for smaller cells near the poles,
- ! result in [sh] rad^2
- do i = 1, lli%im
- ilast = 1
- call IntervalQuad_Cos_Lin( lat, llf(i,:), lli%blat(j-1), lli%blat(j), ll(i,j), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- ! area average; lli%area(j) for cells in row j in rad^2
- ll(:,j) = ll(:,j) / lli%area(j)
- end do
- ! free memory
- deallocate( llgrid )
- deallocate( lons_fine )
- deallocate( row_fine )
- deallocate( llf )
- deallocate( lat )
- end subroutine Aver_sh_ll
- ! ===========================================================
-
- !
- ! key == 'aver'
- !
- ! int int F(k) dA / A
- !
- ! key == 'exp,aver'
- !
- ! int int exp(F(k)) dA / A
- !
-
- subroutine IntArea_shi_ll_f( key, shi, shc, lli, ll, status )
-
- use grid_tools, only : deg2rad, pi
-
- use Num, only : IntervalQuad_Lin, IntervalQuad_Cos_Lin
- use Grid_Type_sh, only : TshGrid, TshGridInfo
- use Grid_Type_sh, only : Init, Done, Check, Set, Truncate, SpN
- use Grid_Type_sh, only : sh_Pnm, Eval_Lons
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -----------------------------------------
-
- character(len=*), intent(in) :: key
- type(TshGridInfo), intent(in) :: shi
- complex, intent(in) :: shc(:)
- type(TllGridInfo), intent(in) :: lli
- real, intent(out) :: ll(lli%im,lli%jm)
- integer, intent(out) :: status
-
- ! --- const ----------------------------------
- character(len=*), parameter :: rname = mname//'/IntArea_shi_ll_f'
- ! --- local ------------------------------------------
-
- integer :: i, j, jf
- integer :: ilast
-
- type(TshGrid) :: sh
- integer :: Ttr
- real, allocatable :: Pnm(:)
-
- integer :: refinement_i, refinement_j
-
- integer :: nlon_fine_360, nlon_fine
- real, allocatable :: ff(:)
- real, allocatable :: lons_fine(:), row_fine(:)
- real, allocatable :: llf(:,:), lat(:)
-
- real, allocatable :: llf_dim2(:)
-
- !logical :: aver_to_prev
-
- ! --- begin ------------------------------------------
-
- ! store input in old type grid:
- call Init( sh )
- call Set( sh, shi%T, shc )
- ! use truncation up to grid resolution:
- Ttr = ShTruncation( shi%T, lli%dlon_deg, lli%dlat_deg )
- call Truncate( sh, Ttr )
-
- ! allocate space for legendre coeff:
- allocate( Pnm(SpN(Ttr)) )
- ! determine refinement (5 points per sh resolution)
- refinement_i = ShRefinement( Ttr, lli%dlon_deg )
- refinement_j = ShRefinement( Ttr, lli%dlat_deg )
- ! number of lons in fine grid on complete circle:
- nlon_fine_360 = 360.0/lli%dlon_deg * refinement_i
- nlon_fine = lli%im * refinement_i
-
- ! store evaluation of spectral field:
- allocate( ff(0:nlon_fine) )
-
- ! lons on arc westb+[0,..)
- allocate( row_fine(0:nlon_fine) )
- allocate( lons_fine(0:nlon_fine) )
- do i = 0, nlon_fine
- lons_fine(i) = i*2*pi/nlon_fine_360
- end do
- lons_fine = lli%blon(0) + lons_fine
-
- ! ll in lon, fine in lat
- allocate( llf(lli%im,0:refinement_j) )
- allocate( llf_dim2(0:refinement_j) )
- allocate( lat(0:refinement_j) )
- ! loop over latitudes in ll grid:
- !aver_to_prev = .false.
- do j = 1, lli%jm
- ! loop over latitudes in fine grid:
- do jf = 0, refinement_j
-
- ! latitude in fine grid:
- lat(jf) = lli%blat(j-1) + jf*lli%dlat/refinement_j
-
- !! southpole ?
- !if ( abs(lat(jf) - (-pi/2)) < 1.0e-4 ) then
- ! ! fill with average of next row
- ! aver_to_prev = .true.
- ! cycle
- !end if
- !
- !! northpole ?
- !if ( abs(lat(jf) - (pi/2)) < 1.0e-4 ) then
- ! ! fill with average of previous row:
- ! llf(:,jf) = sum(llf(:,jf-1)) / size(llf,1)
- ! exit
- !end if
-
- ! evaluate Legendre functions:
- call sh_Pnm( Pnm, Ttr, lat(jf), status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! evaluate rows:
- call Eval_Lons( ff, sh, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- ! combine fields:
- select case ( key )
- !
- ! int int F(k) dA / A
- !
- case ( 'aver' )
- row_fine = ff / lli%area(j)
- !
- ! int int exp(F(k)) dA / A
- !
- case ( 'exp,aver' )
- row_fine = exp(ff) / lli%area(j)
- !
- ! error ...
- !
- case default
- write (*,'("ERROR - unknown key `",a,"`")') trim(key)
- write (*,'("ERROR in ",a)') rname; status=1; return
- end select
- ! integral in lon direction assuming linear interpolation,
- ! result in [sh] rad
- ilast = 1
- do i = 1, lli%im
- call IntervalQuad_Lin( lons_fine, row_fine, lli%blon(i-1), lli%blon(i), llf(i,jf), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- !! copy to southpole ..
- !if ( (jf==1) .and. aver_to_prev ) then
- ! llf(:,0) = sum(llf(:,1)) / size(llf,1)
- ! aver_to_prev = .false.
- !end if
- end do ! loop over rows in fine grid
- ! integral in lat direction;
- ! weight with cos(lat) to account for smaller grid cells:
- do i = 1, lli%im
- ilast = 1
- !call IntervalQuad_Cos_Lin( lat, llf(i,:,l), lli%blat(j-1), lli%blat(j), ll(i,j,l), ilast )
- !>>> bsf15k bug fix >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- llf_dim2 = llf(i,:)
- call IntervalQuad_Cos_Lin( lat, llf_dim2, lli%blat(j-1), lli%blat(j), ll(i,j), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- end do
- end do ! loop over rows
- ! free memory
- deallocate( Pnm )
- deallocate( ff )
- deallocate( lons_fine )
- deallocate( row_fine )
- deallocate( llf )
- deallocate( llf_dim2 )
- deallocate( lat )
- call Done( sh )
-
- end subroutine IntArea_shi_ll_f
- ! ***
-
-
- subroutine IntArea_sh_ll_f( key, F, lli, ll, status )
-
- use grid_tools, only : deg2rad, pi
-
- use Num, only : IntervalQuad_Lin, IntervalQuad_Cos_Lin
- use Grid_Type_sh, only : TshGrid, Init, Done, SpN, sh_Pnm, Eval_Lons, Set, Check
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -----------------------------------------
-
- character(len=*), intent(in) :: key
- type(TshGrid), intent(in) :: F(:)
- type(TllGridInfo), intent(in) :: lli
- real, intent(out) :: ll(lli%im,lli%jm,size(F))
- integer, intent(out) :: status
-
- ! --- const --------------------------------
-
- character(len=*), parameter :: rname = mname//'/IntArea_sh_ll_f'
-
-
- ! --- local ------------------------------------------
-
- integer :: i, j, jf
- integer :: l, lm
- integer :: ilast
-
- integer :: T
- type(TshGrid) :: sh
- real, allocatable :: Pnm(:)
-
- integer :: refinement_i, refinement_j
-
- integer :: nlon_fine_360, nlon_fine
- real, allocatable :: ff(:)
- real, allocatable :: lons_fine(:), row_fine(:)
- real, allocatable :: llf(:,:,:), lat(:)
-
- real, allocatable :: llf_dim2(:)
-
- ! --- begin ------------------------------------------
-
- ! number of levels:
- lm = size(F)
-
- ! check arguments:
- T = F(1)%T
- do l = 2, lm
- call Check( F(l), T )
- end do
- ! use truncation up to grid resolution:
- T = ShTruncation( T, lli%dlon_deg, lli%dlat_deg )
- call Init( sh, T )
-
- ! allocate space for legendre coeff:
- allocate( Pnm(SpN(T)) )
- ! determine refinement (5 points per sh resolution)
- refinement_i = ShRefinement( T, lli%dlon_deg )
- refinement_j = ShRefinement( T, lli%dlat_deg )
- ! number of lons in fine grid on complete circle:
- nlon_fine_360 = 360.0/lli%dlon_deg * refinement_i
- nlon_fine = lli%im * refinement_i
-
- ! store evaluation of spectral field:
- allocate( ff(0:nlon_fine) )
-
- ! lons on arc westb+[0,..)
- allocate( row_fine(0:nlon_fine) )
- allocate( lons_fine(0:nlon_fine) )
- do i = 0, nlon_fine
- lons_fine(i) = i*2*pi/nlon_fine_360
- end do
- lons_fine = lli%blon(0) + lons_fine
-
- ! ll in lon, fine in lat
- allocate( llf(lli%im,0:refinement_j,lm) )
- allocate( llf_dim2(0:refinement_j) )
- allocate( lat(0:refinement_j) )
- ! loop over latitudes in ll grid:
- !aver_to_prev = .false.
- do j = 1, lli%jm
- ! loop over latitudes in fine grid:
- do jf = 0, refinement_j
-
- ! latitude in fine grid:
- lat(jf) = lli%blat(j-1) + jf*lli%dlat/refinement_j
-
- !! southpole ?
- !if ( abs(lat(jf) - (-pi/2)) < 1.0e-4 ) then
- ! ! fill with average of next row
- ! aver_to_prev = .true.
- ! cycle
- !end if
- !
- !! northpole ?
- !if ( abs(lat(jf) - (pi/2)) < 1.0e-4 ) then
- ! ! fill with average of previous row:
- ! do l = 1, lm
- ! llf(:,jf,l) = sum(llf(:,jf-1,l)) / size(llf,1)
- ! end do
- ! exit
- !end if
-
- ! evaluate Legendre functions:
- call sh_Pnm( Pnm, T, lat(jf), status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! evaluate rows:
- do l = 1, lm
- call Set( sh, T, F(l) )
- call Eval_Lons( ff, sh, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- ! combine fields:
- select case ( key )
- !
- ! int int F(k) dA / A
- !
- case ( 'aver' )
- row_fine = ff / lli%area(j)
-
- !
- ! int int exp(F(k)) dA / A
- !
- case ( 'exp,aver' )
- row_fine = exp(ff) / lli%area(j)
-
- !
- ! error ...
- !
- case default
- write (*,'("ERROR - unsupported integrand key : ",a)') trim(key)
- write (*,'("ERROR in ",a)') rname; status=1; return
- end select
- ! integral in lon direction assuming linear interpolation,
- ! result in [sh] rad
- ilast = 1
- do i = 1, lli%im
- call IntervalQuad_Lin( lons_fine, row_fine, lli%blon(i-1), lli%blon(i), llf(i,jf,l), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- end do ! loop over levels
- !! copy to southpole ..
- !if ( (jf==1) .and. aver_to_prev ) then
- ! do l = 1, lm
- ! llf(:,0,l) = sum(llf(:,1,l)) / size(llf,1)
- ! end do
- ! aver_to_prev = .false.
- !end if
- end do ! loop over rows in fine grid
- ! integral in lat direction;
- ! weight with cos(lat) to account for smaller grid cells:
- do l = 1, lm
- do i = 1, lli%im
- ilast = 1
- !call IntervalQuad_Cos_Lin( lat, llf(i,:,l), lli%blat(j-1), lli%blat(j), ll(i,j,l), ilast )
- !>>> bsf15k bug fix >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- llf_dim2 = llf(i,:,l)
- call IntervalQuad_Cos_Lin( lat, llf_dim2, lli%blat(j-1), lli%blat(j), ll(i,j,l), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- end do
- end do
- end do ! loop over rows
- ! free memory
- deallocate( Pnm )
- deallocate( ff )
- deallocate( lons_fine )
- deallocate( row_fine )
- deallocate( llf )
- deallocate( llf_dim2 )
- deallocate( lat )
- call Done( sh )
-
- ! ok
- status = 0
-
- end subroutine IntArea_sh_ll_f
-
-
- !
- ! key == 'F*(da+db*exp(H))*cos'
- !
- ! int int F(k) (da+db*exp(H)) cos(lat) dA
- !
- ! key == 'F*G*(db*exp(H))/cos'
- !
- ! int int F(k) G db*exp(H) / cos(lat) dA
- !
- ! (for these keys, results are added to ll)
- !
- !
- subroutine IntArea_sh_ll_fgh( key, F, G, H, da, db, lli, ll, status )
-
- use grid_tools, only : deg2rad, pi
-
- use Num, only : IntervalQuad_Lin
- use Grid_Type_sh, only : TshGrid, Init, Done, SpN, sh_Pnm, Eval_Lons, Set, Check
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -----------------------------------------
-
- character(len=*), intent(in) :: key
- type(TshGrid), intent(in) :: F(:)
- type(TshGrid), intent(in) :: G, H
- real, intent(in) :: da(size(F)), db(size(F))
- type(TllGridInfo), intent(in) :: lli
- real, intent(inout) :: ll(lli%im,lli%jm,size(F))
- integer, intent(out) :: status
-
- ! --- const --------------------------------------
-
- character(len=*), parameter :: rname = mname//'/IntArea_sh_ll_fgh'
-
- ! --- local ------------------------------------------
-
- integer :: i, j, jf
- integer :: l, lm
- integer :: ilast
-
- integer :: T
- type(TshGrid) :: sh
- real, allocatable :: Pnm(:)
-
- integer :: refinement_i, refinement_j
-
- integer :: nlon_fine_360, nlon_fine
- real, allocatable :: ff(:)
- real, allocatable :: gg(:)
- real, allocatable :: exp_hh(:)
- real, allocatable :: lons_fine(:), row_fine(:)
- real, allocatable :: llf(:,:,:), lat(:)
-
- real, allocatable :: llf_dim2(:)
-
- logical :: aver_to_prev
- real :: res
-
- ! --- begin ------------------------------------------
-
- ! number of levels:
- lm = size(F)
-
- ! check arguments:
- call Check( H )
- T = H%T
- do l = 1, lm
- call Check( F(l), T )
- end do
- call Check( G, T )
-
- ! use truncation up to grid resolution:
- T = ShTruncation( T, lli%dlon_deg, lli%dlat_deg )
- call Init( sh, T )
-
- ! allocate space for legendre coeff:
- allocate( Pnm(SpN(T)) )
-
- ! determine refinement (5 points per sh resolution)
- refinement_i = ShRefinement( T, lli%dlon_deg )
- refinement_j = ShRefinement( T, lli%dlat_deg )
- ! number of lons in fine grid on complete circle:
- nlon_fine_360 = 360.0/lli%dlon_deg * refinement_i
- nlon_fine = lli%im * refinement_i
-
- ! store evaluation of spectral field:
- allocate( ff(0:nlon_fine) )
- allocate( gg(0:nlon_fine) )
- allocate( exp_hh(0:nlon_fine) )
-
- ! lons on arc westb+[0,..)
- allocate( row_fine(0:nlon_fine) )
- allocate( lons_fine(0:nlon_fine) )
- do i = 0, nlon_fine
- lons_fine(i) = i*2*pi/nlon_fine_360
- end do
- lons_fine = lli%blon(0) + lons_fine
-
- ! ll in lon, fine in lat
- allocate( llf(lli%im,0:refinement_j,lm) )
- allocate( lat(0:refinement_j) )
- allocate( llf_dim2(0:refinement_j) )
-
-
- ! *** integrals in lon direction
- ! loop over latitudes in ll grid:
- aver_to_prev = .false.
- do j = 1, lli%jm
- ! loop over latitudes in fine grid:
- do jf = 0, refinement_j
-
- ! latitude in fine grid:
- lat(jf) = lli%blat(j-1) + jf*lli%dlat/refinement_j
-
- ! southpole ?
- if ( abs(lat(jf) - (-pi/2)) < 1.0e-4 ) then
- ! fill with average of next row
- aver_to_prev = .true.
- cycle
- end if
-
- ! northpole ?
- if ( abs(lat(jf) - (pi/2)) < 1.0e-4 ) then
- ! fill with average of previous row:
- do l = 1, lm
- llf(:,jf,l) = sum(llf(:,jf-1,l)) / size(llf,1)
- end do
- exit
- end if
-
- ! evaluate Legendre functions:
- call sh_Pnm( Pnm, T, lat(jf), status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! evaluate rows:
- call Set( sh, T, G )
- call Eval_Lons( gg, sh, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- call Set( sh, T, H )
- call Eval_Lons( exp_hh, sh, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- exp_hh = exp(exp_hh)
-
- do l = 1, lm
- ! combine fields:
- select case ( key )
- !
- ! int int F(k) (da+db*exp(H)) cos(lat) dA
- !
- case ( 'F*(da+db*exp(H))*cos' )
- call Set( sh, T, F(l) )
- call Eval_Lons( ff, sh, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- row_fine = ff * ( da(l) + exp_hh*db(l) ) * cos(lat(jf))
-
- !
- ! int int F(k) G db*exp(H) / cos(lat) dA
- !
- case ( 'F*G*(db*exp(H))/cos' )
-
- if ( db(l) == 0.0 ) then
- row_fine = 0.0
- else
- call Set( sh, T, F(l) )
- call Eval_Lons( ff, sh, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- row_fine = ff * gg * ( exp_hh*db(l) ) / cos(lat(jf))
- end if
- !
- ! error ...
- !
- case default
- print *, 'IntArea_sh_ll_fgh - unknown key "'//trim(key)//'"'
- stop
- end select
- ! integral in lon direction assuming linear interpolation,
- ! result in [sh] rad
- ilast = 1
- do i = 1, lli%im
- call IntervalQuad_Lin( lons_fine, row_fine, lli%blon(i-1), lli%blon(i), llf(i,jf,l), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- end do ! loop over levels
- ! copy to southpole ..
- if ( (jf==1) .and. aver_to_prev ) then
- do l = 1, lm
- llf(:,0,l) = sum(llf(:,1,l)) / size(llf,1)
- end do
- aver_to_prev = .false.
- end if
- end do ! loop over rows in fine grid
-
- ! *** integral in lat direction
-
- ! 3D field:
- do l = 1, lm
- ilast = 1
- do i = 1, lli%im
- !call lquad( lat, llf(i,:,l), lli%blat(j-1), lli%blat(j), res, ilast )
- !>>> bsf15k bug fix >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- llf_dim2 = llf(i,:,l)
- call IntervalQuad_Lin( lat, llf_dim2, lli%blat(j-1), lli%blat(j), res, ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- ! add result
- ll(i,j,l) = ll(i,j,l) + res
- end do
- end do
-
- end do ! loop over rows
- ! free memory
- deallocate( Pnm )
- deallocate( ff )
- deallocate( gg )
- deallocate( exp_hh )
- deallocate( lons_fine )
- deallocate( row_fine )
- deallocate( llf )
- deallocate( llf_dim2 )
- deallocate( lat )
- call Done( sh )
-
- ! ok
- status = 0
-
- end subroutine IntArea_sh_ll_fgh
-
- ! ***
-
-
- subroutine IntArea_shi_ll_fgh( key, shi_in, nlev, F, G, H, da, db, lli, ll, status )
-
- use grid_tools, only : deg2rad, pi
-
- use Num, only : IntervalQuad_Lin
- use Grid_Type_sh, only : TshGridInfo, Init, Done, sh_Pnm, Eval_Lons, Set, Check
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -----------------------------------------
-
- character(len=*), intent(in) :: key
- type(TshGridInfo), intent(in) :: shi_in
- integer, intent(in) :: nlev
- complex, intent(in) :: F(shi_in%np,nlev)
- complex, intent(in) :: G(shi_in%np)
- complex, intent(in) :: H(shi_in%np)
- real, intent(in) :: da(nlev), db(nlev)
- type(TllGridInfo), intent(in) :: lli
- real, intent(inout) :: ll(lli%im,lli%jm,nlev)
- integer, intent(out) :: status
-
- ! --- const --------------------------------------
-
- character(len=*), parameter :: rname = mname//'/IntArea_sh_ll_fgh'
-
- ! --- local ------------------------------------------
-
- integer :: i, j, jf
- integer :: l
- integer :: ilast
-
- type(TshGridInfo) :: shi
- integer :: T
- real, pointer :: Pnm(:)
-
- integer :: refinement_i, refinement_j
-
- integer :: nlon_fine_360, nlon_fine
- real, pointer :: ff(:)
- real, pointer :: gg(:)
- real, pointer :: exp_hh(:)
- real, pointer :: lons_fine(:), row_fine(:)
- real, pointer :: llf(:,:,:), lat(:)
-
- real, pointer :: llf_dim2(:)
-
- logical :: aver_to_prev
- real :: res
-
- ! --- begin ------------------------------------------
-
- ! use truncation up to grid resolution:
- T = ShTruncation( shi_in%T, lli%dlon_deg, lli%dlat_deg )
- !T = ShTruncation( 159, lli%dlon_deg, lli%dlat_deg )
- ! spectral info:
- call Init( shi, T, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! allocate space for legendre coeff:
- allocate( Pnm(shi%np) )
-
- ! determine refinement (5 points per sh resolution)
- refinement_i = ShRefinement( shi%T, lli%dlon_deg )
- refinement_j = ShRefinement( shi%T, lli%dlat_deg )
- ! number of lons in fine grid on complete circle:
- nlon_fine_360 = 360.0/lli%dlon_deg * refinement_i
- nlon_fine = lli%im * refinement_i
-
- ! store evaluation of spectral field:
- allocate( ff(0:nlon_fine) )
- allocate( gg(0:nlon_fine) )
- allocate( exp_hh(0:nlon_fine) )
-
- ! lons on arc westb+[0,..)
- allocate( row_fine(0:nlon_fine) )
- allocate( lons_fine(0:nlon_fine) )
- do i = 0, nlon_fine
- lons_fine(i) = i*2*pi/nlon_fine_360
- end do
- lons_fine = lli%blon(0) + lons_fine
-
- ! ll in lon, fine in lat
- allocate( llf(lli%im,0:refinement_j,nlev) )
- allocate( lat(0:refinement_j) )
- allocate( llf_dim2(0:refinement_j) )
-
-
- ! *** integrals in lon direction
- ! loop over latitudes in ll grid:
- aver_to_prev = .false.
- do j = 1, lli%jm
- ! loop over latitudes in fine grid:
- do jf = 0, refinement_j
-
- ! latitude in fine grid:
- lat(jf) = lli%blat(j-1) + jf*lli%dlat/refinement_j
-
- ! southpole ?
- if ( abs(lat(jf) - (-pi/2)) < 1.0e-4 ) then
- ! fill with average of next row
- aver_to_prev = .true.
- cycle
- end if
-
- ! northpole ?
- if ( abs(lat(jf) - (pi/2)) < 1.0e-4 ) then
- ! fill with average of previous row:
- do l = 1, nlev
- llf(:,jf,l) = sum(llf(:,jf-1,l)) / size(llf,1)
- end do
- exit
- end if
-
- ! evaluate Legendre functions:
- call sh_Pnm( Pnm, shi%T, lat(jf), status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! evaluate rows:
- !print *, 'aaa10b shi_in ', shi_in%T, shi_in%np
- !print *, 'aaa10b G size ', size(G)
- !print *, 'aaa10b G val ', G(1:10)
- !print *, 'aaa10b shi ', shi%T, shi%np
- !print *, 'aaa10b Pnm size ', size(Pnm)
- !print *, 'aaa10b Pnm val ', Pnm(1:10)
- call Eval_Lons( shi_in, G, shi, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, gg, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- call Eval_Lons( shi_in, H, shi, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, exp_hh, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- exp_hh = exp(exp_hh)
-
- ! loop over levels:
- !xOMP PARALLEL &
- !xOMP default ( none ) &
- !xOMP shared ( nlev, key, T, F, Pnm, nlon_fine_360, nlon_fine, lons_fine ) &
- !xOMP shared ( ff, gg, da, exp_hh, db, lat, jf, lli, llf ) &
- !xOMP private ( l, sh, row_fine, ilast, status )
- !xOMP DO
- do l = 1, nlev
- ! combine fields:
- select case ( key )
- !
- ! int int F(k) (da+db*exp(H)) cos(lat) dA
- !
- case ( 'F*(da+db*exp(H))*cos' )
- call Eval_Lons( shi_in, F(:,l), shi, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, ff, status )
- !if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- row_fine = ff * ( da(l) + exp_hh*db(l) ) * cos(lat(jf))
-
- !
- ! int int F(k) G db*exp(H) / cos(lat) dA
- !
- case ( 'F*G*(db*exp(H))/cos' )
-
- if ( db(l) == 0.0 ) then
- row_fine = 0.0
- else
- call Eval_Lons( shi_in, F(:,l), shi, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, ff, status )
- !if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- row_fine = ff * gg * ( exp_hh*db(l) ) / cos(lat(jf))
- end if
- !
- ! error ...
- !
- case default
- print *, 'IntArea_sh_ll_fgh - unknown key "'//trim(key)//'"'
- !stop
- end select
- ! integral in lon direction assuming linear interpolation,
- ! result in [sh] rad
- ilast = 1
- do i = 1, lli%im
- call IntervalQuad_Lin( lons_fine, row_fine, lli%blon(i-1), lli%blon(i), llf(i,jf,l), ilast, status )
- !if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- end do ! levels
- !xOMP END DO
- !xOMP END PARALLEL
- ! copy to southpole ..
- if ( (jf==1) .and. aver_to_prev ) then
- do l = 1, nlev
- llf(:,0,l) = sum(llf(:,1,l)) / size(llf,1)
- end do
- aver_to_prev = .false.
- end if
- end do ! loop over rows in fine grid
-
- ! *** integral in lat direction
-
- ! loop over levels:
- !xOMP PARALLEL DO
- do l = 1, nlev
- ilast = 1
- do i = 1, lli%im
- !call lquad( lat, llf(i,:,l), lli%blat(j-1), lli%blat(j), res, ilast )
- !>>> bsf15k bug fix >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- llf_dim2 = llf(i,:,l)
- call IntervalQuad_Lin( lat, llf_dim2, lli%blat(j-1), lli%blat(j), res, ilast, status )
- !if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- ! add result
- ll(i,j,l) = ll(i,j,l) + res
- end do
- end do
- !xOMP END PARALLEL DO
-
- end do ! loop over rows
- ! free memory
- deallocate( Pnm )
- deallocate( ff )
- deallocate( gg )
- deallocate( exp_hh )
- deallocate( lons_fine )
- deallocate( row_fine )
- deallocate( llf )
- deallocate( llf_dim2 )
- deallocate( lat )
-
- call Done( shi )!, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! ok
- status = 0
-
- end subroutine IntArea_shi_ll_fgh
-
- ! ***
-
-
- !
- ! key == '[F*(da+db*exp(H))*cos]/[()*cos]'
- !
- ! int int F(k) (da+db*exp(H)) cos(lat) dA / int int (da+db*exp(H)) cos(lat) dA
- !
- ! Result is put in ll, not added.
- ! Uses cos integration in lat direction.
- !
- subroutine IntArea_sh_ll_fh( key, F, H, da, db, lli, ll, status )
-
- use grid_tools, only : deg2rad, pi
-
- use Num, only : IntervalQuad_Lin, IntervalQuad_Cos_Lin
- use Grid_Type_sh, only : TshGrid, Init, Done, SpN, sh_Pnm, Eval_Lons, Set, Check
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -----------------------------------------
-
- character(len=*), intent(in) :: key
- type(TshGrid), intent(in) :: F(:)
- type(TshGrid), intent(in) :: H
- real, intent(in) :: da(size(F)), db(size(F))
- type(TllGridInfo), intent(in) :: lli
- real, intent(inout) :: ll(lli%im,lli%jm,size(F))
- integer, intent(out) :: status
-
- ! --- const --------------------------------------
-
- character(len=*), parameter :: rname = mname//'/IntArea_sh_ll_fh'
-
- ! --- local ------------------------------------------
-
- integer :: i, j, jf
- integer :: l, lm
- integer :: ilast
-
- integer :: T
- type(TshGrid) :: sh
- real, allocatable :: Pnm(:)
-
- integer :: refinement_i, refinement_j
-
- integer :: nlon_fine_360, nlon_fine
- real, allocatable :: ff(:)
- real, allocatable :: exp_hh(:)
- real, allocatable :: lons_fine(:), row_fine(:)
- real, allocatable :: llf(:,:,:), lat(:)
- real, allocatable :: llf_dim2(:)
-
- real :: res
-
- real, allocatable :: llf_expH(:,:)
-
- ! --- begin ------------------------------------------
-
- ! number of levels:
- lm = size(F)
-
- ! check arguments:
- call Check( H )
- T = H%T
- do l = 1, lm
- call Check( F(L), T )
- end do
-
- T = ShTruncation( T, lli%dlon_deg, lli%dlat_deg )
- call Init( sh, T )
-
- ! allocate space for legendre coeff:
- allocate( Pnm(SpN(T)) )
-
- ! determine refinement (5 points per sh resolution)
- refinement_i = ShRefinement( T, lli%dlon_deg )
- refinement_j = ShRefinement( T, lli%dlat_deg )
- ! number of lons in fine grid on complete circle:
- nlon_fine_360 = 360.0/lli%dlon_deg * refinement_i
- nlon_fine = lli%im * refinement_i
-
- ! store evaluation of spectral field:
- allocate( ff(0:nlon_fine) )
- allocate( exp_hh(0:nlon_fine) )
-
- ! lons on arc westb+[0,..)
- allocate( row_fine(0:nlon_fine) )
- allocate( lons_fine(0:nlon_fine) )
- do i = 0, nlon_fine
- lons_fine(i) = i*2*pi/nlon_fine_360
- end do
- lons_fine = lli%blon(0) + lons_fine
-
- ! ll in lon, fine in lat
- allocate( llf(lli%im,0:refinement_j,lm) )
- allocate( llf_expH(lli%im,0:refinement_j) )
- allocate( lat(0:refinement_j) )
- allocate( llf_dim2(0:refinement_j) )
-
-
- ! *** integrals in lon direction
- ! loop over latitudes in ll grid:
- do j = 1, lli%jm
- ! loop over latitudes in fine grid:
- do jf = 0, refinement_j
-
- ! latitude in fine grid:
- lat(jf) = lli%blat(j-1) + jf*lli%dlat/refinement_j
-
- ! evaluate Legendre functions:
- call sh_Pnm( Pnm, T, lat(jf), status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! evaluate rows:
- call Set( sh, T, H )
- call Eval_Lons( exp_hh, sh, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! exponent:
- exp_hh = exp(exp_hh)
-
- ! compute lon integral over exp(H), as a part of integral over second term
- ! (use linear interpolation):
- ilast = 1
- do i = 1, lli%im
- call IntervalQuad_Lin( lons_fine, exp_hh, lli%blon(i-1), lli%blon(i), llf_expH(i,jf), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- do l = 1, lm
- call Set( sh, T, F(l) )
- call Eval_Lons( ff, sh, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- ! combine fields:
- select case ( key )
- !
- ! int int F(k) (da+db*exp(H)) cos(lat) dA / int int (da+db*exp(H)) cos(lat) dA
- !
- case ( '[F*(da+db*exp(H))*cos]/[()*cos]' )
- ! lon integral of first term:
- row_fine = ff * ( da(l) + exp_hh*db(l) )
-
- !
- ! error ...
- !
- case default
- print *, 'IntArea_sh_ll_fh - unknown key "'//trim(key)//'"'
- stop
- end select
- ! integral in lon direction assuming linear interpolation,
- ! result in [sh] rad
- ilast = 1
- do i = 1, lli%im
- call IntervalQuad_Lin( lons_fine, row_fine, lli%blon(i-1), lli%blon(i), llf(i,jf,l), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- end do ! loop over levels
- end do ! loop over rows in fine grid
-
- ! *** integral in lat direction
-
- ! 3D field:
- do l = 1, lm
- ilast = 1
- do i = 1, lli%im
- !call IntervalQuad_Cos_Lin( lat, llf(i,:,l), lli%blat(j-1), lli%blat(j), res, ilast )
- !>>> bsf15k bug fix >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- llf_dim2 = llf(i,:,l)
- call IntervalQuad_Cos_Lin( lat, llf_dim2, lli%blat(j-1), lli%blat(j), res, ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- ! set result
- ll(i,j,l) = res
- end do
- end do
-
- ! weight with integral over exp_hh :
- ilast = 1
- do i = 1, lli%im
- !>>> bsf15k bug fix >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- !call IntervalQuad_Cos_Lin( lat, llf_expH(i,:), lli%blat(j-1), lli%blat(j), res, ilast )
- llf_dim2 = llf_expH(i,:)
- call IntervalQuad_Cos_Lin( lat, llf_dim2, lli%blat(j-1), lli%blat(j), res, ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- ! weight with int int (da+db*exp(H))*cos(lat) dA
- do l = 1, lm
- ll(i,j,l) = ll(i,j,l) / (da(l)*lli%area(j) + db(l)*res)
- end do
- end do
-
- end do ! loop over rows
- ! free memory
- deallocate( Pnm )
- deallocate( ff )
- deallocate( exp_hh )
- deallocate( lons_fine )
- deallocate( row_fine )
- deallocate( llf )
- deallocate( llf_dim2 )
- deallocate( llf_expH )
- deallocate( lat )
-
- call Done( sh )
-
- ! ok
- status = 0
-
- end subroutine IntArea_sh_ll_fh
-
- ! ***
-
-
- subroutine IntArea_shi_ll_fh( key, shi_in, nlev, F, H, da, db, lli, ll, status )
-
- use grid_tools, only : deg2rad, pi
-
- use Num, only : IntervalQuad_Lin, IntervalQuad_Cos_Lin
- use Grid_Type_sh, only : TshGrid, Init, Done
- use Grid_Type_sh, only : SpN, sh_Pnm, Eval_Lons, Set, Check, SpN, Truncate
- use Grid_Type_sh, only : TshGridInfo
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -----------------------------------------
-
- character(len=*), intent(in) :: key
- type(TshGridInfo), intent(in) :: shi_in
- integer, intent(in) :: nlev
- complex, intent(in) :: F(shi_in%np,nlev)
- complex, intent(in) :: H(shi_in%np)
- real, intent(in) :: da(nlev), db(nlev)
- type(TllGridInfo), intent(in) :: lli
- real, intent(inout) :: ll(lli%im,lli%jm,nlev)
- integer, intent(out) :: status
-
- ! --- const ------------------------------------------
-
- character(len=*), parameter :: rname = mname//'/IntArea_shi_ll_fh'
-
- ! --- local ------------------------------------------
-
- integer :: i, j, jf
- integer :: l !, lm
- integer :: ilast
-
- type(TshGridInfo) :: shi
- ! type(TshGrid) :: sh
- integer :: Ttr
- real, allocatable :: Pnm(:)
-
- integer :: refinement_i, refinement_j
-
- integer :: nlon_fine_360, nlon_fine
- real, allocatable :: ff(:)
- real, allocatable :: exp_hh(:)
- real, allocatable :: lons_fine(:), row_fine(:)
- real, allocatable :: llf(:,:,:), lat(:)
- real, allocatable :: llf_dim2(:)
-
- real :: res
-
- real, allocatable :: llf_expH(:,:)
-
- ! --- begin ------------------------------------------
-
- ! ! number of levels:
- ! lm = size(F,2)
- !
- ! ! check arguments:
- ! if ( (size(F,1) /= shi%np) .or. (size(H) /= shi%np) ) then
- ! write (*,'("ERROR - number of complex coeff does not match with sh grid definition:")')
- ! write (*,'("ERROR - shi%np : ",i6)') shi%np
- ! write (*,'("ERROR - size(F,1) : ",i6)') size(F,1)
- ! write (*,'("ERROR - size(H) : ",i6)') size(H)
- ! write (*,'("ERROR in ",a)') rname; status=1; return
- ! end if
- !
- ! ! input temporary stored in old type grid:
- ! call Init( sh, shi%T )
-
- ! use truncation up to grid resolution:
- Ttr = ShTruncation( shi_in%T, lli%dlon_deg, lli%dlat_deg )
- ! call Truncate( sh, Ttr )
- call Init( shi, Ttr, status )
-
- ! allocate space for legendre coeff:
- ! allocate( Pnm(SpN(Ttr)) )
- allocate( Pnm(shi%np) )
- ! determine refinement (5 points per sh resolution)
- refinement_i = ShRefinement( shi%T, lli%dlon_deg )
- refinement_j = ShRefinement( shi%T, lli%dlat_deg )
- ! number of lons in fine grid on complete circle:
- nlon_fine_360 = 360.0/lli%dlon_deg * refinement_i
- nlon_fine = lli%im * refinement_i
-
- ! store evaluation of spectral field:
- allocate( ff(0:nlon_fine) )
- allocate( exp_hh(0:nlon_fine) )
-
- ! lons on arc westb+[0,..)
- allocate( row_fine(0:nlon_fine) )
- allocate( lons_fine(0:nlon_fine) )
- do i = 0, nlon_fine
- lons_fine(i) = i*2*pi/nlon_fine_360
- end do
- lons_fine = lli%blon(0) + lons_fine
-
- ! ll in lon, fine in lat
- !allocate( llf(lli%im,0:refinement_j,lm) )
- allocate( llf(lli%im,0:refinement_j,nlev) )
- allocate( llf_expH(lli%im,0:refinement_j) )
- allocate( lat(0:refinement_j) )
- allocate( llf_dim2(0:refinement_j) )
-
-
- ! *** integrals in lon direction
- ! loop over latitudes in ll grid:
- do j = 1, lli%jm
- ! loop over latitudes in fine grid:
- do jf = 0, refinement_j
-
- ! latitude in fine grid:
- lat(jf) = lli%blat(j-1) + jf*lli%dlat/refinement_j
-
- ! evaluate Legendre functions:
- !call sh_Pnm( Pnm, Ttr, lat(jf), status )
- call sh_Pnm( Pnm, shi%T, lat(jf), status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! evaluate rows:
- !call Set( sh, shi%T, H )
- !call Truncate( sh, Ttr )
- !call Eval_Lons( exp_hh, sh, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, status )
- !if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- call Eval_Lons( shi_in, H, shi, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, exp_hh, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- exp_hh = exp(exp_hh)
-
- ! compute lon integral over exp(H), as a part of integral over second term
- ! (use linear interpolation):
- ilast = 1
- do i = 1, lli%im
- call IntervalQuad_Lin( lons_fine, exp_hh, lli%blon(i-1), lli%blon(i), llf_expH(i,jf), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- ! combine fields:
- select case ( key )
- !
- ! int int F(k) (da+db*exp(H)) cos(lat) dA / int int (da+db*exp(H)) cos(lat) dA
- !
- case ( '[F*(da+db*exp(H))*cos]/[()*cos]' )
- !$OMP PARALLEL &
- !$OMP default ( none ) &
- !$OMP shared ( shi_in, F, shi, Pnm, nlon_fine_360, lons_fine, nlon_fine, lli, llf ) &
- !$OMP shared ( exp_hh, da, db, jf ) &
- !$OMP shared ( nlev ) &
- !$OMP private ( l, ff, status, row_fine, ilast )
- !$OMP DO
- do l = 1, nlev
- !do l = 1, lm
- !call Set( sh, shi%T, F(:,l) )
- !call Truncate( sh, Ttr )
- call Eval_Lons( shi_in, F(:,l), shi, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, ff, status )
- !if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- ! lon integral of first term:
- row_fine = ff * ( da(l) + exp_hh*db(l) )
-
- ! integral in lon direction assuming linear interpolation,
- ! result in [sh] rad
- ilast = 1
- do i = 1, lli%im
- call IntervalQuad_Lin( lons_fine, row_fine, lli%blon(i-1), lli%blon(i), llf(i,jf,l), ilast, status )
- !if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- end do ! loop over levels
- !$OMP END DO
- !$OMP END PARALLEL
- !
- ! error ...
- !
- case default
- print *, 'IntArea_shi_ll_fh - unknown key "'//trim(key)//'"'
- stop
- end select
- end do ! loop over rows in fine grid
-
- ! *** integral in lat direction
-
- ! 3D field:
- do l = 1, nlev
- !do l = 1, lm
- ilast = 1
- do i = 1, lli%im
- !call IntervalQuad_Cos_Lin( lat, llf(i,:,l), lli%blat(j-1), lli%blat(j), res, ilast )
- !>>> bsf15k bug fix >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- llf_dim2 = llf(i,:,l)
- call IntervalQuad_Cos_Lin( lat, llf_dim2, lli%blat(j-1), lli%blat(j), res, ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- ! set result
- ll(i,j,l) = res
- end do
- end do
-
- ! weight with integral over exp_hh :
- ilast = 1
- do i = 1, lli%im
- !>>> bsf15k bug fix >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- !call IntervalQuad_Cos_Lin( lat, llf_expH(i,:), lli%blat(j-1), lli%blat(j), res, ilast )
- llf_dim2 = llf_expH(i,:)
- call IntervalQuad_Cos_Lin( lat, llf_dim2, lli%blat(j-1), lli%blat(j), res, ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- ! weight with int int (da+db*exp(H))*cos(lat) dA
- do l = 1, nlev
- !do l = 1, lm
- ll(i,j,l) = ll(i,j,l) / (da(l)*lli%area(j) + db(l)*res)
- end do
- end do
-
- end do ! loop over rows
- ! free memory
- deallocate( Pnm )
- deallocate( ff )
- deallocate( exp_hh )
- deallocate( lons_fine )
- deallocate( row_fine )
- deallocate( llf )
- deallocate( llf_dim2 )
- deallocate( llf_expH )
- deallocate( lat )
-
- !call Done( sh )
-
- ! ok
- status = 0
-
- end subroutine IntArea_shi_ll_fh
-
- ! ***
-
-
- subroutine IntLat_sh_ll( key, F, H, da, db, lli, ll_u, status )
-
- use grid_tools, only : deg2rad, pi
-
- use Num, only : IntervalQuad_Lin
- use Grid_Type_sh, only : TshGrid, Init, Done, Set, Check
- use Grid_Type_sh, only : sh_Pnm, Eval_Lons, SpN
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -----------------------------------------
-
- character(len=*), intent(in) :: key
- type(TshGrid), intent(in) :: F(:)
- type(TshGrid), intent(in) :: H
- real, intent(in) :: da(size(F))
- real, intent(in) :: db(size(F))
- type(TllGridInfo), intent(in) :: lli
- real, intent(inout) :: ll_u(0:lli%im,lli%jm,size(F))
- integer, intent(out) :: status
-
- ! --- const --------------------------------------
-
- character(len=*), parameter :: rname = mname//'/IntLat_sh_ll'
-
- ! --- local ------------------------------------------
-
- integer :: i, j, jf
- integer :: l, lm
- integer :: ilast
-
- integer :: T
- type(TshGrid) :: sh
- real, allocatable :: Pnm(:)
-
- integer :: refinement_j
-
- integer :: nlon_fine_360, nlon_fine
- real, allocatable :: ff(:)
- real, allocatable :: exp_hh(:)
- real, allocatable :: llf(:,:,:), lat(:), llf_row(:)
-
- logical :: aver_to_prev
-
- ! --- begin ------------------------------------------
-
- ! number of levels:
- lm = size(F)
-
- ! check arguments:
- call Check( H )
- T = H%T
- do l = 1, lm
- call Check( F(l), T )
- end do
-
- T = ShTruncation( T, lli%dlon_deg, lli%dlat_deg )
- call Init( sh, T )
-
- ! allocate space for legendre coeff:
- allocate( Pnm(SpN(T)) )
- ! determine refinement based on spectral resolution
- ! and length of required integration interval:
- refinement_j = ShRefinement( T, lli%dlat_deg )
- ! number of lons in fine grid on complete circle:
- nlon_fine_360 = 360.0/lli%dlon_deg
- nlon_fine = lli%im
-
- ! store evaluation of spectral field:
- allocate( ff(0:nlon_fine) )
- allocate( exp_hh(0:nlon_fine) )
-
- ! ll in lon, fine in lat
- allocate( llf(0:lli%im,0:refinement_j,lm) )
- allocate( llf_row(0:refinement_j) )
- allocate( lat(0:refinement_j) )
- ! loop over latitudes in ll grid:
- aver_to_prev = .false.
- do j = 1, lli%jm
- ! loop over latitudes in fine grid:
- do jf = 0, refinement_j
-
- ! latitude in fine grid:
- lat(jf) = lli%blat(j-1) + jf*lli%dlat/refinement_j
-
- ! southpole ?
- if ( abs(lat(jf) - (-pi/2)) < 1.0e-4 ) then
- ! fill with average of next row
- aver_to_prev = .true.
- cycle
- end if
-
- ! northpole ?
- if ( abs(lat(jf) - (pi/2)) < 1.0e-4 ) then
- ! fill with average of previous row:
- do l = 1, lm
- llf(:,jf,l) = sum(llf(:,jf-1,l)) / size(llf,1)
- end do
- exit
- end if
-
- ! evaluate Legendre functions:
- call sh_Pnm( Pnm, T, lat(jf), status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! evaluate rows:
- call Set( sh, T, H )
- call Eval_Lons( exp_hh, sh, Pnm, nlon_fine_360, lli%blon(0), nlon_fine+1, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- exp_hh = exp(exp_hh)
- do l = 1, lm
- call Set( sh, T, F(l) )
- call Eval_Lons( ff, sh, Pnm, nlon_fine_360, lli%blon(0), nlon_fine+1, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- ! combine fields:
- select case ( key )
- !
- ! [ int exp(H) dlat ] / deltalat
- !
- case ( 'exp(H),aver' )
- llf(:,jf,l) = exp_hh / lli%dlat
- !
- ! int F (da+db*exp(H)) / cos(lat) dlat
- !
- case ( '(da+exp*db)/cos' )
- llf(:,jf,l) = ff * ( da(l) + exp_hh*db(l) ) / cos(lat(jf))
-
- !
- ! error ...
- !
- case default
- print *, 'IntLat_sh_ll - unknown key "'//trim(key)//'"'
- stop
- end select
- end do ! loop over levels
- ! copy to southpole ..
- if ( (jf==1) .and. aver_to_prev ) then
- do l = 1, lm
- llf(:,0,l) = sum(llf(:,1,l)) / size(llf,1)
- end do
- aver_to_prev = .false.
- end if
- end do ! loop over rows in fine grid
- ! integral in lat direction:
- do l = 1, lm
- do i = 0, lli%im
- ilast = 1
- llf_row = llf(i,:,l)
- call IntervalQuad_Lin( lat, llf_row, lli%blat(j-1), lli%blat(j), ll_u(i,j,l), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- end do
- end do ! loop over rows
- ! free memory
- call Done( sh )
- deallocate( Pnm )
- deallocate( ff )
- deallocate( exp_hh )
- deallocate( llf )
- deallocate( llf_row )
- deallocate( lat )
-
- ! ok
- status = 0
- end subroutine IntLat_sh_ll
-
- ! ***
-
- ! ***
-
-
- subroutine IntLat_shi_ll( key,shi_in,nlev, F, H, da, db, lli, ll_u, status )
-
- use grid_tools, only : deg2rad, pi
-
- use Num, only : IntervalQuad_Lin
- use Grid_Type_sh, only : TshGridInfo, TshGrid, Init, Done, Set, Check
- use Grid_Type_sh, only : sh_Pnm, Eval_Lons, SpN
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -----------------------------------------
-
- character(len=*), intent(in) :: key
- type(TshGridInfo), intent(in) :: shi_in
- integer, intent(in) :: nlev
- complex, intent(in) :: F(shi_in%np,nlev)
- complex, intent(in) :: H(shi_in%np)
- real, intent(in) :: da(nlev)
- real, intent(in) :: db(nlev)
- type(TllGridInfo), intent(in) :: lli
- real, intent(inout) :: ll_u(0:lli%im,lli%jm,nlev)
- integer, intent(out) :: status
-
- ! --- const --------------------------------------
-
- character(len=*), parameter :: rname = mname//'/IntLat_shi_ll'
-
- ! --- local ------------------------------------------
-
- integer :: i, j, jf
- integer :: l, lm
- integer :: ilast
-
- type(TshGridInfo) :: shi
- integer :: T
- ! type(TshGrid) :: sh
- real, allocatable :: Pnm(:)
-
- integer :: refinement_j
-
- integer :: nlon_fine_360, nlon_fine
- real, allocatable :: ff(:)
- real, allocatable :: exp_hh(:)
- real, allocatable :: llf(:,:,:), lat(:), llf_row(:)
-
- logical :: aver_to_prev
-
- ! --- begin ------------------------------------------
-
- T = ShTruncation( shi_in%T, lli%dlon_deg, lli%dlat_deg )
- ! T = ShTruncation( T, lli%dlon_deg, lli%dlat_deg )
- call Init( shi, T,status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- ! allocate space for legendre coeff:
- allocate( Pnm(shi%np) )
- ! determine refinement based on spectral resolution
- ! and length of required integration interval:
- refinement_j = ShRefinement( shi%T, lli%dlat_deg )
- ! number of lons in fine grid on complete circle:
- nlon_fine_360 = 360.0/lli%dlon_deg
- nlon_fine = lli%im
- ! store evaluation of spectral field:
- allocate( ff(0:nlon_fine) )
- allocate( exp_hh(0:nlon_fine) )
- ! ll in lon, fine in lat
- allocate( llf(0:lli%im,0:refinement_j,nlev) )
- allocate( llf_row(0:refinement_j) )
- allocate( lat(0:refinement_j) )
- ! loop over latitudes in ll grid:
- aver_to_prev = .false.
- do j = 1, lli%jm
- ! loop over latitudes in fine grid:
- do jf = 0, refinement_j
-
- ! latitude in fine grid:
- lat(jf) = lli%blat(j-1) + jf*lli%dlat/refinement_j
-
- ! southpole ?
- if ( abs(lat(jf) - (-pi/2)) < 1.0e-4 ) then
- ! fill with average of next row
- aver_to_prev = .true.
- cycle
- end if
-
- ! northpole ?
- if ( abs(lat(jf) - (pi/2)) < 1.0e-4 ) then
- ! fill with average of previous row:
- do l = 1, nlev
- llf(:,jf,l) = sum(llf(:,jf-1,l)) / size(llf,1)
- end do
- exit
- end if
- ! evaluate Legendre functions:
- call sh_Pnm( Pnm, shi%T, lat(jf), status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- ! evaluate rows:
- call Eval_Lons( shi_in, H, shi, Pnm, nlon_fine_360, lli%blon(0), nlon_fine+1,exp_hh, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- exp_hh = exp(exp_hh)
- do l = 1, nlev
- call Eval_Lons( shi_in, (/F(:,l)/), shi, Pnm, nlon_fine_360, lli%blon(0), nlon_fine+1,ff, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- ! combine fields:
- select case ( key )
- !
- ! [ int exp(H) dlat ] / deltalat
- !
- case ( 'exp(H),aver' )
- llf(:,jf,l) = exp_hh / lli%dlat
- !
- ! int F (da+db*exp(H)) / cos(lat) dlat
- !
- case ( '(da+exp*db)/cos' )
- llf(:,jf,l) = ff * ( da(l) + exp_hh*db(l) ) / cos(lat(jf))
-
- !
- ! error ...
- !
- case default
- print *, 'IntLat_sh_ll - unknown key "'//trim(key)//'"'
- stop
- end select
- end do ! loop over levels
- ! copy to southpole ..
- if ( (jf==1) .and. aver_to_prev ) then
- do l = 1, nlev
- llf(:,0,l) = sum(llf(:,1,l)) / size(llf,1)
- end do
- aver_to_prev = .false.
- end if
- end do ! loop over rows in fine grid
- ! integral in lat direction:
- do l = 1, nlev
- do i = 0, lli%im
- ilast = 1
- llf_row = llf(i,:,l)
- call IntervalQuad_Lin( lat, llf_row, lli%blat(j-1), lli%blat(j), ll_u(i,j,l), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- end do
- end do ! loop over rows
- ! free memory
- call Done( shi )
- deallocate( Pnm )
- deallocate( ff )
- deallocate( exp_hh )
- deallocate( llf )
- deallocate( llf_row )
- deallocate( lat )
- ! ok
- status = 0
- end subroutine IntLat_shi_ll
-
- ! ***
- subroutine IntLon_sh_ll( key, F, H, da, db, lli, ll_v, status )
-
- use grid_tools, only : deg2rad, pi
-
- use Num, only : IntervalQuad_Lin
- use Grid_Type_sh, only : TshGrid, Init, Done, SpN, Set, Check
- use Grid_Type_sh, only : sh_Pnm, Eval_Lons
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -----------------------------------------
-
- character(len=*), intent(in) :: key
- type(TshGrid), intent(in) :: F(:)
- type(TshGrid), intent(in) :: H
- real, intent(in) :: da(size(F))
- real, intent(in) :: db(size(F))
- type(TllGridInfo), intent(in) :: lli
- real, intent(inout) :: ll_v(lli%im,0:lli%jm,size(F))
- integer, intent(out) :: status
-
- ! --- const --------------------------------------
-
- character(len=*), parameter :: rname = mname//'/IntLon_sh_ll'
-
- ! --- local ------------------------------------------
-
- integer :: i, j
- integer :: l, lm
- integer :: ilast
-
- integer :: T
- type(TshGrid) :: sh
- real, allocatable :: Pnm(:)
-
- integer :: refinement_i
-
- integer :: nlon_fine_360, nlon_fine
- real, allocatable :: ff(:)
- real, allocatable :: exp_hh(:)
- real, allocatable :: lons_fine(:), row_fine(:)
-
- logical :: pole
-
- ! --- begin ------------------------------------------
- ! number of levels:
- lm = size(F)
-
- ! check arguments:
- call Check( H )
- T = H%T
- do l = 1, lm
- call Check( F(l), T )
- end do
- ! use truncated harmonics ?
- T = ShTruncation( T, lli%dlon_deg, lli%dlat_deg )
- call Init( sh, T )
-
- ! allocate space for legendre coeff:
- allocate( Pnm(SpN(T)) )
- ! determine refinement based on spectral resolution
- ! and length of required integration interval:
- refinement_i = ShRefinement( T, lli%dlon_deg )
- ! number of lons in fine grid on complete circle:
- nlon_fine_360 = 360.0/lli%dlon_deg * refinement_i
- nlon_fine = lli%im * refinement_i
-
- ! store evaluation of spectral field:
- allocate( ff(0:nlon_fine) )
- allocate( exp_hh(0:nlon_fine) )
-
- ! lons on arc westb+[0,..)
- allocate( row_fine(0:nlon_fine) )
- allocate( lons_fine(0:nlon_fine) )
- do i = 0, nlon_fine
- lons_fine(i) = i*2*pi/nlon_fine_360
- end do
- lons_fine = lli%blon(0) + lons_fine
-
- ! loop over boundary latitudes in ll grid:
- do j = 0, lli%jm
-
- ! pole ? then int f(x) dx = f
- pole = ( abs(lli%blat(j) - (-pi/2)) < 1.0e-4 ) .or. &
- ( abs(lli%blat(j) - ( pi/2)) < 1.0e-4 )
- ! evaluate Legendre functions:
- call sh_Pnm( Pnm, T, lli%blat(j), status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- ! evaluate rows:
- call Set( sh, T, H )
- call Eval_Lons( exp_hh, sh, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- exp_hh = exp(exp_hh)
- ! loop over levels
- do l = 1, lm
- call Set( sh, T, F(l) )
- call Eval_Lons( ff, sh, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- ! combine fields:
- select case ( key )
- !
- ! [ int exp(H) dlon ] / deltalon
- !
- case ( 'exp(H),aver' )
-
- if ( pole ) then
- row_fine = exp_hh
- else
- row_fine = exp_hh / lli%dlon
- end if
- !
- ! int F (da+db*exp(H)) dlon
- !
- case ( '(da+exp*db)' )
- if ( pole ) then
- row_fine = 0.0
- else
- row_fine = ff * ( da(l) + exp_hh*db(l) )
- end if
- !
- ! error ...
- !
- case default
- print *, 'IntLon_sh_ll - unknown key "'//trim(key)//'"'
- stop
- end select
- ! special treatment of poles:
- if ( pole ) then
- ! same value at al 'longitudes', thus for example the average ...
- ll_v(:,j,l) = sum(row_fine)/size(row_fine)
- else
- ! integral in lon direction assuming linear interpolation,
- ! result in [sh] rad
- ilast = 1
- do i = 1, lli%im
- call IntervalQuad_Lin( lons_fine, row_fine, lli%blon(i-1), lli%blon(i), ll_v(i,j,l), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- end if
- end do ! loop over levels
-
- end do ! loop over rows
- ! free memory
- call Done( sh )
- deallocate( Pnm )
- deallocate( ff )
- deallocate( exp_hh )
- deallocate( lons_fine )
- deallocate( row_fine )
-
- ! ok
- status = 0
-
- end subroutine IntLon_sh_ll
-
- ! ***
- subroutine IntLon_shi_ll( key, shi_in,nlev, F, H, da, db, lli, ll_v, status )
-
- use grid_tools, only : deg2rad, pi
-
- use Num, only : IntervalQuad_Lin
- use Grid_Type_sh, only : TshGridInfo, TshGrid, Init, Done, SpN, Set, Check
- use Grid_Type_sh, only : sh_Pnm, Eval_Lons
- use Grid_Type_ll, only : TllGridInfo, Check
-
- ! --- in/out -----------------------------------------
-
- character(len=*), intent(in) :: key
- type(TshGridInfo), intent(in) :: shi_in
- integer, intent(in) :: nlev
- complex, intent(in) :: F(shi_in%np,nlev)
- complex, intent(in) :: H(shi_in%np)
- real, intent(in) :: da(nlev)
- real, intent(in) :: db(nlev)
- type(TllGridInfo), intent(in) :: lli
- real, intent(inout) :: ll_v(lli%im,0:lli%jm,nlev)
- integer, intent(out) :: status
-
- ! --- const --------------------------------------
-
- character(len=*), parameter :: rname = mname//'/IntLon_shi_ll'
-
- ! --- local ------------------------------------------
-
- integer :: i, j
- integer :: l
- integer :: ilast
- type(TshGridInfo) :: shi
- integer :: T
- ! type(TshGrid) :: sh
- real, allocatable :: Pnm(:)
-
- integer :: refinement_i
-
- integer :: nlon_fine_360, nlon_fine
- real, allocatable :: ff(:)
- real, allocatable :: exp_hh(:)
- real, allocatable :: lons_fine(:), row_fine(:)
-
- logical :: pole
-
- ! --- begin ------------------------------------------
- ! use truncated harmonics ?
- T = ShTruncation( shi_in%T, lli%dlon_deg, lli%dlat_deg )
- ! T = ShTruncation( T, lli%dlon_deg, lli%dlat_deg )
- call Init( shi, T ,status)
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
-
- ! allocate space for legendre coeff:
- allocate( Pnm(shi%np) )
- ! determine refinement based on spectral resolution
- ! and length of required integration interval:
- refinement_i = ShRefinement( shi%T, lli%dlon_deg )
- ! number of lons in fine grid on complete circle:
- nlon_fine_360 = 360.0/lli%dlon_deg * refinement_i
- nlon_fine = lli%im * refinement_i
-
- ! store evaluation of spectral field:
- allocate( ff(0:nlon_fine) )
- allocate( exp_hh(0:nlon_fine) )
-
- ! lons on arc westb+[0,..)
- allocate( row_fine(0:nlon_fine) )
- allocate( lons_fine(0:nlon_fine) )
- do i = 0, nlon_fine
- lons_fine(i) = i*2*pi/nlon_fine_360
- end do
- lons_fine = lli%blon(0) + lons_fine
-
- ! loop over boundary latitudes in ll grid:
- do j = 0, lli%jm
-
- ! pole ? then int f(x) dx = f
- pole = ( abs(lli%blat(j) - (-pi/2)) < 1.0e-4 ) .or. &
- ( abs(lli%blat(j) - ( pi/2)) < 1.0e-4 )
- ! evaluate Legendre functions:
- call sh_Pnm( Pnm, shi%T, lli%blat(j), status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- ! evaluate rows:
- ! call Set( sh, T, H )
- ! call Eval_Lons( exp_hh, sh, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, status )
- call Eval_Lons( shi_in,H,shi,Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1,exp_hh, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- exp_hh = exp(exp_hh)
- ! loop over levels
- do l = 1, nlev
- ! call Set( sh, T, F(l) )
- ! call Eval_Lons( ff, sh, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, status )
- call Eval_Lons( shi_in,F(:,l), shi, Pnm, nlon_fine_360, lons_fine(0), nlon_fine+1, ff,status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- ! combine fields:
- select case ( key )
- !
- ! [ int exp(H) dlon ] / deltalon
- !
- case ( 'exp(H),aver' )
-
- if ( pole ) then
- row_fine = exp_hh
- else
- row_fine = exp_hh / lli%dlon
- end if
- !
- ! int F (da+db*exp(H)) dlon
- !
- case ( '(da+exp*db)' )
- if ( pole ) then
- row_fine = 0.0
- else
- row_fine = ff * ( da(l) + exp_hh*db(l) )
- end if
- !
- ! error ...
- !
- case default
- print *, 'IntLon_sh_ll - unknown key "'//trim(key)//'"'
- stop
- end select
- ! special treatment of poles:
- if ( pole ) then
- ! same value at al 'longitudes', thus for example the average ...
- ll_v(:,j,l) = sum(row_fine)/size(row_fine)
- else
- ! integral in lon direction assuming linear interpolation,
- ! result in [sh] rad
- ilast = 1
- do i = 1, lli%im
- call IntervalQuad_Lin( lons_fine, row_fine, lli%blon(i-1), lli%blon(i), ll_v(i,j,l), ilast, status )
- if (status/=0) then; write (*,'("ERROR in ",a)') rname; status=1; return; end if
- end do
- end if
- end do ! loop over levels
-
- end do ! loop over rows
- ! free memory
- call Done( shi )
- deallocate( Pnm )
- deallocate( ff )
- deallocate( exp_hh )
- deallocate( lons_fine )
- deallocate( row_fine )
-
- ! ok
- status = 0
-
- end subroutine IntLon_shi_ll
- end module Grid_Interpol
|