12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335 |
- /* c++ -O2 -o burn7.x burn7.cpp -lm -lnetcdf_c++ -lnetcdf */
- #define NETCDF_OUTPUT
- #define V0 "burn 7.7 (02-Feb-2017)"
- #define V1 "KlimaCampus"
- #define V2 "Usage: burn7 [-help|-c|-d|-m|-n|-r|-s] <modelfile> <resultfile>"
- #define V3 "New: option <-g> writes Grads ctl for service plotting"
- #define V4 "New: comments (#) are allowed in namelist file"
- /* ============= */
- /* include files */
- /* ============= */
- #include <ctype.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <time.h>
- #include <sys/resource.h>
- #include <vector>
- #include <valarray>
- #ifdef OPEN_MP
- #include <omp.h>
- #endif
- #ifdef NETCDF_OUTPUT
- #include <netcdfcpp.h>
- #endif
- using namespace std;
- #define LONG long long
- #ifndef M_PI
- #define M_PI 3.1415926535
- #endif
- #ifndef M_SQRT2
- #define M_SQRT2 1.4142136
- #endif
- #ifndef MAX
- #define MAX(v1,v2) ((v1) > (v2) ? (v1) : (v2))
- #endif
- #ifndef min
- #define min(v1,v2) ((v1) < (v2) ? (v1) : (v2))
- #endif
- #ifndef abs
- #define abs(x) ((x) >= 0 ? (x) : -(x))
- #endif
- #ifndef TRUE
- #define TRUE 1
- #endif
- #ifndef FALSE
- #define FALSE 0
- #endif
- #define LEV_SURFACE 1
- #define LEV_99 99
- #define LEV_ISOBARIC 100
- #define LEV_MEANSEA 102
- #define LEV_ALTITUDE 103
- #define LEV_HEIGHT 105
- #define LEV_SIGMA 107
- #define LEV_HYBRID 109
- #define LEV_GROUND 112
- #define REP_REGULAR 0
- #define REP_GAUSS 4
- #define REP_SPECTRAL 50
- #define MAX_HOURS 4
- #define MAX_LEVELS 99
- #define MAX_NVCT (MAX_LEVELS * 2 + 2)
- #define L_TIMES_RHOH2O (-333700000.0)
- #define EARTH_RADIUS 6371220.0
- #define MARS_RADIUS 3400000.0
- #define SQUARE_RADIUS (-PlanetRadius * PlanetRadius)
- #define EARTH_GRAV 9.80665
- #define MARS_GRAV 3.728
- #define RG (1.0 / Grav)
- #define MARS_RD (189.0 )
- /* ************************************** */
- /* Thermodynamical constants adopted from */
- /* ECMWF IFS-Code */
- /* ************************************** */
- #define RKBOL (1.380658e-23)
- #define RNAVO (6.0221367e+23)
- #define R (RKBOL * RNAVO)
- #define RMD (28.9644)
- #define RMV (18.0153)
- #define EARTH_RD (1000. * R / RMD)
- #define RV (1000. * R / RMV)
- #define RCPD (3.5 * RD)
- #define RCPV (4.0 * RV)
- #define RETV (RV / RD - 1.)
- #define RCW (4218.)
- #define RCS (2106.)
- #define RTT (273.16)
- #define RLVTT (2.5008e+6)
- #define RLSTT (2.8345e+6)
- #define RESTT (611.14)
- #define RLAPSE (0.0065)
- #ifdef NETCDF_OUTPUT
- NcFile *NetFile;
- NcVar *LonVar;
- NcVar *LatVar;
- NcVar *LevVar;
- NcVar *TimVar;
- NcDim *LonDim;
- NcDim *LatDim;
- NcDim *LevDim;
- NcDim *TimDim;
- #endif
- int SaveMemory = 0; /* Switch on for dynamic memory usage */
- int PolyCreate = 0; /* Create polynomials files for hires T1365 and more */
- int PolyDisk = 0; /* Read polynomials from disk */
- int GaussGrid = -1; /* 1: use Gaussian grid, 0: use regular grid */
- int DPM = 0; /* Days Per Month */
- int DPY = 0; /* Days Per Year */
- int DayDivisor = 0; /* Use for day adjustment if more than 99 days per month */
- char VerType; /* s=Sigma p=Pressure */
- char HorType; /* s=Spherical f=Fourier z=Zonal Mean g=Gauss Grid */
- char *filename;
- char ifile[256]; // name of input file (PUMA-II format)
- char ofile[256]; // Name of output file (Service or NetCDF format)
- char gfile[256]; // Name of Grads control file
- char rfile[256]; // Name of Grads data file (for zonal means only)
- #define MAX_NL 40960
- char namelist[MAX_NL];
- char AllocName[256];
- int PumaCode;
- int PumaLevel;
- int RepGrib;
- int Debug;
- int Dim3FC ;
- int Dim3SP ;
- int Dim3GG ;
- int Dim3GP ;
- int DimFC ; // Dimension of fourier array
- int DimGP ; // Dimension of output grid
- int DimGG ; // Dimension of Gauss grid
- int DimAB ; // Dimension of array buffer
- int DimSP ;
- int DimSP_half ;
- int CoreBigEndian ; // Do we run on a big endian machine ?
- int FileBigEndian ;
- int Endian = 0 ; /* Marker for reverse endian format */
- int LongFCW = 0 ; /* Flag for 64bit (1) or 32bit (0) FCW's */
- int RealSize = 4 ; /* Size of real data (4 = float) (8 = double) */
- int HeadSize = 32 ; // 32:Service single 64:Service double
- int EndOfMonth ;
- int EndOfTerm ;
- int Fouriers ;
- int HumInfo ; // Flag for humidity info issued
- double Grav = EARTH_GRAV;
- double SigmaTop = 0.0;
- int NetCDF ;
- int GaussianOutput = 1;
- int Grads ;
- int HeaderWords ; /* Length of file header in 32-bit words */
- int Gats ;
- int Lats ;
- int AllLevs = 0 ; // # of sigma levels in data file
- int SigLevs = 0 ; // # of sigma levels used
- int SingleLevel = 0 ; // Set to true for SAM/SOM models
- double LevelFactor = 1.0 ; // Multiplier for head(2)
- int LevelType ;
- int Gons ;
- int Lons ;
- int Cyclical = 0 ; // 1 = Cyclical completion (Lons from 0 to 360)
- double L_times_rhoH2O = L_TIMES_RHOH2O;
- int mars ;
- int Mean ;
- int MeanCount ; // Count terms during month
- int Multi ;
- int FirstMonth = 1;
- int LastMonth = 12;
- double PlanetRadius= EARTH_RADIUS;
- double RD = EARTH_RD;
- int Spectral = FALSE;
- int TermCount ;
- int MonthCount ;
- int OutputCount ;
- int Truncation = 0;
- int Waves ;
- int SpecialUV ;
- struct tm NewDate;
- struct tm OldDate;
- int NewMonth;
- int OldMonth;
- // Some functions for a nice printout
- #define COLS 72
- void Stars(int n) {while (n--) putchar('*');}
- void ErrStars(int n) {while (n--) putc('*',stderr);}
- void Blanks(int n) {while (n--) putchar(' ');}
- void Dashes(int n) {while (n--) putchar('-');}
- void NewLine(void) {putchar('\n');}
- void ErrNewLine(void) {putc('\n',stderr);}
- void StarLine(void) {Stars(COLS); NewLine();}
- /* ==================================== */
- /* Abort - Print error message and exit */
- /* ==================================== */
- void Abort(const char *errtext)
- {
- Stars(min(80,strlen(errtext))); NewLine();
- puts(errtext); NewLine();
- Stars(min(80,strlen(errtext))); NewLine();
- ErrStars(min(80,strlen(errtext))); ErrNewLine();
- fputs(errtext,stderr); ErrNewLine();
- ErrStars(min(80,strlen(errtext))); ErrNewLine();
- exit(1);
- }
- void BlankLine(void)
- {
- putchar('*');
- Blanks(COLS-2);
- putchar('*');
- NewLine();
- }
- void DashLine(void)
- {
- putchar('*');
- putchar(' ');
- Dashes(COLS-4);
- putchar(' ');
- putchar('*');
- NewLine();
- }
- void CenterText(const char *t)
- {
- int i,j,l;
- l = strlen(t);
- if (l < 1) return;
- if (l > COLS-4) puts(t);
- else
- {
- i = (COLS - 4 - l) / 2;
- j = (COLS - 4 - l - i);
- putchar('*');
- Blanks(i+1);
- fputs(t,stdout);
- Blanks(j+1);
- putchar('*');
- NewLine();
- }
- }
- void LeftText(const char *t)
- {
- int l;
- l = strlen(t);
- if (l < 1) return;
- if (l > COLS-4) puts(t);
- else
- {
- putchar('*');
- putchar(' ');
- fputs(t,stdout);
- Blanks(COLS - l - 3);
- putchar('*');
- NewLine();
- }
- }
- #define MAX_ID_LEN 8
- #define MAX_NA_LEN 32
- #define MAX_UN_LEN 16
- class Control
- {
- public:
- int readit ;
- int needed ;
- int selected ;
- int detected ;
- int hlev ;
- int plev ;
- int loff ;
- int twod ;
- int code ;
- valarray<double>hsp;
- valarray<double>hfc;
- valarray<double>hgp;
- valarray<double>pgp;
- valarray<double>mgp;
- valarray<double>pfc;
- valarray<double>psp;
- char Id[MAX_ID_LEN];
- char Na[MAX_NA_LEN];
- char Un[MAX_UN_LEN];
- #ifdef NETCDF_OUTPUT
- NcVar *NetVar ;
- #endif
- void Status(void);
- void Init(const char* Idf, const char *Name, const char *Units, int TwoD);
- void SetHSpec(int Hlev, int Plev, int Twod);
- void SetHFour(int Hlev, int Plev, int Twod);
- void SetHGrid(int Hlev, int Plev, int Twod);
- void SetPGrid(void);
- void SetPFour(void);
- void SetPSpec(void);
- };
- void Control::Status(void)
- {
- printf("\nStatus for code %3d: %s\n",code,Id);
- printf("-------------------------\n");
- printf("needed: %5d\n",needed);
- printf("selected: %5d\n",selected);
- printf("detected: %5d\n",detected);
- printf("hlev: %5d\n",hlev);
- printf("plev: %5d\n",plev);
- printf("twod: %5d\n",twod);
- printf("hsp: %5ld\n",hsp.size());
- printf("hfc: %5ld\n",hfc.size());
- printf("hgp: %5ld\n",hgp.size());
- printf("pgp: %5ld\n",pgp.size());
- printf("mean: %5ld\n",mgp.size());
- printf("pfc: %5ld\n",pfc.size());
- printf("psp: %5ld\n",psp.size());
- if (hgp.size()) printf("mean of hgp: %16.10lf\n",hgp.sum() / hgp.size());
- if (pgp.size()) printf("mean of pgp: %16.10lf\n",pgp.sum() / pgp.size());
- };
- void Control::Init(const char* Idf, const char *Name, const char *Units, int TwoD)
- {
- strncpy(Id,Idf ,MAX_ID_LEN-1);
- strncpy(Na,Name ,MAX_NA_LEN-1);
- strncpy(Un,Units,MAX_UN_LEN-1);
- twod = TwoD;
- }
- void Control::SetHSpec(int Hlev, int Plev, int Twod)
- {
- int OldSize;
- int NewSize;
- hlev = Hlev;
- plev = Plev;
- twod = Twod;
- OldSize = hsp.size();
- NewSize = Hlev * DimSP;
- if (NewSize == OldSize) return;
- hsp.resize(NewSize);
- if (Debug)
- {
- char tb[COLS];
- if (OldSize == 0)
- sprintf(tb,"Alloc: %p %6s[%3d].hsp %6ld double",&hsp[0],Id,code,hsp.size());
- else
- sprintf(tb,"Realloc: %p %6s[%3d].hsp %6ld double",&hsp[0],Id,code,hsp.size());
- LeftText(tb);
- }
- }
- void Control::SetHFour(int Hlev, int Plev, int Twod)
- {
- if (hfc.size() == Hlev * DimFC) return;
- hlev = Hlev;
- plev = Plev;
- twod = Twod;
- hfc.resize(hlev * DimFC);
- if (Debug)
- {
- char tb[COLS];
- sprintf(tb,"Alloc: %p %6s[%3d].hfc %6ld double",&hfc[0],Id,code,hfc.size());
- LeftText(tb);
- }
- }
- void Control::SetPFour(void)
- {
- if (pfc.size() == plev * DimFC) return;
- pfc.resize(plev * DimFC);
- if (Debug)
- {
- char tb[COLS];
- sprintf(tb,"Alloc: %p %6s[%3d].pfc %6ld double",&pfc[0],Id,code,pfc.size());
- LeftText(tb);
- }
- }
- void Control::SetHGrid(int Hlev, int Plev, int Twod)
- {
- if (hgp.size() == Hlev * DimGP) return;
- hlev = Hlev;
- plev = Plev;
- twod = Twod;
- hgp.resize(hlev * DimGP);
- if (Debug)
- {
- char tb[COLS];
- sprintf(tb,"Alloc: %p %6s[%3d].hgp %6d double",&hgp[0],Id,code,hlev*DimGP);
- LeftText(tb);
- }
- }
-
- void Control::SetPGrid(void)
- {
- if (twod && hgp.size())
- {
- pgp.resize(DimGP);
- pgp = hgp;
- hgp.resize(0);
- if (Debug)
- {
- char tb[COLS];
- sprintf(tb,"Moved: %p %6s[%3d].hgp to pgp",&pgp[0],Id,code);
- LeftText(tb);
- }
- }
- else if (pgp.size() != plev * DimGP)
- {
- pgp.resize(plev * DimGP);
- if (Debug)
- {
- char tb[COLS];
- sprintf(tb,"Alloc: %p %6s[%3d].pgp %6d double",&pgp[0],Id,code,plev*DimGP);
- LeftText(tb);
- }
- }
- }
-
- void Control::SetPSpec(void)
- {
- int OldSize;
- int NewSize;
- OldSize = psp.size();
- NewSize = plev * DimSP;
- if (NewSize == OldSize) return;
- psp.resize(NewSize);
- if (Debug)
- {
- char tb[COLS];
- if (OldSize == 0)
- sprintf(tb,"Alloc: %p %6s[%3d].psp %6ld double",&psp[0],Id,code,psp.size());
- else
- sprintf(tb,"Realloc: %p %6s[%3d].psp %6ld double",&psp[0],Id,code,psp.size());
- LeftText(tb);
- }
- }
- #define CODES 512
- #define MAXCODES (CODES+5)
- #define GEOSCODE 129
- #define TCODE 130
- #define UCODE 131
- #define VCODE 132
- #define SHCODE 133
- #define PSCODE 134
- #define WCODE 135
- #define WZCODE 137
- #define VORCODE 138
- #define STRCODE 148
- #define VELCODE 149
- #define SLPCODE 151
- #define LNPSCODE 152
- #define DIVCODE 155
- #define ZCODE 156
- #define RHCODE 157
- int SpecialCodes[4] = {DIVCODE,VORCODE,STRCODE,VELCODE};
- Control All[MAXCODES];
- Control *Geopotential = &All[129];
- Control *Temperature = &All[130];
- Control *u_wind = &All[131];
- Control *v_wind = &All[132];
- Control *Humidity = &All[133];
- Control *Ps = &All[134];
- Control *Omega = &All[135];
- Control *w_wind = &All[137];
- Control *Vorticity = &All[138];
- Control *Ts = &All[139];
- Control *StreamF = &All[148];
- Control *VeloPot = &All[149];
- Control *SLP = &All[151];
- Control *LnPs = &All[152];
- Control *Divergence = &All[155];
- Control *GeopotHeight = &All[156];
- Control *Rhumidity = &All[157];
- Control *speed = &All[259];
- Control *precip = &All[260];
- Control *net_top = &All[261];
- Control *net_bot = &All[262];
- Control *net_heat = &All[263];
- Control *net_water = &All[264];
- Control *sw_atm = &All[268];
- Control *lw_atm = &All[269];
- Control *net_atm = &All[270];
- Control *surf_runoff = &All[271];
- Control *dpsdx = &All[273];
- Control *dpsdy = &All[274];
- Control *fresh_water = &All[275];
- Control *HalfPress = &All[277];
- Control *FullPress = &All[278];
- Control *ThetaH = &All[279];
- Control *ThetaF = &All[280];
- int *vert_index;
- valarray<double>Orography;
- double *poli;
- double *pol2;
- double *pliu;
- double *pliv;
- char polin[80]; /* filenames for polynomial files */
- char pol2n[80];
- char pliun[80];
- char plivn[80];
- FILE *polif;
- FILE *pol2f;
- FILE *pliuf;
- FILE *plivf;
- int OutLevs; /* number of requested output levels */
- int nrpl; /* number of requested pressure levels */
- int nrml; /* number of requested model levels */
- int nrqh;
- #define ATTR_MAX 20
- int nattr; /* number of global attributes (NetCDF) */
- char AttrNam[ATTR_MAX][80];
- char AttrVal[ATTR_MAX][80];
- int nvct = 0;
- double vct[MAX_NVCT];
- int DaysPerYear = 360;
- double DataStep = 0.0;
- int DeltaDy;
- int DeltaHr;
- int DeltaMn;
- vector<int>HeadSt(8,0); // First header vector
- vector<int>HeadIn(8,0); // Input header vector
- vector<int>HeadOu(8,0); // Output header vector
- #define HYB_SPEC 0
- #define HYB_FOUR 1
- #define HYB_ZONM 2
- #define HYB_GRID 3
- #define PRE_GRID 4
- #define PRE_FOUR 5
- #define PRE_ZONM 6
- #define PRE_SPEC 7
- int OutRep = HYB_SPEC; // Output Representation
- int hours[MAX_HOURS+1];
- double level[MAX_LEVELS+1];
- int LevelFound[MAX_LEVELS+1];
- double hPa[MAX_LEVELS];
- int mol[MAX_LEVELS];
- int mom[MAX_LEVELS]; /* Mask for selected levels */
- int LevelUnits[MAX_LEVELS];
- int SigmaF[MAX_LEVELS];
- double *Record_double;
- float *Record_float; // Buffer for FORTRAN records
- int *Record_int; // All share the same space
- unsigned short *Record_short;
- char *Record_char;
- double *CosPhi; /* Cosine of Phi (Latitude) */
- double *RevCosPhi; /* 1.0 / CosPhi */
- double *DerivationFactor;
- double *wfc; /* FFT work array */
- double *wgp; /* FFT work array */
- int ifax[10]; /* FFT factorization */
- FILE *fpi;
- FILE *gp;
-
- class RegLon // class for equidistant longituinal array
- {
- char Name[16]; // Array name
- double DeltaLam; // Distance of Longitudes
- public:
- int Lons; // Number of latitudes
- double *Lam; // Coordinate in degrees
- RegLon(int, const char *); // Constructor
- ~RegLon(void); // Destructor
- void PrintArray(void); // Print table
- };
- RegLon::RegLon(int n, const char *name)
- {
- int jlon;
- Lons = n;
- DeltaLam = 360.0 / Lons;
- Lam = new double[Lons+1];
- for (jlon=0 ; jlon < Lons ; ++jlon)
- {
- Lam[jlon] = jlon * DeltaLam;
- }
- Lam[Lons] = 360.0;
- strncpy(Name,name,15);
- }
- RegLon::~RegLon(void)
- {
- delete Lam;
- }
- void RegLon::PrintArray(void)
- {
- int jlon;
- printf("*******************************\n");
- printf("* %16.16s Longitude *\n",Name);
- printf("*******************************\n");
- for (jlon=0 ; jlon < Lons ; ++jlon)
- printf("* %16d %10.4f *\n",jlon,Lam[jlon]);
- printf("*******************************\n");
- }
- class RegLat // class for equidistant latitudinal array
- {
- char Name[16]; // Array name
- double DeltaPhi; // Distance of latitudes
- double FirstPhi; // First latitude
- public:
- int Lats; // Number of latitudes
- double *Phi; // Coordinate in degrees
- double *gmu; // Sine of phi
- double *gwt; // Gaussian weight
- RegLat(int, const char *); // Constructor
- ~RegLat(void); // Destructor
- void PrintArray(void); // Print table
- };
- RegLat::RegLat(int n, const char *name)
- {
- int jlat;
- Lats = n;
- DeltaPhi = 180.0 / (Lats - 1);
- Phi = new double[Lats];
- gmu = new double[Lats];
- gwt = new double[Lats];
- if (Lats & 1) /* odd -> start with DeltaPhi */
- {
- DeltaPhi = 180.0 / (Lats + 1);
- FirstPhi = 90.0 - DeltaPhi;
- }
- else /* even -> start with 0.5 DeltaPhi */
- {
- DeltaPhi = 180.0 / Lats;
- FirstPhi = 90.0 - 0.5 * DeltaPhi;
- }
- for (jlat=0 ; jlat < Lats ; ++jlat)
- {
- Phi[jlat] = FirstPhi - jlat * DeltaPhi;
- gmu[jlat] = sin(Phi[jlat] * M_PI / 180.0);
- gwt[jlat] = 0.0;
- }
- strncpy(Name,name,15);
- }
- RegLat::~RegLat(void)
- {
- delete Phi;
- delete gmu;
- delete gwt;
- }
- void RegLat::PrintArray(void)
- {
- int jlat;
- printf("*******************************\n");
- printf("* %16.16s Latitude *\n",Name);
- printf("*******************************\n");
- for (jlat=0 ; jlat < Lats ; ++jlat)
- printf("* %16d %10.4f *\n",jlat,Phi[jlat]);
- printf("*******************************\n");
- }
- class GauLat : public RegLat
- {
- public:
- GauLat(int, const char *); // Constructor
- ~GauLat(void); // Destructor
- private:
- void IniGau(void);
- double nlp(int, double);
- double dlp(int, double);
- };
- GauLat::GauLat(int n, const char *name) : RegLat(n, name)
- {
- int jlat;
- IniGau();
- for (jlat = 0 ; jlat < Lats ; ++jlat)
- Phi[jlat] = 180.0 * asin(gmu[jlat]) / M_PI;
- }
- GauLat::~GauLat(void)
- {
- }
- /* ============================== */
- /* Calculate Legendre Polynomials */
- /* ============================== */
- double GauLat::nlp(int k, double p) // After Nodorp (1988)
- {
- int j;
- double z0,z1,z2,z3,z4;
- z0 = acos(p);
- z1 = 1.0;
- z2 = 0.0;
- z3 = 0.0;
-
- for (j=k ; j >= 0 ; j-=2)
- {
- z3 = z1 * cos(j * z0);
- z2 += z3;
- z4 = (k-j+1) * (k+j)/2;
- z1 *= z4 / (z4+j-1);
- }
- if (k % 2 == 0) z2 -= 0.5 * z3;
- z0 = sqrt(2.0);
- for (j=1; j <= k ; ++j)
- z0 *= sqrt(1.0 - 0.25/(j*j));
- return (z0*z2);
- }
- /* ============================================= */
- /* Calculate Derivatives of Legendre Polynomials */
- /* ============================================= */
- double GauLat::dlp(int k, double p) // After Nodorp (1988)
- {
- double z0,z3,z4;
- if (!k) return 0.0;
- z0 = 1.0 / (p*p - 1.0);
- z3 = sqrt((k+k+1.0)/(k+k-1.0));
- z4 = p * nlp(k,p) - z3 * nlp(k-1,p);
- return(k*z0*z4);
- }
- void GauLat::IniGau(void)
- {
- int jlat,Iter;
- double z0, z1, z2, z3;
- double eps=1.e-15;
- z0 = M_PI / (2 * Lats + 1);
- z1 = 1.0 / (8 * Lats * Lats);
- for (jlat=0 ; jlat < Lats/2 ; ++jlat) // North to Equator
- {
- z2 = (2 * jlat + 1.5) * z0;
- z2 = cos(z2 + z1 / tan(z2));
- Iter = 0;
- do
- {
- z3 = nlp(Lats,z2) / dlp(Lats,z2);
- z2 -= z3;
- } while ((z3 < -eps || z3 > eps) && ++Iter < 1000);
- gmu[jlat] = z2;
- gmu[Lats-1-jlat] = -z2;
- }
- z1 = 2.0 / (Lats * Lats);
- for (jlat=0 ; jlat < Lats/2 ; ++jlat) // North to Equator
- {
- z0 = nlp(Lats-1,gmu[jlat]) / sqrt(Lats - 0.5);
- z0 = z0 * z0;
- gwt[jlat] = z1 * (1.0 - gmu[jlat] * gmu[jlat]) / z0;
- gwt[Lats-1-jlat] = gwt[jlat];
- }
- }
- RegLon *Outlon;
- RegLat *Outlat;
- GauLat *Gaulat;
- #ifdef NETCDF_OUTPUT
- #define TITLE "PUMA/PLASIM DATA"
- #define HISTORY "Created by PumaBurner 7.4"
- void NetOpen(char *NetFileName)
- {
- int yy,mm,dd;
- int jlev;
- int jvar;
- int londim;
- double *Outlev;
- const char *title=TITLE;
- const char *conv="CF-1.0";
- const char *hist=HISTORY;
- char cale[80];
- char t_unit[80];
- int BaseDate[4];
- Outlev = new double[OutLevs];
- if (VerType == 's') // sigma
- {
- for (jlev = 0 ; jlev < OutLevs ; ++jlev)
- Outlev[jlev] = 0.5 *
- (vct[SigLevs+mol[jlev]]+vct[SigLevs+mol[jlev]+1]);
- }
- else // pressure levels [hPa]
- {
- for (jlev = 0 ; jlev < OutLevs ; ++jlev) Outlev[jlev] = hPa[jlev];
- }
- BaseDate[0] = yy = HeadSt[2] / 10000;
- BaseDate[1] = mm = HeadSt[2] / 100 % 100;
- BaseDate[2] = dd = HeadSt[2] % 100;
- BaseDate[3] = 0;
- if (Mean)
- {
- sprintf(t_unit,"months since %04d-%02d-%02d 00:00:00",yy,mm,dd);
- sprintf(cale,"360_day");
- }
- else
- {
- sprintf(t_unit,"days since %04d-%02d-%02d 00:00:00",yy,mm,dd);
- if (DaysPerYear != 365) sprintf(cale,"%d_day",DaysPerYear);
- else sprintf(cale,"proleptic_gregorian");
- }
- /* Create NetCDF file */
- NetFile = new NcFile(NetFileName,NcFile::Replace,NULL,0,NcFile::Offset64Bits);
- if (!NetFile->is_valid()) Abort("Could not open NetCDF file");
- /* Define dimensions */
- if (OutRep == HYB_ZONM || OutRep == PRE_ZONM) londim = 1;
- else londim = Lons + Cyclical;
- LonDim = NetFile->add_dim("lon" , londim);
- LatDim = NetFile->add_dim("lat" , Lats );
- LevDim = NetFile->add_dim("lev" , OutLevs );
- TimDim = NetFile->add_dim("time" );
- LonVar = NetFile->add_var("lon" , ncDouble, LonDim);
- LatVar = NetFile->add_var("lat" , ncDouble, LatDim);
- LevVar = NetFile->add_var("lev" , ncDouble, LevDim);
- TimVar = NetFile->add_var("time", ncDouble, TimDim);
- LonVar->add_att("axis" ,"X" );
- LonVar->add_att("long_name" ,"longitude" );
- LonVar->add_att("standard_name","longitude" );
- LonVar->add_att("units" ,"degrees_east" );
- LatVar->add_att("axis" ,"Y" );
- LatVar->add_att("long_name" ,"latitude" );
- LatVar->add_att("standard_name","latitude" );
- LatVar->add_att("units" ,"degrees_north");
- if (VerType == 's') // sigma level
- {
- LevVar->add_att("axis" ,"Z" );
- LevVar->add_att("long_name" ,"sigma at layer midpoints" );
- LevVar->add_att("standard_name","atmosphere_sigma_coordinate");
- LevVar->add_att("positive" ,"down" );
- LevVar->add_att("units" ,"level" );
- }
- else // pressure level
- {
- LevVar->add_att("axis" ,"Z" );
- LevVar->add_att("long_name" ,"pressure" );
- LevVar->add_att("standard_name","pressure" );
- LevVar->add_att("units" ,"hPa" );
- }
- TimVar->add_att("calendar" ,cale );
- TimVar->add_att("units" ,t_unit );
- TimVar->add_att("base_date", 4 ,BaseDate );
-
- NetFile->add_att("title" , title);
- NetFile->add_att("history" , hist );
- NetFile->add_att("Conventions", conv );
- for (jvar = 0 ; jvar < nattr ; ++jvar)
- {
- NetFile->add_att(AttrNam[jvar],AttrVal[jvar]);
- }
-
- LonVar->put(Outlon->Lam,londim );
- LatVar->put(Outlat->Phi,Lats );
- LevVar->put(Outlev ,OutLevs);
- }
- void NetVarDefine(void)
- {
- int jvar;
- for (jvar = 0 ; jvar < CODES ; ++jvar)
- if (All[jvar].selected)
- {
- if (All[jvar].twod)
- {
- if (RealSize == 8)
- All[jvar].NetVar = NetFile->add_var(All[jvar].Id,ncDouble,TimDim,LatDim,LonDim);
- else
- All[jvar].NetVar = NetFile->add_var(All[jvar].Id,ncFloat ,TimDim,LatDim,LonDim);
- }
- else
- {
- if (RealSize == 8)
- All[jvar].NetVar = NetFile->add_var(All[jvar].Id,ncDouble,TimDim,LevDim,LatDim,LonDim);
- else
- All[jvar].NetVar = NetFile->add_var(All[jvar].Id,ncFloat ,TimDim,LevDim,LatDim,LonDim);
- }
- All[jvar].NetVar->add_att("long_name" ,All[jvar].Na);
- All[jvar].NetVar->add_att("standard_name",All[jvar].Na);
- All[jvar].NetVar->add_att("units" ,All[jvar].Un);
- All[jvar].NetVar->add_att("code" , jvar );
- if (GaussianOutput)
- All[jvar].NetVar->add_att("grid_type" ,"gaussian" );
- }
- }
- void NetBuffer(double *d, float *f)
- {
- for (int jdim = 0 ; jdim < DimGP ; ++jdim) *f++ = *d++;
- }
-
- void NetScale(float *f, int dim, double s)
- {
- int j;
- for (j = 0 ; j < dim ; ++j) *f++ *= s;
- }
- void NetScale(double *f, int dim, double s)
- {
- int j;
- for (j = 0 ; j < dim ; ++j) *f++ *= s;
- }
- void NetWrite32(int code, double *Var)
- {
- int jlev;
- if (All[code].twod)
- {
- NetBuffer(Var,Record_float);
- if (code==SLPCODE || code==PSCODE)
- NetScale(Record_float,Lats*(Lons+Cyclical),0.01);
- All[code].NetVar->set_cur(OutputCount);
- All[code].NetVar->put(Record_float,1,Lats,Lons+Cyclical);
- }
- else
- {
- for (jlev = 0 ; jlev < OutLevs ; ++jlev, Var += DimGP)
- {
- NetBuffer(Var,Record_float);
- if (code==WCODE)
- NetScale(Record_float,Lats*(Lons+Cyclical),0.01);
- All[code].NetVar->set_cur(OutputCount,jlev);
- All[code].NetVar->put(Record_float,1,1,Lats,Lons+Cyclical);
- }
- }
- }
- void NetWrite64(int code, double *Var)
- {
- int jlev;
- if (All[code].twod)
- {
- memcpy(Record_double,Var,DimGP * sizeof(double));
- if (code==SLPCODE || code==PSCODE)
- NetScale(Record_double,Lats*(Lons+Cyclical),0.01);
- All[code].NetVar->set_cur(OutputCount);
- All[code].NetVar->put(Record_double,1,Lats,Lons+Cyclical);
- }
- else
- {
- for (jlev = 0 ; jlev < OutLevs ; ++jlev, Var += DimGP)
- {
- memcpy(Record_double,Var,DimGP * sizeof(double));
- if (code==WCODE)
- NetScale(Record_double,Lats*(Lons+Cyclical),0.01);
- All[code].NetVar->set_cur(OutputCount,jlev);
- All[code].NetVar->put(Record_double,1,1,Lats,Lons+Cyclical);
- }
- }
- }
- void NetWriteSection(int code, double *Var)
- {
- int jvar,jlev;
- double *vp;
- for (jlev = 0 ; jlev < OutLevs ; ++jlev)
- {
- vp = Var + jlev * DimFC;
- if (code==SLPCODE || code==PSCODE || code==WCODE)
- {
- for (jvar = 0 ; jvar < Lats ; ++jvar)
- {
- Record_float[jvar] = vp[jvar] * 0.01;
- }
- }
- else
- {
- for (jvar = 0 ; jvar < Lats ; ++jvar)
- {
- Record_float[jvar] = vp[jvar];
- }
- }
- All[code].NetVar->set_cur(OutputCount,jlev);
- All[code].NetVar->put(Record_float,1,1,Lats,1);
- }
- }
- void NetClose(void)
- {
- int jt;
- double * Outtim;
- Outtim = new double[OutputCount];
- for (jt = 0 ; jt < OutputCount ; jt++) Outtim[jt] = jt;
- if (Mean == 0 && (DataStep < 0.99999 || DataStep > 1.00001))
- for (jt = 0 ; jt < OutputCount ; jt++) Outtim[jt] *= DataStep;
- TimVar->put(Outtim,OutputCount);
- delete Outtim;
- delete NetFile;
- }
- #endif
- class ServiceGrid
- {
- int HeadControl;
- FILE *File;
- float *FloatBuffer;
- public:
- int h4; // head[4] = 1st dimension
- int h5; // head[5] = 2nd dimension
- int Dim; // total dimension
- int FieldControl;
- ServiceGrid(FILE *, int, int);
- ~ServiceGrid(void);
- void Write(int *, double *);
- void WriteCode(int code, double *field, int twod);
- void Write_hspec(void);
- void Write_pspec(void);
- void Write_hfour(void);
- void Write_pfour(void);
- void Write_hgrid(void);
- void Write_pgrid(void);
- void Clear_hspec(void);
- void Clear_pspec(void);
- void Clear_hfour(void);
- void Clear_pfour(void);
- void Clear_hgrid(void);
- void Clear_pgrid(void);
- };
-
- ServiceGrid::ServiceGrid(FILE *fd, int Dim1, int Dim2)
- {
- h4 = Dim1;
- h5 = Dim2;
- Dim = Dim1 * Dim2;
- HeadControl = 8 * RealSize;
- FieldControl = Dim * RealSize;
- File = fd;
- FloatBuffer = new float[Dim];
- }
- ServiceGrid::~ServiceGrid(void)
- {
- delete FloatBuffer;
- }
- void ServiceGrid::Write(int *Head, double *Array)
- {
- int i,j;
- LONG lhc,lfc;
- if (Debug) // Check for NaN (Not A Number)
- {
- for (j=0 ; j<Dim ; ++j)
- {
- if (isnan(Array[j]))
- {
- printf("\n Head: ");
- for (i=0 ; i<6 ; i++) printf(" %d",Head[i]);
- printf("\n Array[%d] = NaN\n",j);
- exit(1);
- }
- }
- }
- if (RealSize == 4)
- {
- for (j=0 ; j<Dim ; ++j) FloatBuffer[j] = Array[j];
-
- if (LongFCW)
- {
- lhc = HeadControl;
- lfc = FieldControl;
- fwrite(&lhc ,sizeof(lhc) ,1 ,File);
- fwrite( Head ,sizeof(int) ,8 ,File);
- fwrite(&lhc ,sizeof(lhc) ,1 ,File);
- fwrite(&lfc ,sizeof(lfc) ,1 ,File);
- fwrite( FloatBuffer,sizeof(float),Dim,File);
- fwrite(&lfc ,sizeof(lfc) ,1 ,File);
- }
- else
- {
- fwrite(&HeadControl ,sizeof(int) ,1 ,File);
- fwrite( Head ,sizeof(int) ,8 ,File);
- fwrite(&HeadControl ,sizeof(int) ,1 ,File);
- fwrite(&FieldControl,sizeof(int) ,1 ,File);
- fwrite( FloatBuffer ,sizeof(float),Dim,File);
- fwrite(&FieldControl,sizeof(int) ,1 ,File);
- }
- }
- else // RealSize == 8
- {
- if (LongFCW)
- {
- lhc = HeadControl;
- lfc = FieldControl;
- fwrite(&lhc ,sizeof(lhc) ,1 ,File);
- fwrite( Head ,sizeof(int) ,8 ,File);
- fwrite(&lhc ,sizeof(lhc) ,1 ,File);
- fwrite(&lfc ,sizeof(lfc) ,1 ,File);
- fwrite( Array ,sizeof(double),Dim,File);
- fwrite(&lfc ,sizeof(lfc) ,1 ,File);
- }
- else
- {
- long LongHead[8];
- for (int i=0 ; i<8 ; ++i) LongHead[i] = Head[i];
- fwrite(&HeadControl ,sizeof(int) ,1 ,File);
- fwrite( LongHead ,RealSize ,8 ,File);
- fwrite(&HeadControl ,sizeof(int) ,1 ,File);
- fwrite(&FieldControl,sizeof(int) ,1 ,File);
- fwrite( Array ,RealSize ,Dim,File);
- fwrite(&FieldControl,sizeof(int) ,1 ,File);
- }
- }
- }
-
- void ServiceGrid::WriteCode(int code, double *field, int twod)
- {
- int jlev;
- if (field == NULL)
- {
- fprintf(stderr, "*** Error in ServiceGrid::WriteCode\n");
- fprintf(stderr, " Code %d not defined for this OutRep\n",code);
- fprintf(stderr, " Skipping this record\n\n");
- return;
- }
- HeadOu[0] = code;
- HeadOu[4] = h4;
- HeadOu[5] = h5;
- if (twod)
- {
- HeadOu[1] = 0;
- HeadOu[7] = 0;
- Write(&HeadOu[0],field);
- }
- else for (jlev = 0; jlev < OutLevs; jlev++)
- {
- HeadOu[1] = LevelUnits[jlev];
- HeadOu[7] = SigmaF[jlev];
- Write(&HeadOu[0], field + jlev * Dim);
- }
- }
- void ServiceGrid::Write_hspec(void)
- {
- for (int code = 0; code < CODES; code++)
- if (All[code].selected)
- WriteCode(code,&All[code].hsp[0],All[code].twod);
- }
- void ServiceGrid::Write_pspec(void)
- {
- for (int code = 0; code < CODES; code++)
- if (All[code].selected)
- WriteCode(code,&All[code].psp[0],All[code].twod);
- }
- void ServiceGrid::Clear_hspec(void)
- {
- for (int code = CODES-1 ; code >= 0 ; --code)
- if (All[code].hsp.size() && !All[code].twod)
- {
- if (Debug)
- {
- char tb[COLS];
- sprintf(tb,"Clear: %p %6s[%3d].hsp",
- &All[code].hsp[0],All[code].Id,code);
- LeftText(tb);
- }
- All[code].hsp.resize(0);
- }
- }
- void ServiceGrid::Clear_hfour(void)
- {
- for (int code = CODES-1 ; code >= 0 ; --code)
- if (All[code].hfc.size() && !All[code].twod)
- {
- if (Debug)
- {
- char tb[COLS];
- sprintf(tb,"CLear: %p %6s[%3d].hfc",&All[code].hfc[0],All[code].Id,code);
- LeftText(tb);
- }
- All[code].hfc.resize(0);
- }
- }
- void ServiceGrid::Clear_hgrid(void)
- {
- for (int code = CODES-1 ; code >= 0 ; --code)
- if (All[code].hgp.size())
- {
- if (Debug)
- {
- char tb[COLS];
- sprintf(tb,"CLear: %p %6s[%3d].hgp",&All[code].hgp[0],All[code].Id,code);
- LeftText(tb);
- }
- All[code].hgp.resize(0);
- }
- }
- void ServiceGrid::Clear_pgrid(void)
- {
- for (int code = CODES-1 ; code >= 0 ; --code)
- if (All[code].pgp.size())
- {
- if (Debug)
- {
- char tb[COLS];
- sprintf(tb,"CLear: %p %6s[%3d].pgp",&All[code].pgp[0],All[code].Id,code);
- LeftText(tb);
- }
- All[code].pgp.resize(0);
- }
- }
- void ServiceGrid::Clear_pfour(void)
- {
- for (int code = CODES-1 ; code >= 0 ; --code)
- if (All[code].pfc.size())
- {
- if (Debug)
- {
- char tb[COLS];
- sprintf(tb,"CLear: %p %6s[%3d].pfc",&All[code].pfc[0],All[code].Id,code);
- LeftText(tb);
- }
- All[code].pfc.resize(0);
- }
- }
- void ServiceGrid::Clear_pspec(void)
- {
- for (int code = CODES-1 ; code >= 0 ; --code)
- if (All[code].psp.size())
- {
- if (Debug)
- {
- char tb[COLS];
- sprintf(tb,"CLear: %p %6s[%3d].psp",&All[code].psp[0],All[code].Id,code);
- LeftText(tb);
- }
- All[code].psp.resize(0);
- }
- }
- void ServiceGrid::Write_hfour(void)
- {
- int code;
- for (code = 0; code < CODES; code++)
- if (All[code].selected)
- WriteCode(code,&All[code].hfc[0],All[code].twod);
- }
- void ServiceGrid::Write_pfour(void)
- {
- int code;
- for (code = 0; code < CODES; code++)
- if (All[code].selected)
- WriteCode(code,&All[code].pfc[0],All[code].twod);
- }
- void ServiceGrid::Write_hgrid(void)
- {
- int code;
- for (code = 0; code < CODES; code++)
- if (All[code].selected)
- {
- if (All[code].hgp.size() == 0)
- {
- fprintf(stderr, "*** Error in ServiceGrid::Write_hgrid\n");
- fprintf(stderr, " Code %d is not available on sigma level\n",code);
- fprintf(stderr, " Skipping this record\n\n");
- return;
- }
- #ifdef NETCDF_OUTPUT
- if (NetCDF)
- {
- if (RealSize == 8) NetWrite64(code,&All[code].hgp[0]);
- else NetWrite32(code,&All[code].hgp[0]);
- }
- else
- #endif
- WriteCode(code,&All[code].hgp[0],All[code].twod);
- }
- OutputCount++;
- }
- void ServiceGrid::Write_pgrid(void)
- {
- int code;
- for (code = 0; code < CODES; code++)
- if (All[code].selected)
- {
- #ifdef NETCDF_OUTPUT
- if (NetCDF)
- {
- if (RealSize == 8) NetWrite64(code,&All[code].pgp[0]);
- else NetWrite32(code,&All[code].pgp[0]);
- }
- else
- #endif
- WriteCode(code,&All[code].pgp[0],All[code].twod);
- }
- OutputCount++;
- }
- class ServiceSect : public ServiceGrid
- {
- double *Buffer;
- public:
- ServiceSect(FILE *, int, int);
- ~ServiceSect(void);
- void WriteCode(int code, double *field, int twod);
- void Write_hfour(void);
- void Write_pfour(void);
- };
- ServiceSect::ServiceSect(FILE *fd, int Dim1, int Dim2) :
- ServiceGrid(fd,Dim1,Dim2)
- {
- Buffer = new double[Dim1*Dim2];
- }
- ServiceSect::~ServiceSect(void)
- {
- delete Buffer;
- }
- void ServiceSect::WriteCode(int code, double *field, int twod)
- {
- int jlev;
- HeadOu[0] = code;
- HeadOu[1] = -1;
- HeadOu[7] = 0;
- if (twod)
- {
- h5 = 1;
- memcpy(Buffer,field,Lats * sizeof(double));
- }
- else
- {
- h5 = OutLevs;
- for (jlev=0 ; jlev < OutLevs ; ++jlev)
- memcpy(Buffer+jlev*Lats,field+jlev*DimFC,Lats*sizeof(double));
- }
- HeadOu[4] = h4;
- HeadOu[5] = h5;
- Dim = h4 * h5;
- FieldControl = Dim * sizeof(float);
- Write(&HeadOu[0],Buffer);
- }
- void ServiceSect::Write_hfour(void)
- {
- int code;
- for (code = 0; code < CODES; code++)
- if (All[code].selected)
- {
- #ifdef NETCDF_OUTPUT
- if (NetCDF)
- NetWriteSection(code,&All[code].hfc[0]);
- else
- #endif
- WriteCode(code,&All[code].hfc[0],All[code].twod);
- }
- OutputCount++;
- }
- void ServiceSect::Write_pfour(void)
- {
- int code;
- for (code = 0; code < CODES; code++)
- if (All[code].selected)
- {
- #ifdef NETCDF_OUTPUT
- if (NetCDF)
- NetWriteSection(code,&All[code].pfc[0]);
- else
- #endif
- WriteCode(code,&All[code].pfc[0],All[code].twod);
- }
- OutputCount++;
- }
- ServiceGrid *HybSpec;
- ServiceGrid *HybFour;
- ServiceGrid *HybGrid;
- ServiceSect *HybSect;
- void HeadToDate(vector<int>Head, struct tm *Date)
- {
- Date->tm_year = Head[2] / 10000;
- Date->tm_mon = Head[2] / 100 % 100;
- Date->tm_mday = Head[2] % 100;
- Date->tm_hour = Head[3] / 100;
- Date->tm_min = Head[3] % 100;
- }
- /* ============================================== */
- /* DoubleZero - Set array of type double to zero */
- /* ============================================== */
- inline void DoubleZero(double *field, int words)
- {
- memset((char *)field,0,words * sizeof(double));
- }
- /* ====================== */
- /* Fast Fourier Transform */
- /* ====================== */
- /* constants in math.h :
- #define M_E 2.71828182845904523536
- #define M_LOG2E 1.44269504088896340736
- #define M_LOG10E 0.434294481903251827651
- #define M_LN2 0.693147180559945309417
- #define M_LN10 2.30258509299404568402
- #define M_PI 3.14159265358979323846
- #define M_PI_2 1.57079632679489661923
- #define M_PI_4 0.785398163397448309616
- #define M_1_PI 0.318309886183790671538
- #define M_2_PI 0.636619772367581343076
- #define M_1_SQRTPI 0.564189583547756286948
- #define M_2_SQRTPI 1.12837916709551257390
- #define M_SQRT2 1.41421356237309504880
- #define M_SQRT_2 0.707106781186547524401
- */
- #define QUA 0.25
- #define QT5 0.559016994374947
- #define S36 0.587785252292473
- #define S60 0.866025403784437
- #define S72 0.951056516295154
- #define SQ2 0.707106781186547524401
- #define D60 (S60+S60)
- #define FORK for(k=la;k<=kstop;k+=la){
- #define LOOP for(l=0;l<la;++l){i=ibase;j=jbase;for(ijk=0;ijk<lot;++ijk){
- #define ENDL i+=inc3;j+=inc4;}ibase++;jbase++;}
- void fft_set(int n)
- {
- int j,k,nfax;
- nfax = 0;
- for (k = 0; k < 9; ++k) ifax[k] = 0;
- ifax[9] = n;
- if (n % 8 == 0) {ifax[++nfax] = 8; n /= 8;}
- while (n % 6 == 0) {ifax[++nfax] = 6; n /= 6;}
- while (n % 5 == 0) {ifax[++nfax] = 5; n /= 5;}
- while (n % 4 == 0) {ifax[++nfax] = 4; n /= 4;}
- while (n % 3 == 0) {ifax[++nfax] = 3; n /= 3;}
- if (n % 2 == 0) {ifax[++nfax] = 2; n /= 2;}
- ifax[0] = nfax;
- for (k = 0; k < nfax/2; ++k)
- {
- j = ifax[k+1];
- ifax[k+1] = ifax[nfax-k];
- ifax[nfax-k] = j;
- }
- }
- int rpassc(double *a, double *b, double *c, double *d,
- int inc3, int inc4,
- int lot , int n , int ifac, int la )
- {
- /*
- rpassc' - performs one pass through data as part;
- of multiple real fft (fourier synthesis) routine;
- a is first real input vector
- b is equivalent to a + la
- c is first real output vector
- d is equivalent to c + ifac * la
- inc3 is the increment between input vectors a;
- inc4 is the increment between output vectors c;
- lot is the number of vectors;
- n is the length of the vectors;
- ifac is the current factor of n;
- la is the product of previous factors;
- ierr is an error indicator:;
- 0 - pass completed without error;
- 2 - ifac not catered for;
- 3 - ifac only catered for if la=n/ifac;
- */
- int i0,i1,i2,i3,i4,i5,i6,i7;
- int j0,j1,j2,j3,j4,j5,j6,j7;
- int ia,ib,ic,id,ie,iF;
- int ja,jb,jc,jd,je,jf;
- int i,j,k,ijk,l,m;
- int ibase,jbase;
- int iink,jink;
- int jump;
- int kstop;
- double c1,c2,c3,c4,c5;
- double s1,s2,s3,s4,s5;
- double kpidn;
- double angle;
- double qqrt5;
- double ssin36;
- double ssin72;
- double pin;
- double a10,a11,a20,a21;
- double b10,b11,b20,b21;
- m = n / ifac;
- iink = la;
- jink = la;
- jump = (ifac-1) * jink;
- kstop = (n-ifac) / (2*ifac);
- pin = 2.0 * M_PI / n;
- ibase = 0;
- jbase = 0;
- switch (ifac)
- {
- case 2:
- {
- double a0m1,b0p1;
- i0 = j0 = 0;
- i1 = i0 + (m+m-la);
- j1 = j0 + jink;
- if (la != m)
- {
- LOOP
- c[j0+j] = a[i0+i] + a[i1+i];
- c[j1+j] = a[i0+i] - a[i1+i];
- ENDL
- i0 += iink;
- iink += iink;
- i1 -= iink;
- ibase = 0;
- jbase += jump;
- jump += jump + jink;
- if (i0 != i1)
- {
- FORK
- angle = k * pin;
- c1 = cos(angle);
- s1 = sin(angle);
- ibase = 0;
- LOOP
- a0m1 = a[i0+i] - a[i1+i];
- b0p1 = b[i0+i] + b[i1+i];
- c[j0+j] = a[i0+i] + a[i1+i];
- d[j0+j] = b[i0+i] - b[i1+i];
- c[j1+j] = c1 * a0m1 - s1 * b0p1;
- d[j1+j] = s1 * a0m1 + c1 * b0p1;
- ENDL
- i0 += iink;
- i1 -= iink;
- jbase += jump;
- } /* End FORK */
- if (i0 > i1) return 0;
- } /* End (i0 != i1) */
- ibase = 0;
- LOOP
- c[j0+j] = a[i0+i];
- c[j1+j] = -b[i0+i];
- ENDL
- }
- else /* (la != m) */ {
- LOOP
- c[j0+j] = 2.0 * (a[i0+i] + a[i1+i]);
- c[j1+j] = 2.0 * (a[i0+i] - a[i1+i]);
- ENDL
- }
- return 0;
- }
- case 3: {
- double afa1,a1p2,a1m2,a0mm,a0mp;
- double bfa1,b1p2,b1m2,b0mm,b0mp;
- i0 = j0 = 0 ;
- i1 = i0 + (m+m-la);
- i2 = i1;
- j1 = j0 + jink;
- j2 = j1 + jink;
- if (la != m) {
- LOOP
- afa1 = a[i0+i] - 0.5 * a[i1+i];
- bfa1 = S60 * b[i1+i];
- c[j0+j] = a[i0+i] + a[i1+i];
- c[j1+j] = afa1 - bfa1;
- c[j2+j] = afa1 + bfa1;
- ENDL
- i0 += iink;
- iink += iink;
- i1 += iink;
- i2 -= iink;
- jbase += jump;
- jump += jump + jink;
- if (i0 != i2) {
- FORK
- angle = k * pin;
- c1 = cos(angle);
- s1 = sin(angle);
- angle += angle;
- c2 = cos(angle);
- s2 = sin(angle);
- ibase = 0;
- LOOP
- a1p2 = a[i0+i] - 0.5 * (a[i1+i] + a[i2+i]);
- b1m2 = b[i0+i] - 0.5 * (b[i1+i] - b[i2+i]);
- a1m2 = S60 * (a[i1+i] - a[i2+i]);
- b1p2 = S60 * (b[i1+i] + b[i2+i]);
- a0mm = a1p2 - b1p2;
- a0mp = a1p2 + b1p2;
- b0mm = b1m2 - a1m2;
- b0mp = b1m2 + a1m2;
- c[j0+j] = a[i0+i] + a[i1+i] + a[i2+i];
- d[j0+j] = b[i0+i] + b[i1+i] - b[i2+i];
- c[j1+j] = c1 * a0mm - s1 * b0mp;
- d[j1+j] = s1 * a0mm + c1 * b0mp;
- c[j2+j] = c2 * a0mp - s2 * b0mm;
- d[j2+j] = s2 * a0mp + c2 * b0mm;
- ENDL
- i0 += iink;
- i1 += iink;
- i2 -= iink;
- jbase += jump;
- } /* End FORK */
- if (i0 > i2) return 0;
- } /* End (i0 != i2) */
- ibase=0;
- LOOP
- a0mp = 0.5 * a[i0+i];
- b0mp = S60 * b[i0+i];
- c[j0+j] = a[i0+i] + a[i1+i];
- c[j1+j] = a0mp - a[i1+i] - b0mp;
- c[j2+j] = a[i1+i] - a0mp - b0mp;
- ENDL
- }
- else /* (la != m) */ {
- LOOP
- a0mp = 2.0 * a[i0+i] - a[i1+i];
- b0mp = D60 * b[i1+i];
- c[j0+j] = 2.0 * (a[i0+i] + a[i1+i]);
- c[j1+j] = a0mp - b0mp;
- c[j2+j] = a0mp + b0mp;
- ENDL
- }
- return 0;
- }
- case 4: {
- double a0m1,a0p2,a1p3,a0m2,a1m3,a0p2ma1p3,a0m2pb1p3,a0m2mb1p3;
- double b0p1,b0p2,b1p3,b0m2,b1m3,b0p2pa1m3,b0p2ma1m3,b0m2mb1m3;
- i0 = j0 = 0;
- i1 = i3 = i0 + (m+m-la);
- i2 = i1 + (m+m);
- j1 = j0 + jink;
- j2 = j1 + jink;
- j3 = j2 + jink;
- if (la != m) {
- LOOP
- a0p2 = a[i0+i] + a[i2+i];
- a0m2 = a[i0+i] - a[i2+i];
- c[j0+j] = a0p2 + a[i1+i];
- c[j1+j] = a0m2 - b[i1+i];
- c[j2+j] = a0p2 - a[i1+i];
- c[j3+j] = a0m2 + b[i1+i];
- ENDL
- i0 += iink;
- iink += iink;
- i1 += iink;
- i2 -= iink;
- i3 -= iink;
- jbase += jump;
- jump += jump + jink;
- if (i1 != i2) {
- FORK
- angle = kpidn = k * pin;
- c1 = cos(angle);
- s1 = sin(angle);
- angle += kpidn;
- c2 = cos(angle);
- s2 = sin(angle);
- angle += kpidn;
- c3 = cos(angle);
- s3 = sin(angle);
- ibase=0;
- LOOP
- a0p2 = a[i0+i] + a[i2+i];
- a0m2 = a[i0+i] - a[i2+i];
- a1p3 = a[i1+i] + a[i3+i];
- a1m3 = a[i1+i] - a[i3+i];
- b0p2 = b[i0+i] + b[i2+i];
- b0m2 = b[i0+i] - b[i2+i];
- b1p3 = b[i1+i] + b[i3+i];
- b1m3 = b[i1+i] - b[i3+i];
- a0p2ma1p3 = a0p2 - a1p3;
- a0m2pb1p3 = a0m2 + b1p3;
- a0m2mb1p3 = a0m2 - b1p3;
- b0p2pa1m3 = b0p2 + a1m3;
- b0p2ma1m3 = b0p2 - a1m3;
- b0m2mb1m3 = b0m2 - b1m3;
- c[j0+j] = a0p2 + a1p3;
- d[j0+j] = b0m2 + b1m3;
- c[j2+j] = c2 * a0p2ma1p3 - s2 * b0m2mb1m3;
- d[j2+j] = s2 * a0p2ma1p3 + c2 * b0m2mb1m3;
- c[j1+j] = c1 * a0m2mb1p3 - s1 * b0p2pa1m3;
- d[j1+j] = s1 * a0m2mb1p3 + c1 * b0p2pa1m3;
- c[j3+j] = c3 * a0m2pb1p3 - s3 * b0p2ma1m3;
- d[j3+j] = s3 * a0m2pb1p3 + c3 * b0p2ma1m3;
- ENDL
- i0 += iink;
- i1 += iink;
- i2 -= iink;
- i3 -= iink;
- jbase += jump;
- } /* End FORK */
- if (i1 > i2) return 0;
- } /* End (i1 != i2) */
- ibase=0;
- LOOP
- a0m1 = a[i0+i] - a[i1+i];
- b0p1 = b[i0+i] + b[i1+i];
- c[j0+j] = a[i0+i] + a[i1+i];
- c[j2+j] = b[i1+i] - b[i0+i];
- c[j1+j] = SQ2 * (a0m1 - b0p1);
- c[j3+j] = -SQ2 * (a0m1 + b0p1);
- ENDL
- }
- else /* (la != m) */ {
- LOOP
- a0p2 = a[i0+i] + a[i2+i];
- a0m2 = a[i0+i] - a[i2+i];
- c[j0+j] = 2.0 * (a0p2 + a[i1+i]);
- c[j1+j] = 2.0 * (a0m2 - b[i1+i]);
- c[j2+j] = 2.0 * (a0p2 - a[i1+i]);
- c[j3+j] = 2.0 * (a0m2 + b[i1+i]);
- ENDL
- }
- return 0;
- }
- case 5: {
- double a1p2,a1m2,a0mm,a0mp,b136,b172,b236,b272;
- i0 = j0 = 0;
- i1 = i4 = i0 + (m+m-la);
- i2 = i3 = i1 + (m+m);
- j1 = j0 + jink;
- j2 = j1 + jink;
- j3 = j2 + jink;
- j4 = j3 + jink;
- if (la != m) {
- LOOP
- a1p2 = QUA * (a[i1+i] + a[i2+i]);
- a1m2 = QT5 * (a[i1+i] - a[i2+i]);
- a0mp = a[i0+i] - a1p2 + a1m2;
- a0mm = a[i0+i] - a1p2 - a1m2;
- b136 = b[i1+i] * S36;
- b172 = b[i1+i] * S72;
- b236 = b[i2+i] * S36;
- b272 = b[i2+i] * S72;
- c[j0+j] = a[i0+i] + a[i1+i] + a[i2+i];
- c[j1+j] = a0mp - b172 - b236;
- c[j2+j] = a0mm - b136 + b272;
- c[j3+j] = a0mm + b136 - b272;
- c[j4+j] = a0mp + b172 + b236;
- ENDL
- i0 += iink;
- iink += iink;
- i1 += iink;
- i2 += iink;
- i3 -= iink;
- i4 -= iink;
- jbase += jump;
- jump += jump + jink;
- if (i1 != i3) {
- FORK
- angle = kpidn = k * pin;
- c1 = cos(angle);
- s1 = sin(angle);
- angle += kpidn;
- c2 = cos(angle);
- s2 = sin(angle);
- angle += kpidn;
- c3 = cos(angle);
- s3 = sin(angle);
- angle += kpidn;
- c4 = cos(angle);
- s4 = sin(angle);
- ibase=0;
- LOOP
- a10=(a[i0+i]-0.25*((a[i1+i]+a[i4+i])+(a[i2+i]+a[i3+i])))
- +QT5*((a[i1+i]+a[i4+i])-(a[i2+i]+a[i3+i]));
- a20=(a[i0+i]-0.25*((a[i1+i]+a[i4+i])+(a[i2+i]+a[i3+i])))
- -QT5*((a[i1+i]+a[i4+i])-(a[i2+i]+a[i3+i]));
- b10=(b[i0+i]-0.25*((b[i1+i]-b[i4+i])+(b[i2+i]-b[i3+i])))
- +QT5*((b[i1+i]-b[i4+i])-(b[i2+i]-b[i3+i]));
- b20=(b[i0+i]-0.25*((b[i1+i]-b[i4+i])+(b[i2+i]-b[i3+i])))
- -QT5*((b[i1+i]-b[i4+i])-(b[i2+i]-b[i3+i]));
- a11=S72*(b[i1+i]+b[i4+i])+S36*(b[i2+i]+b[i3+i]);
- a21=S36*(b[i1+i]+b[i4+i])-S72*(b[i2+i]+b[i3+i]);
- b11=S72*(a[i1+i]-a[i4+i])+S36*(a[i2+i]-a[i3+i]);
- b21=S36*(a[i1+i]-a[i4+i])-S72*(a[i2+i]-a[i3+i]);
- c[j0+j]=a[i0+i]+((a[i1+i]+a[i4+i])+(a[i2+i]+a[i3+i]));
- d[j0+j]=b[i0+i]+((b[i1+i]-b[i4+i])+(b[i2+i]-b[i3+i]));
- c[j1+j]=c1*(a10-a11)-s1*(b10+b11);
- d[j1+j]=s1*(a10-a11)+c1*(b10+b11);
- c[j4+j]=c4*(a10+a11)-s4*(b10-b11);
- d[j4+j]=s4*(a10+a11)+c4*(b10-b11);
- c[j2+j]=c2*(a20-a21)-s2*(b20+b21);
- d[j2+j]=s2*(a20-a21)+c2*(b20+b21);
- c[j3+j]=c3*(a20+a21)-s3*(b20-b21);
- d[j3+j]=s3*(a20+a21)+c3*(b20-b21);
- ENDL
- i0 += iink;
- i1 += iink;
- i2 += iink;
- i3 -= iink;
- i4 -= iink;
- jbase += jump;
- } /* End FORK */
- if (i1 > i3) return 0;
- } /* End (i1 != i3) */
- ibase=0;
- LOOP
- c[j0+j] = a[i0+i] + a[i1+i] + a[i2+i];
- c[j1+j] = (QT5 * (a[i0+i]-a[i1+i])
- + (0.25 * (a[i0+i]+a[i1+i])-a[i2+i]))
- - (S36 * b[i0+i]+S72*b[i1+i]);
- c[j4+j] =-(QT5 * (a[i0+i]-a[i1+i])
- + (0.25 * (a[i0+i]+a[i1+i])-a[i2+i]))
- - (S36 * b[i0+i]+S72*b[i1+i]);
- c[j2+j] = (QT5 * (a[i0+i]-a[i1+i])
- - (0.25 * (a[i0+i]+a[i1+i])-a[i2+i]))
- - (S72 * b[i0+i]-S36*b[i1+i]);
- c[j3+j] =-(QT5 * (a[i0+i]-a[i1+i])
- - (0.25 * (a[i0+i]+a[i1+i])-a[i2+i]))
- - (S72 * b[i0+i]-S36*b[i1+i]);
- ENDL
- } else {
- qqrt5 = 2.0 * QT5 ;
- ssin36 = 2.0 * S36;
- ssin72 = 2.0 * S72;
- LOOP
- c[j0+j]= 2.0 *(a[i0+i]+a[i1+i]+a[i2+i]);
- c[j1+j]=(2.0 *(a[i0+i]-0.25*(a[i1+i]+a[i2+i]))
- +qqrt5*(a[i1+i]-a[i2+i]))-(ssin72*b[i1+i]+ssin36*b[i2+i]);
- c[j2+j]=(2.0 *(a[i0+i]-0.25*(a[i1+i]+a[i2+i]))
- -qqrt5*(a[i1+i]-a[i2+i]))-(ssin36*b[i1+i]-ssin72*b[i2+i]);
- c[j3+j]=(2.0 *(a[i0+i]-0.25*(a[i1+i]+a[i2+i]))
- -qqrt5*(a[i1+i]-a[i2+i]))+(ssin36*b[i1+i]-ssin72*b[i2+i]);
- c[j4+j]=(2.0 *(a[i0+i]-0.25*(a[i1+i]+a[i2+i]))
- +qqrt5*(a[i1+i]-a[i2+i]))+(ssin72*b[i1+i]+ssin36*b[i2+i]);
- ENDL
- }
- return 0;
- }
- case 6: {
- ia = 0;
- ib = ia+(2*m-la);
- ic = ib+2*m;
- id = ic+2*m;
- ie = ic;
- iF = ib;
- ja = 0;
- jb = ja+jink;
- jc = jb+jink;
- jd = jc+jink;
- je = jd+jink;
- jf = je+jink;
- if (la != m) /* go to 690 */ {
- LOOP
- c[ja+j] = (a[ia+i]+a[id+i]) + (a[ib+i]+a[ic+i]) ;
- c[jd+j] = (a[ia+i]-a[id+i]) - (a[ib+i]-a[ic+i]) ;
- c[jb+j] = ((a[ia+i]-a[id+i]) +0.5*(a[ib+i]-a[ic+i]))
- - S60*(b[ib+i]+b[ic+i]);
- c[jf+j] = ((a[ia+i]-a[id+i]) +0.5*(a[ib+i]-a[ic+i]))
- + S60*(b[ib+i]+b[ic+i]);
- c[jc+j] = ((a[ia+i]+a[id+i]) -0.5*(a[ib+i]+a[ic+i]))
- - S60*(b[ib+i]-b[ic+i]);
- c[je+j] = ((a[ia+i]+a[id+i]) -0.5*(a[ib+i]+a[ic+i]))
- + S60*(b[ib+i]-b[ic+i]);
- ENDL
- ia += iink;
- iink += iink;
- ib += iink;
- ic += iink;
- id -= iink;
- ie -= iink;
- iF -= iink;
- jbase += jump;
- jump += jump+jink;
- if (ic != id) /* go to 660 */ {
- FORK
- angle = kpidn = k * pin;
- c1 = cos(angle);
- s1 = sin(angle);
- angle += kpidn;
- c2 = cos(angle);
- s2 = sin(angle);
- angle += kpidn;
- c3 = cos(angle);
- s3 = sin(angle);
- angle += kpidn;
- c4 = cos(angle);
- s4 = sin(angle);
- angle += kpidn;
- c5 = cos(angle);
- s5 = sin(angle);
- ibase=0;
- LOOP
- a11 = a[ie+i] + a[ib+i] + a[ic+i] + a[iF+i];
- a20 = a[ia+i] + a[id+i] - 0.5 * a11;
- a21 = S60*((a[ie+i]+a[ib+i])-(a[ic+i]+a[iF+i]));
- b11 = b[ib+i] - b[ie+i] + b[ic+i] - b[iF+i];
- b20 = b[ia+i] - b[id+i] - 0.5 * b11;
- b21 = S60*((b[ib+i]-b[ie+i])-(b[ic+i]-b[iF+i]));
- c[ja+j] = a[ia+i] + a[id+i] + a11;
- d[ja+j] = b[ia+i] - b[id+i] + b11;
- c[jc+j] = c2*(a20-b21)-s2*(b20+a21);
- d[jc+j] = s2*(a20-b21)+c2*(b20+a21);
- c[je+j] = c4*(a20+b21)-s4*(b20-a21);
- d[je+j] = s4*(a20+b21)+c4*(b20-a21);
- a11 = (a[ie+i]-a[ib+i]) + (a[ic+i]-a[iF+i]);
- b11 = (b[ie+i]+b[ib+i]) - (b[ic+i]+b[iF+i]);
- a20 = (a[ia+i]-a[id+i]) - 0.5 * a11;
- a21 = S60 * ((a[ie+i]-a[ib+i]) - (a[ic+i]-a[iF+i]));
- b20 = (b[ia+i]+b[id+i]) + 0.5 * b11;
- b21 = S60 * ((b[ie+i]+b[ib+i]) + (b[ic+i]+b[iF+i]));
- c[jd+j] = c3*(a[ia+i] - a[id+i] + a11)
- - s3*(b[ia+i] + b[id+i] - b11);
- d[jd+j] = s3*(a[ia+i] - a[id+i] + a11)
- + c3*(b[ia+i] + b[id+i] - b11);
- c[jb+j] = c1*(a20-b21)-s1*(b20-a21);
- d[jb+j] = s1*(a20-b21)+c1*(b20-a21);
- c[jf+j] = c5*(a20+b21)-s5*(b20+a21);
- d[jf+j] = s5*(a20+b21)+c5*(b20+a21);
- ENDL
- ia += iink;
- ib += iink;
- ic += iink;
- id -= iink;
- ie -= iink;
- iF -= iink;
- jbase += jump;
- }
- if (ic > id) return 0;
- }
- ibase=0;
- LOOP
- c[ja+j]= a[ib+i] + (a[ia+i] + a[ic+i]);
- c[jd+j]= b[ib+i] - (b[ia+i] + b[ic+i]);
- c[jb+j]= (S60*(a[ia+i]-a[ic+i]))-(0.5*(b[ia+i]+b[ic+i])+b[ib+i]);
- c[jf+j]=-(S60*(a[ia+i]-a[ic+i]))-(0.5*(b[ia+i]+b[ic+i])+b[ib+i]);
- c[jc+j]= S60*(b[ic+i]-b[ia+i]) +(0.5*(a[ia+i]+a[ic+i])-a[ib+i]);
- c[je+j]= S60*(b[ic+i]-b[ia+i]) -(0.5*(a[ia+i]+a[ic+i])-a[ib+i]);
- ENDL
- } else {
- LOOP
- c[ja+j]=(2.0*(a[ia+i]+a[id+i]))+(2.0*(a[ib+i]+a[ic+i]));
- c[jd+j]=(2.0*(a[ia+i]-a[id+i]))-(2.0*(a[ib+i]-a[ic+i]));
- c[jb+j]=(2.0*(a[ia+i]-a[id+i])+(a[ib+i]-a[ic+i]))
- -(D60*(b[ib+i]+b[ic+i]));
- c[jf+j]=(2.0*(a[ia+i]-a[id+i])+(a[ib+i]-a[ic+i]))
- +(D60*(b[ib+i]+b[ic+i]));
- c[jc+j]=(2.0*(a[ia+i]+a[id+i])-(a[ib+i]+a[ic+i]))
- -(D60*(b[ib+i]-b[ic+i]));
- c[je+j]=(2.0*(a[ia+i]+a[id+i])-(a[ib+i]+a[ic+i]))
- +(D60*(b[ib+i]-b[ic+i]));
- ENDL
- }
- return 0;
- }
- case 8: {
- double a0p7,a1p5,a2p6,p073,p074,p152;
- double a0m7,a1m5,a2m6,m073,m074,m152;
- if (la != m) return 3;
- i0 = 0;
- i1 = i0 + iink;
- i2 = i1 + iink;
- i3 = i2 + iink;
- i4 = i3 + iink;
- i5 = i4 + iink;
- i6 = i5 + iink;
- i7 = i6 + iink;
- j0 = 0;
- j1 = j0 + jink;
- j2 = j1 + jink;
- j3 = j2 + jink;
- j4 = j3 + jink;
- j5 = j4 + jink;
- j6 = j5 + jink;
- j7 = j6 + jink;
- LOOP
- a0p7 = a[i0+i] + a[i7+i];
- a0m7 = a[i0+i] - a[i7+i];
- a1p5 = a[i1+i] + a[i5+i];
- a1m5 = a[i1+i] - a[i5+i];
- a2p6 = a[i2+i] + a[i6+i];
- a2m6 = a[i2+i] - a[i6+i];
- p073 = a0p7 + a[i3+i];
- m073 = a0p7 - a[i3+i];
- p074 = 2.0 * (a0m7 + a[i4+i]);
- m074 = 2.0 * (a0m7 - a[i4+i]);
- p152 = M_SQRT2 * (a1m5 + a2p6);
- m152 = M_SQRT2 * (a1m5 - a2p6);
- c[j0+j] = 2.0 * (p073 + a1p5);
- c[j4+j] = 2.0 * (p073 - a1p5);
- c[j2+j] = 2.0 * (m073 - a2m6);
- c[j6+j] = 2.0 * (m073 + a2m6);
- c[j1+j] = m074 + m152;
- c[j5+j] = m074 - m152;
- c[j3+j] = p074 - p152;
- c[j7+j] = p074 + p152;
- ENDL
- }
- }
- return 0;
- }
- int qpassc(double *a, double *b, double *c, double *d,
- int inc3, int inc4,
- int lot , int n , int ifac, int la )
- {
- /*
- qpassc - performs one pass through data as part;
- of multiple real fft (fourier analysis) routine;
- a is first real input vector;
- b is equivalent to a + ifac * la
- c is first real output vector;
- d is equivalent to c + la
- inc3 is the increment between input vectors a;
- inc4 is the increment between output vectors c;
- lot is the number of vectors;
- n is the length of the vectors;
- ifac is the current factor of n;
- la is the product of previous factors;
- qpassc returns an error indicator:;
- 0 - pass completed without error;
- 2 - ifac not catered for;
- 3 - ifac only catered for if la=n/ifac;
- */
- int i0,i1,i2,i3,i4,i5,i6,i7;
- int j0,j1,j2,j3,j4,j5,j6,j7;
- int ia,ib,ic;
- int ja,jb,jc;
- int i,j,k;
- int ibase,jbase;
- int iink,jink;
- int ijk;
- int jump;
- int kstop;
- int l;
- int m;
- double a0,a1,a2,a3;
- double b0,b1,b2,b3;
- double c1,c2,c3,c4,c5;
- double s1,s2,s3,s4,s5;
- double w,x,y,z;
- double angle,kpidn,pin;
- m = n / ifac;
- iink = la;
- jink = la;
- jump = (ifac-1) * iink;
- kstop = (n-ifac) / (2*ifac);
- pin = 2.0 * M_PI / n;
- ibase = 0;
- jbase = 0;
- switch (ifac) {
- case 2: {
- i0 = j0 = 0;
- i1 = i0 + iink;
- j1 = j0 + (m+m-la);
- if (la != m) {
- LOOP
- c[j0+j] = a[i0+i] + a[i1+i];
- c[j1+j] = a[i0+i] - a[i1+i];
- ENDL
- j0 += jink;
- jink += jink;
- j1 -= jink;
- ibase += jump;
- jump += jump + iink;
- if (j0 != j1) {
- FORK
- angle = k * pin;
- c1 = cos(angle);
- s1 = sin(angle);
- jbase = 0;
- LOOP
- c[j0+j] = a[i0+i] + c1 * a[i1+i] + s1 * b[i1+i];
- c[j1+j] = a[i0+i] - c1 * a[i1+i] - s1 * b[i1+i];
- d[j0+j] = c1 * b[i1+i] - s1 * a[i1+i] + b[i0+i];
- d[j1+j] = c1 * b[i1+i] - s1 * a[i1+i] - b[i0+i];
- ENDL
- j0 += jink;
- j1 -= jink;
- ibase += jump;
- } /* End FORK */
- if (j0 > j1) return 0;
- } /* End (i0 != i1) */
- jbase = 0;
- LOOP
- c[j0+j] = a[i0+i];
- d[j1+j] = -a[i1+i];
- ENDL
- }
- else /* (la != m) */ {
- z = 1.0 / n;
- LOOP
- c[j0+j] = z * (a[i0+i] + a[i1+i]);
- c[j1+j] = z * (a[i0+i] - a[i1+i]);
- ENDL
- }
- return 0;
- }
- case 3: {
- ia = 0;
- ib = ia + iink;
- ic = ib + iink;
- ja = 0;
- jb = ja + (m+m-la);
- jc = jb;
- if (la != m) /* else 390 */ {
- LOOP
- c[ja+j] = a[ia+i] + a[ib+i] + a[ic+i];
- c[jb+j] = a[ia+i] - 0.5 * (a[ib+i] + a[ic+i]);
- d[jb+j] = S60 * (a[ic+i] - a[ib+i]);
- ENDL
- ja += jink;
- jink += jink;
- jb += jink;
- jc -= jink;
- ibase += jump;
- jump += jump + iink;
- if (ja != jc) /* else 360 */ {
- FORK
- angle = k * pin;
- c1 = cos(angle);
- s1 = sin(angle);
- angle += angle;
- c2 = cos(angle);
- s2 = sin(angle);
- jbase = 0;
- LOOP
- a1 = c1 * a[ib+i] + s1 * b[ib+i] + c2 * a[ic+i] + s2 * b[ic+i];
- b1 = c1 * b[ib+i] - s1 * a[ib+i] + c2 * b[ic+i] - s2 * a[ic+i];
- a2 = a[ia+i] - 0.5 * a1;
- b2 = b[ia+i] - 0.5 * b1;
- a3 = S60 * (c1 * a[ib+i] + s1 * b[ib+i] - c2 * a[ic+i] - s2 * b[ic+i]);
- b3 = S60 * (c1 * b[ib+i] - s1 * a[ib+i] - c2 * b[ic+i] + s2 * a[ic+i]);
- c[ja+j] = a[ia+i] + a1;
- d[ja+j] = b[ia+i] + b1;
- c[jb+j] = a2 + b3;
- d[jb+j] = b2 - a3;
- c[jc+j] = a2 - b3;
- d[jc+j] =-b2 - a3;
- ENDL
- ja += jink;
- jb += jink;
- jc -= jink;
- ibase += jump;
- } /* End FORK */
- if (ja > jc) return 0;
- } /* End (ia != ic) */
- jbase = 0;
- LOOP
- /* soweit */
- c[ja+j] = a[ia+i] + 0.5 * (a[ib+i] - a[ic+i]);
- d[ja+j] =-S60 * (a[ib+i] + a[ic+i]);
- c[jb+j] = a[ia+i] - a[ib+i] + a[ic+i];
- ENDL
- }
- else /* (la != m) */ {
- z = 1.0 / n;
- y = S60 / n;
- LOOP
- c[ja+j] = z * (a[ia+i] + a[ib+i] + a[ic+i]);
- c[jb+j] = z * (a[ia+i] - 0.5 * (a[ib+i] + a[ic+i]));
- d[jb+j] = y * (a[ic+i] - a[ib+i]);
- ENDL
- }
- return 0;
- }
- case 4: {
- double a0p2,a1p3;
- i0 = 0;
- i1 = i0 + iink;
- i2 = i1 + iink;
- i3 = i2 + iink;
- j0 = 0;
- j1 = j0 + (m+m-la);
- j2 = j1 + (m+m );
- j3 = j1;
- if (la != m) /*else go to 490 */ {
- LOOP
- a0p2 = a[i0+i] + a[i2+i];
- a1p3 = a[i1+i] + a[i3+i];
- c[j0+j] = a0p2 + a1p3;
- c[j2+j] = a0p2 - a1p3;
- c[j1+j] = a[i0+i] - a[i2+i];
- d[j1+j] = a[i3+i] - a[i1+i];
- ENDL
- j0 += jink;
- jink += jink;
- j1 += jink;
- j2 -= jink;
- j3 -= jink;
- ibase += jump;
- jump += jump + iink;
- if (j1 != j2) /* else go to 460; */ {
- FORK
- angle = kpidn = k * pin;
- c1 = cos(angle);
- s1 = sin(angle);
- angle += kpidn;
- c2 = cos(angle);
- s2 = sin(angle);
- angle += kpidn;
- c3 = cos(angle);
- s3 = sin(angle);
- jbase=0;
- LOOP
- a0 = a[i0+i] + c2 * a[i2+i] + s2 * b[i2+i];
- a2 = a[i0+i] - c2 * a[i2+i] - s2 * b[i2+i];
- b0 = b[i0+i] + c2 * b[i2+i] - s2 * a[i2+i];
- b2 = b[i0+i] - c2 * b[i2+i] + s2 * a[i2+i];
- a1 = c1*a[i1+i] + s1*b[i1+i] + c3*a[i3+i] + s3*b[i3+i];
- a3 = c1*a[i1+i] + s1*b[i1+i] - c3*a[i3+i] - s3*b[i3+i];
- b1 = c1*b[i1+i] - s1*a[i1+i] + c3*b[i3+i] - s3*a[i3+i];
- b3 = c1*b[i1+i] - s1*a[i1+i] - c3*b[i3+i] + s3*a[i3+i];
- c[j0+j] = a0 + a1;
- c[j2+j] = a0 - a1;
- d[j0+j] = b0 + b1;
- d[j2+j] = b1 - b0;
- c[j1+j] = a2 + b3;
- c[j3+j] = a2 - b3;
- d[j1+j] = b2 - a3;
- d[j3+j] =-b2 - a3;
- ENDL
- j0 += jink;
- j1 += jink;
- j2 -= jink;
- j3 -= jink;
- ibase += jump;
- } /* End FORK */
- if (j1 > j2) return 0;
- } /* End (i1 != i2) */
- jbase=0;
- LOOP
- c[j0+j] = a[i0+i] + SQ2 * (a[i1+i] - a[i3+i]);
- c[j1+j] = a[i0+i] - SQ2 * (a[i1+i] - a[i3+i]);
- d[j0+j] =-a[i2+i] - SQ2 * (a[i1+i] + a[i3+i]);
- d[j1+j] = a[i2+i] - SQ2 * (a[i1+i] + a[i3+i]);
- ENDL
- }
- else /* (la != m) */ {
- z = 1.0 / n;
- LOOP
- a0p2 = a[i0+i] + a[i2+i];
- a1p3 = a[i1+i] + a[i3+i];
- c[j0+j] = z * (a0p2 + a1p3);
- c[j2+j] = z * (a0p2 - a1p3);
- c[j1+j] = z * (a[i0+i] - a[i2+i]);
- d[j1+j] = z * (a[i3+i] - a[i1+i]);
- ENDL
- }
- return 0;
- }
- case 5: {
- double a1p4,a2p3,b1p4,b2p3,a025,b025,asps,bsps,a0pq,b0pq;
- double a1m4,a2m3,b1m4,b2m3,aqrt,bqrt,asms,bsms,a0mq,b0mq;
- i0 = 0;
- i1 = i0 + iink;
- i2 = i1 + iink;
- i3 = i2 + iink;
- i4 = i3 + iink;
- j0 = 0;
- j1 = j0 + (m+m-la);
- j2 = j1 + (m+m);
- j3 = j2;
- j4 = j1;
- if (la != m) /* else go to 590; */ {
- LOOP
- a1p4 = a[i1+i] + a[i4+i];
- a1m4 = a[i1+i] - a[i4+i];
- a2p3 = a[i2+i] + a[i3+i];
- a2m3 = a[i2+i] - a[i3+i];
- a025 = a[i0+i] - 0.25 * (a1p4 + a2p3);
- aqrt = QT5 * (a1p4 - a2p3);
- c[j0+j] = a[i0+i] + a1p4 + a2p3;
- c[j1+j] = a025 + aqrt;
- c[j2+j] = a025 - aqrt;
- d[j1+j] = -S72 * a1m4 - S36 * a2m3;
- d[j2+j] = -S36 * a1m4 + S72 * a2m3;
- ENDL
- j0 += jink;
- jink += jink;
- j1 += jink;
- j2 += jink;
- j3 -= jink;
- j4 -= jink;
- ibase += jump;
- jump += jump + iink;
- if (j1 != j3) {
- FORK
- angle = kpidn = k * pin;
- c1 = cos(angle);
- s1 = sin(angle);
- angle += kpidn;
- c2 = cos(angle);
- s2 = sin(angle);
- angle += kpidn;
- c3 = cos(angle);
- s3 = sin(angle);
- angle += kpidn;
- c4 = cos(angle);
- s4 = sin(angle);
- jbase=0;
- LOOP
- a1p4 = c1*a[i1+i] + s1*b[i1+i] + c4*a[i4+i] + s4*b[i4+i];
- a1m4 = c1*a[i1+i] + s1*b[i1+i] - c4*a[i4+i] - s4*b[i4+i];
- a2p3 = c2*a[i2+i] + s2*b[i2+i] + c3*a[i3+i] + s3*b[i3+i];
- a2m3 = c2*a[i2+i] + s2*b[i2+i] - c3*a[i3+i] - s3*b[i3+i];
- b1p4 = c1*b[i1+i] - s1*a[i1+i] + c4*b[i4+i] - s4*a[i4+i];
- b1m4 = c1*b[i1+i] - s1*a[i1+i] - c4*b[i4+i] + s4*a[i4+i];
- b2p3 = c2*b[i2+i] - s2*a[i2+i] + c3*b[i3+i] - s3*a[i3+i];
- b2m3 = c2*b[i2+i] - s2*a[i2+i] - c3*b[i3+i] + s3*a[i3+i];
- a025 = a[i0+i] - 0.25 * (a1p4 + a2p3);
- aqrt = QT5 * (a1p4 - a2p3);
- b025 = b[i0+i] - 0.25 * (b1p4 + b2p3);
- bqrt = QT5 * (b1p4 - b2p3);
- a0pq = a025 + aqrt;
- a0mq = a025 - aqrt;
- b0pq = b025 + bqrt;
- b0mq = b025 - bqrt;
- asps = S72 * a1m4 + S36 * a2m3;
- asms = S36 * a1m4 - S72 * a2m3;
- bsps = S72 * b1m4 + S36 * b2m3;
- bsms = S36 * b1m4 - S72 * b2m3;
- c[j0+j] = a[i0+i] + a1p4 + a2p3;
- c[j1+j] = a0pq + bsps;
- c[j2+j] = a0mq + bsms;
- c[j3+j] = a0mq - bsms;
- c[j4+j] = a0pq - bsps;
- d[j0+j] = b[i0+i] + b1p4 + b2p3;
- d[j1+j] = b0pq - asps;
- d[j2+j] = b0mq - asms;
- d[j3+j] =-b0mq - asms;
- d[j4+j] =-b0pq - asps;
- ENDL
- j0 += jink;
- j1 += jink;
- j2 += jink;
- j3 -= jink;
- j4 -= jink;
- ibase += jump;
- } /* End FORK */
- if (j1 > j3) return 0;
- } /* End (jb != jd) */
- jbase=0;
- LOOP
- a1p4 = a[i1+i] + a[i4+i];
- a1m4 = a[i1+i] - a[i4+i];
- a2p3 = a[i2+i] + a[i3+i];
- a2m3 = a[i2+i] - a[i3+i];
- a025 = a[i0+i] + 0.25 * (a1m4 - a2m3);
- aqrt = QT5 * (a1m4 + a2m3);
- c[j0+j] = a025 + aqrt;
- c[j1+j] = a025 - aqrt;
- c[j2+j] = a[i0+i] - a1m4 + a2m3;
- d[j0+j] = -S36 * a1p4 - S72 * a2p3;
- d[j1+j] = -S72 * a1p4 + S36 * a2p3;
- ENDL
- } else {
- z = 1.0 / n;
- y = QT5 / n;
- x = S36 / n;
- w = S72 / n;
- LOOP
- a1p4 = a[i1+i] + a[i4+i];
- a1m4 = a[i1+i] - a[i4+i];
- a2p3 = a[i2+i] + a[i3+i];
- a2m3 = a[i2+i] - a[i3+i];
- a025 = z * (a[i0+i] - 0.25 * (a1p4 + a2p3));
- aqrt = y * (a1p4 - a2p3);
- c[j0+j] = z * (a[i0+i] + a1p4 + a2p3);
- c[j1+j] = a025 + aqrt;
- c[j2+j] = a025 - aqrt;
- d[j1+j] = -w * a1m4 - x * a2m3;
- d[j2+j] = w * a2m3 - x * a1m4;
- ENDL
- }
- return 0;
- }
- case 6: {
- double ab1a,ab2a,ab3a,ab4a,ab5a;
- double ab1b,ab2b,ab3b,ab4b,ab5b;
- double a0p3,a1p4,a1p5,a2p4,a2p5;
- double a0m3,a1m4,a1m5,a2m4,a2m5;
- double b1p4,b2p5;
- double b1m4,b2m5;
- double ap05,bp05,ap60,bp60;
- double am05,bm05,am60,bm60;
- i0 = 0;
- i1 = i0 + iink;
- i2 = i1 + iink;
- i3 = i2 + iink;
- i4 = i3 + iink;
- i5 = i4 + iink;
- j0 = 0;
- j1 = j0 + (m+m-la);
- j2 = j1 + (m+m);
- j3 = j2 + (m+m);
- j4 = j2;
- j5 = j1;
- if (la != m) {
- LOOP
- a0p3 = a[i0+i] + a[i3+i];
- a0m3 = a[i0+i] - a[i3+i];
- a1p4 = a[i1+i] + a[i4+i];
- a1m4 = a[i1+i] - a[i4+i];
- a2p5 = a[i2+i] + a[i5+i];
- a2m5 = a[i2+i] - a[i5+i];
- c[j0+j] = a0p3 + a1p4 + a2p5;
- c[j3+j] = a0m3 + a2m5 - a1m4;
- c[j1+j] = a0m3 - 0.5 * (a2m5 - a1m4);
- c[j2+j] = a0p3 - 0.5 * (a1p4 + a2p5);
- d[j1+j] = S60 * (-a2m5 - a1m4);
- d[j2+j] = S60 * ( a2p5 - a1p4);
- ENDL
- j0 += jink;
- jink += jink;
- j1 += jink;
- j2 += jink;
- j3 -= jink;
- j4 -= jink;
- j5 -= jink;
- ibase += jump;
- jump += jump+iink;
- if (j2 != j3) {
- FORK
- angle = kpidn = k * pin;
- c1 = cos(angle);
- s1 = sin(angle);
- angle += kpidn;
- c2 = cos(angle);
- s2 = sin(angle);
- angle += kpidn;
- c3 = cos(angle);
- s3 = sin(angle);
- angle += kpidn;
- c4 = cos(angle);
- s4 = sin(angle);
- angle += kpidn;
- c5 = cos(angle);
- s5 = sin(angle);
- jbase = 0;
- LOOP
- ab1a = c1 * a[i1+i] + s1 * b[i1+i];
- ab1b = c1 * b[i1+i] - s1 * a[i1+i];
- ab2a = c2 * a[i2+i] + s2 * b[i2+i];
- ab2b = c2 * b[i2+i] - s2 * a[i2+i];
- ab3a = c3 * a[i3+i] + s3 * b[i3+i];
- ab3b = c3 * b[i3+i] - s3 * a[i3+i];
- ab4a = c4 * a[i4+i] + s4 * b[i4+i];
- ab4b = c4 * b[i4+i] - s4 * a[i4+i];
- ab5a = c5 * a[i5+i] + s5 * b[i5+i];
- ab5b = c5 * b[i5+i] - s5 * a[i5+i];
- a1p4 = ab1a + ab4a;
- a1m4 = ab1a - ab4a;
- a2p5 = ab2a + ab5a;
- a2m5 = ab2a - ab5a;
- b1p4 = ab1b + ab4b;
- b1m4 = ab1b - ab4b;
- b2p5 = ab2b + ab5b;
- b2m5 = ab2b - ab5b;
- ap05 = a[i0+i] + ab3a - 0.5 * (a1p4 + a2p5);
- bp05 = b[i0+i] + ab3b - 0.5 * (b1p4 + b2p5);
- am05 = a[i0+i] - ab3a - 0.5 * (a2m5 - a1m4);
- bm05 =-b[i0+i] + ab3b - 0.5 * (b1m4 - b2m5);
- ap60 = S60 * ( a2p5 - a1p4);
- bp60 = S60 * ( b2p5 - b1p4);
- am60 = S60 * (-a2m5 - a1m4);
- bm60 = S60 * (-b2m5 - b1m4);
- c[j0+j] = a[i0+i] + ab3a + a1p4 + a2p5;
- d[j0+j] = b[i0+i] + ab3b + b1p4 + b2p5;
- c[j1+j] = am05 - bm60;
- d[j1+j] = am60 - bm05;
- c[j2+j] = ap05 - bp60;
- d[j2+j] = ap60 + bp05;
- c[j3+j] = a[i0+i] - ab3a - a1m4 + a2m5;
- d[j3+j] =-b[i0+i] + ab3b + b1m4 - b2m5;
- c[j4+j] = ap05 + bp60;
- d[j4+j] = ap60 - bp05;
- c[j5+j] = am05 + bm60;
- d[j5+j] = am60 + bm05;
- ENDL
- j0 += jink;
- j1 += jink;
- j2 += jink;
- j3 -= jink;
- j4 -= jink;
- j5 -= jink;
- ibase += jump;
- }
- if (j2 > j3) return 0;
- }
- jbase = 0;
- LOOP
- a1p5 = a[i1+i] + a[i5+i];
- a1m5 = a[i1+i] - a[i5+i];
- a2p4 = a[i2+i] + a[i4+i];
- a2m4 = a[i2+i] - a[i4+i];
- c[j0+j] = a[i0+i] + 0.5 * a2m4 + S60 * a1m5;
- d[j0+j] =-a[i3+i] - 0.5 * a1p5 - S60 * a2p4;
- c[j1+j] = a[i0+i] - a2m4;
- d[j1+j] = a[i3+i] - a1p5;
- c[j2+j] = a[i0+i] + 0.5 * a2m4 - S60 * a1m5;
- d[j2+j] =-a[i3+i] - 0.5 * a1p5 + S60 * a2p4;
- ENDL
- } else {
- z = 1.0 / n;
- y = S60 / n;
- LOOP
- a0p3 = a[i0+i] + a[i3+i];
- a0m3 = a[i0+i] - a[i3+i];
- a1p4 = a[i1+i] + a[i4+i];
- a1m4 = a[i1+i] - a[i4+i];
- a2p5 = a[i2+i] + a[i5+i];
- a2m5 = a[i2+i] - a[i5+i];
- c[j0+j] = z * (a0p3 + a1p4 + a2p5);
- c[j3+j] = z * (a0m3 + a2m5 - a1m4);
- c[j1+j] = z * (a0m3 - 0.5 * (a2m5 - a1m4));
- c[j2+j] = z * (a0p3 - 0.5 * (a1p4 + a2p5));
- d[j1+j] = y * (-a2m5 - a1m4);
- d[j2+j] = y * ( a2p5 - a1p4);
- ENDL
- }
- return 0;
- }
- case 8: {
- double a0p4,a1p5,a2p6,a3p7;
- double a0m4,a1m5,a2m6,a3m7;
- if (la != m) return 3;
- i0 = 0;
- i1 = i0 + iink;
- i2 = i1 + iink;
- i3 = i2 + iink;
- i4 = i3 + iink;
- i5 = i4 + iink;
- i6 = i5 + iink;
- i7 = i6 + iink;
- j0 = 0;
- j1 = j0 + jink;
- j2 = j1 + jink;
- j3 = j2 + jink;
- j4 = j3 + jink;
- j5 = j4 + jink;
- j6 = j5 + jink;
- j7 = j6 + jink;
- z = 1.0 / n;
- y = SQ2 / n;
- LOOP
- a0p4 = a[i0+i] + a[i4+i];
- a0m4 = a[i0+i] - a[i4+i];
- a1p5 = a[i1+i] + a[i5+i];
- a1m5 = a[i1+i] - a[i5+i];
- a2p6 = a[i2+i] + a[i6+i];
- a2m6 = a[i2+i] - a[i6+i];
- a3p7 = a[i3+i] + a[i7+i];
- a3m7 = a[i3+i] - a[i7+i];
- c[j0+j] = z * (a0p4 + a1p5 + a2p6 + a3p7);
- c[j7+j] = z * (a0p4 - a1p5 + a2p6 - a3p7);
- c[j3+j] = z * (a0p4 - a2p6);
- c[j4+j] = z * (a3p7 - a1p5);
- c[j1+j] = z * a0m4 + y * (a1m5 - a3m7);
- c[j5+j] = z * a0m4 - y * (a1m5 - a3m7);
- c[j2+j] =-z * a2m6 - y * (a1m5 + a3m7);
- c[j6+j] = z * a2m6 - y * (a1m5 + a3m7);
- ENDL
- }
- }
- return 0;
- }
- void fc2gp(double *fc, double *gp, int Lat, int Lon, int Lev, int Fou)
- {
- int Lot;
- int fou;
- int ia;
- int ifac;
- int j;
- int jump;
- int k;
- int la;
- int lat;
- int lev;
- int lon;
- int nfax;
- int rix;
- int wix;
- double *wpt;
- /* fc2gp performs fourier to gridpoint transforms using */
- /* multiple fast fourier transform of length Lon */
- /* */
- /* fc - real array of fourier coefficients fc[Lev][Fou][Lat] */
- /* gp - real array of gridpoints gp[Lev][Lat][Lon] */
- /* Lat - Number of latitudes */
- /* Lon - Number of longitudes */
- /* Lev - Number of levels */
- /* Fou - Number of fourier coefficients on 1 latitude */
- /* x(j) = sum(k=0,...,n-1)(c(k)*exp(2*i*j*k*pi/Lon)) */
- /* where c(k) = a(k) + i*b(k) and c(n-k) = a(k)-i*b(k) */
- jump = (Lon + 2) | 1;
- Lot = Lev * Lat;
- nfax = ifax[0];
- for (lev = 0; lev < Lev; ++lev)
- {
- for (lat = 0; lat < Lat; ++lat)
- {
- wix = jump * (lat + lev * Lat);
- rix = lat + lev * Lat * Fou;
- for (fou = 0 ; fou < Fou && fou < jump ; ++fou)
- wfc[wix + fou] = fc[rix + fou * Lat];
- for (fou = Fou; fou < jump; ++fou)
- wfc[wix + fou] = 0.0;
- wfc[wix+1] = 0.5 * wfc[wix];
- }
- }
- ia = 1;
- la = 1;
- for (k = 0; k < nfax; ++k) {
- ifac = ifax[k+1];
- if (k&1) rpassc(wgp,wgp+la,wfc+ia,wfc+ia+ifac*la,
- jump,jump,Lot,Lon,ifac,la);
- else rpassc(wfc+ia,wfc+ia+la,wgp,wgp+ifac*la,
- jump,jump,Lot,Lon,ifac,la);
- la *= ifac;
- ia = 0;
- }
- if (nfax & 1) wpt = wgp;
- else wpt = wfc;
- for (j = 0; j < Lot ; ++j)
- for (lon = 0; lon < Lon; ++lon)
- gp[lon + j * Lon] = wpt[lon + j * jump];
- }
- void gp2fc(double *gp, double *fc, int Lat, int Lon, int Lev, int Fou)
- {
- int Lot;
- int fou;
- int ia;
- int ifac;
- int jump;
- int k;
- int la;
- int lat;
- int lev;
- int lon;
- int lot;
- int nfax;
- int rix;
- int wix;
- double *wpt;
- /* gp2fc performs gridpoint to fourier transforms using */
- /* multiple fast fourier transform of length Lon */
- /* */
- /* fc - real array of fourier coefficients fc[Lev][Fou][Lat] */
- /* gp - real array of gridpoints gp[Lev][Lat][Lon] */
- /* Lat - Number of latitudes */
- /* Lon - Number of longitudes */
- /* Lev - Number of levels */
- /* Fou - Number of fourier coefficients on 1 latitude */
- /* a(k) = (1/n) * sum(j=0,...,n-1)(x(j) * cos(2*j*k*pi/n)) */
- /* b(k) = -(1/n) * sum(j=0,...,n-1)(x(j) * sin(2*j*k*pi/n)) */
- if (!gp) Abort("gp2fc called with NULL pointer for gp");
- if (!fc) Abort("gp2fc called with NULL pointer for fc");
- jump = (Lon + 2) | 1;
- Lot = Lev * Lat;
- nfax = ifax[0];
- rix = 0;
- wix = 0;
- for (lot = 0; lot < Lot; ++lot) {
- for (lon = 0; lon < Lon; ++lon) wgp[wix+lon] = gp[rix+lon];
- wgp[wix+Lon ] = 0.0;
- wgp[wix+Lon+1] = 0.0;
- rix += Lon;
- wix += jump;
- }
- ia = 0;
- la = Lon;
- for (k = 0; k < nfax; ++k) {
- ifac = ifax[nfax-k];
- la /= ifac;
- if (k & 1) qpassc(wfc,wfc+ifac*la,wgp+ia,wgp+ia+la,
- jump,jump,Lot,Lon,ifac,la);
- else qpassc(wgp+ia,wgp+ia+ifac*la,wfc,wfc+la,
- jump,jump,Lot,Lon,ifac,la);
- ia = 1;
- }
- if (nfax & 1) wpt = wfc;
- else wpt = wgp+1;
- for (lev = 0; lev < Lev; ++lev) {
- for (lat = 0; lat < Lat; ++lat) {
- rix = jump * (lat + lev * Lat);
- wix = lat + lev * Lat * Fou;
- fc[wix ] = wpt[rix];
- fc[wix+Lat] = 0.0;
- for (fou = 2 ; fou < Fou ; ++fou)
- fc[wix + fou * Lat] = wpt[rix + fou - 1];
- }
- }
- }
- inline void SwapIEEE(char W[4])
- {
- char B;
- B = W[0]; W[0] = W[3]; W[3] = B;
- B = W[1]; W[1] = W[2]; W[2] = B;
- }
- inline void SwapIEEE64(char W[8])
- {
- char B;
- B = W[0]; W[0] = W[3]; W[3] = B;
- B = W[1]; W[1] = W[2]; W[2] = B;
- B = W[4]; W[4] = W[7]; W[7] = B;
- B = W[5]; W[5] = W[6]; W[6] = B;
- }
- int check_fcw(int fcws, int fcwe)
- {
- if (fcwe != fcws)
- {
- printf("\n*************** ERROR reading input file **************\n");
- printf("The FORTRAN control words (FCW) of a record don't match\n");
- printf("FCW before record = %d\n",fcws);
- printf("FCW after record = %d\n",fcwe);
- printf("File position: %ld\n",ftell(fpi));
- printf("Possible causes are:\n");
- printf("1) Model crashed leaving an incomplete output file\n");
- printf("2) Corrupt data file (cache or disk problems)\n");
- return 1;
- }
- return 0;
- }
- /* =============================== */
- /* Read IEEE 32 bit data from file */
- /* =============================== */
- inline int ReadINT(void)
- {
- int k;
- fread(&k,sizeof(k),1,fpi);
- if (Endian) SwapIEEE((char *)&k);
- return k;
- }
- inline LONG ReadLONG(void)
- {
- LONG l;
- fread(&l,sizeof(l),1,fpi);
- if (Endian) SwapIEEE64((char *)&l);
- return l;
- }
- inline int ReadFCW(void)
- {
- int k;
- LONG l;
- if (LongFCW)
- {
- fread(&l,sizeof(l),1,fpi);
- if (Endian) SwapIEEE64((char *)&l);
- k = (int)l;
- }
- else
- {
- fread(&k,sizeof(k),1,fpi);
- if (Endian) SwapIEEE((char *)&k);
- }
- return k;
- }
- inline float ReadFLOAT(void)
- {
- int i;
- float f;
- i = fread(&f,sizeof(f),1,fpi);
- if (i != 1) Abort("Unexpected EOF in ReadFLOAT");
- if (Endian) SwapIEEE((char *)&f);
- return f;
- }
- inline double ReadDOUBLE(void)
- {
- int i;
- double f;
- i = fread(&f,sizeof(f),1,fpi);
- if (i != 1) Abort("Unexpected EOF in ReadDOUBLE");
- if (Endian) SwapIEEE64((char *)&f);
- return f;
- }
- inline int ReadINTRecord(void)
- {
- int k,b,e;
- b = ReadFCW();
- fread(&k,sizeof(k),1,fpi); /* IEEE 32-bit integer */
- e = ReadFCW();
- if (check_fcw(b,e)) Abort("record control word mismatch in ReadINTRecord");
- if (Endian) SwapIEEE((char *)&k);
- return k;
- }
- inline int Skip_FORTRAN_Record(void)
- {
- int fcws,fcwe;
- fcws = ReadFCW();
- if (feof(fpi)) return 0;
- fseek(fpi,fcws,SEEK_CUR);
- fcwe = ReadFCW();
- if (check_fcw(fcws,fcwe))
- Abort("record control word mismatch in Skip_FORTRAN_Record");
- return fcws;
- }
- inline void Swap_FORTRAN_Record(char *c, int n)
- {
- char b;
- int i;
- for (i=0 ; i < n ; i+=4)
- {
- b = c[i ]; c[i ] = c[i+3]; c[i+3] = b;
- b = c[i+1]; c[i+1] = c[i+2]; c[i+2] = b;
- }
- }
- inline void Swap_FORTRAN_Double(char *c, int n)
- {
- char b;
- int i;
- for (i=0 ; i < n ; i+=8)
- {
- b = c[i ]; c[i ] = c[i+7]; c[i+7] = b;
- b = c[i+1]; c[i+1] = c[i+6]; c[i+6] = b;
- b = c[i+2]; c[i+2] = c[i+5]; c[i+5] = b;
- b = c[i+3]; c[i+3] = c[i+4]; c[i+4] = b;
- }
- }
- inline int Read_FORTRAN_Record(void)
- {
- int fcws,fcwe;
- fcws = ReadFCW();
- if (feof(fpi)) return 0;
- fread(Record_char,1,fcws,fpi);
- fcwe = ReadFCW();
- if (check_fcw(fcws,fcwe)) Abort("record control word mismatch in Read_FORTRAN_Record");
- if (Endian) Swap_FORTRAN_Record(Record_char,fcws);
- return fcws;
- }
- inline int Read_FORTRAN_Double_Record(void)
- {
- int fcws,fcwe;
- fcws = ReadFCW();
- if (feof(fpi)) return 0;
- fread(Record_char,1,fcws,fpi);
- fcwe = ReadFCW();
- if (check_fcw(fcws,fcwe)) Abort("record control word mismatch in Read_FORTRAN_Double_Record");
- if (Endian) Swap_FORTRAN_Double(Record_char,fcws);
- return fcws;
- }
- int ReadHeaderRecord(void)
- {
- int h,i,fcws,fcwe;
-
- fcws = ReadFCW();
- if (feof(fpi)) return 1;
- if (fcws == 8) /* Skip PUMA header */
- {
- if (Debug)
- {
- printf("Skipping %d header words\n",HeaderWords);
- for (i=0 ; i < HeaderWords ; ++i)
- {
- h = ReadINT();
- printf("HW[%2d] = %8x %d\n",i,h,h);
- }
- }
- else
- for (i=0 ; i < HeaderWords ; ++i) ReadINT();
- fcws = ReadFCW();
- if (feof(fpi))
- {
- printf("\n#### Empty data file #####\n");
- printf("Mark [Write Ouput] in MoSt\n");
- printf("or set NOUTPUT=1 in file <puma_namelist>\n");
- Abort("Empty data file");
- }
- }
- if (fcws != HeadSize)
- {
- printf("FCW = %d (should be %d)\n",fcws,HeadSize);
- Abort("Wrong FCW found in ReadHeaderRecord");
- }
- for (i=0 ; i < 8 ; ++i)
- {
- if (HeadSize == 32) HeadIn[i] = ReadINT();
- else HeadIn[i] = ReadLONG();
- }
- fcwe = ReadFCW();
- if (check_fcw(fcws,fcwe)) Abort("FCW mismatch in ReadHeaderRecord");
- return 0;
- }
-
-
- void DecodePumaHeader(void)
- {
- PumaCode = HeadIn[0];
- PumaLevel = HeadIn[1];
- NewDate.tm_year = HeadIn[2] / 10000;
- NewDate.tm_mon = HeadIn[2] / 100 % 100;
- NewDate.tm_mday = HeadIn[2] % 100;
- NewDate.tm_hour = HeadIn[3] / 100;
- NewDate.tm_min = HeadIn[3] % 100;
- if (DayDivisor > 1) NewMonth = (TermCount / DPM) % 12 + 1;
- else NewMonth = NewDate.tm_mon;
- if (HeadIn[4] * HeadIn[5] == DimSP) RepGrib = REP_SPECTRAL;
- else RepGrib = REP_GAUSS;
- if (PumaCode < 0 || PumaCode >= CODES)
- {
- printf("Illegal Code %d in header\n",PumaCode);
- Abort("Code < 0 or Code > CODES found");
- }
- All[PumaCode].detected = TRUE;
- }
- // =============
- // ReadPumaArray
- // =============
- void ReadPumaArray(double *Array)
- {
- int i,j,fcws;
- double zfac;
- double zmin;
- if (RealSize == sizeof(float)) fcws = Read_FORTRAN_Record();
- else fcws = Read_FORTRAN_Double_Record();
- if (fcws == sizeof(float) * (Truncation + 2)) // Packed spectral data
- {
- for (i=0 ; i <= Truncation ; i++)
- {
- Array[2*i ] = Record_float[i];
- Array[2*i+1] = 0.0; // Imaginary parts of zonal modes
- }
- zfac = 1.0 / Record_float[Truncation+1];
- fcws = Read_FORTRAN_Record();
- if (CoreBigEndian)
- {
- for (i=2*Truncation+2,j=0 ; i < DimSP ; ++i,++j)
- {
- Array[i] = (Record_short[j] - 32768) * zfac;
- }
- }
- else
- {
- for (i=2*Truncation+2,j=0 ; i < DimSP ; i+=2,j+=2)
- {
- Array[i ] = (Record_short[j+1] - 32768) * zfac;
- Array[i+1] = (Record_short[j ] - 32768) * zfac;
- }
- }
- }
- else if (fcws == sizeof(float) * DimSP) // Unpacked spectral float data
- {
- for (i=0 ; i < DimSP ; ++i) Array[i] = Record_float[i];
- }
- else if (fcws == sizeof(double) * DimSP) // Unpacked spectral double data
- {
- memcpy(Array,Record_double,fcws);
- }
- else if (fcws == sizeof(float) * DimGG) // Unpacked grid float data
- {
- for (i=0 ; i < DimGG ; ++i) Array[i] = Record_float[i];
- }
- else if (fcws == sizeof(double) * DimGG) // Unpacked grid double data
- {
- memcpy(Array,Record_double,fcws);
- }
- else if (fcws == 8) /* Packed grid data */
- {
- zmin = Record_float[0];
- zfac = 1.0 / Record_float[1];
- fcws = Read_FORTRAN_Record();
- if (CoreBigEndian)
- {
- for (i=0 ; i < DimGG ; ++i)
- {
- Array[i] = Record_short[i] * zfac + zmin;
- }
- }
- else
- {
- for (i=0 ; i < DimGG ; i+=2)
- {
- Array[i ] = Record_short[i+1] * zfac + zmin;
- Array[i+1] = Record_short[i ] * zfac + zmin;
- }
- }
- }
- else Abort("fcws error in ReadPumaArray");
- }
- /* ============= */
- /* SkipPumaArray */
- /* ============= */
- void SkipPumaArray(void)
- {
- int fcws;
- fcws = Skip_FORTRAN_Record();
- if (fcws == 8 || fcws == 4 * (Truncation + 2))
- fcws = Skip_FORTRAN_Record();
- }
- /* ============================================= */
- /* phcs - Compute values of Legendre polynomials */
- /* and their meridional derivatives */
- /* ============================================= */
- void phcs(double *PNM, double *HNM, int Waves, double PMU,
- double *ZTEMP1, double *ZTEMP2)
- {
- long TwoWaves;
- long JK;
- long JN;
- long JM;
- double JNmJK;
- double ZCOS2;
- double Lat;
- double ZAN;
- double ZSINPAR;
- double ZCOSPAR;
- double ZSQP;
- double ZCOSFAK;
- double ZSINFAK;
- double ZQ;
- double ZWM2;
- double ZW;
- double ZWQ;
- double ZQ2M1;
- double ZWM2Q2;
- double Z2Q2;
- double ZCNM;
- double ZDNM;
- double ZENM;
- TwoWaves = Waves << 1;
- ZCOS2 = sqrt(1.0 - PMU * PMU);
- Lat = acos(PMU);
- ZAN = 1.0;
- ZTEMP1[0] = 0.5;
- for (JN = 1; JN < TwoWaves; JN++) {
- ZSQP = 1.0 / sqrt((double)(JN+JN*JN));
- ZAN *= sqrt(1.0 - 1.0 / (4 * JN * JN));
- ZCOSPAR = cos(Lat * JN);
- ZSINPAR = sin(Lat * JN) * JN * ZSQP;
- ZCOSFAK = 1.0;
- for (JK = 2; JK < JN; JK += 2) {
- JNmJK = JN - JK;
- ZCOSFAK *= (JK-1) * (JN+JNmJK+2) / (JK * (JN+JNmJK+1));
- ZSINFAK = ZCOSFAK * (JNmJK) * ZSQP;
- ZCOSPAR += ZCOSFAK * cos(Lat * JNmJK);
- ZSINPAR += ZSINFAK * sin(Lat * JNmJK);
- }
- /* Code for JK == JN */
- if ((JN & 1) == 0) {
- ZCOSFAK *= (double)((JN-1) * (JN+2)) / (double)(JN * (JN+1));
- ZCOSPAR += ZCOSFAK * 0.5;
- }
- ZTEMP1[JN ] = ZAN * ZCOSPAR;
- ZTEMP2[JN-1] = ZAN * ZSINPAR;
- }
- memcpy(PNM,ZTEMP1,Waves * sizeof(double));
- PNM += Waves;
- memcpy(PNM,ZTEMP2,Waves * sizeof(double));
- PNM += Waves;
- HNM[0] = 0.0;
- for (JN = 1; JN < Waves; JN++) HNM[JN] =
- JN * (PMU * ZTEMP1[JN] - sqrt((JN+JN+1.0) / (JN+JN-1.0)) * ZTEMP1[JN-1]);
- HNM += Waves;
- HNM[0] = PMU * ZTEMP2[0];
- for (JN = 1; JN < Waves; JN++)
- HNM[JN] = (JN+1) * PMU * ZTEMP2[JN]
- - sqrt((double)((JN+JN+3) * ((JN+1) * (JN+1) - 1))
- / (double)(JN+JN+1)) * ZTEMP2[JN-1];
- HNM += Waves;
- for (JM = 2; JM < Waves; JM++) {
- PNM[0] = sqrt(1.0 + 1.0 / (JM+JM)) * ZCOS2 * ZTEMP2[0];
- HNM[0] = JM * PMU * PNM[0];
- for (JN = 1; JN < TwoWaves-JM; JN++) {
- ZQ = JM + JM + JN - 1;
- ZWM2 = ZQ+JN;
- ZW = ZWM2+2;
- ZWQ = ZW*ZQ;
- ZQ2M1 = ZQ*ZQ-1.;
- ZWM2Q2 = ZWM2*ZQ2M1;
- Z2Q2 = ZQ2M1*2;
- ZCNM = sqrt((ZWQ*(ZQ-2.))/(ZWM2Q2-Z2Q2));
- ZDNM = sqrt((ZWQ*(JN+1.))/ZWM2Q2);
- ZENM = sqrt(ZW * JN /((ZQ+1.0) * ZWM2));
- PNM[JN] = ZCNM * ZTEMP1[JN] - PMU
- * (ZDNM * ZTEMP1[JN+1] - ZENM * PNM[JN-1]);
- HNM[JN] = (JM + JN) * PMU * PNM[JN]
- - sqrt(ZW * JN * (ZQ+1) / ZWM2) * PNM[JN-1];
- }
- memcpy(ZTEMP1,ZTEMP2,TwoWaves * sizeof(double));
- memcpy(ZTEMP2,PNM ,TwoWaves * sizeof(double));
- PNM += Waves;
- HNM += Waves;
- }
- }
- void legini(void)
- {
- int jlat,jm,jn,jz;
- int jsp,pdim,hdim;
- double *hnm,*pnm,*ZTEMP1,*ZTEMP2,gmusq;
- double znn1,zgmu;
- char tb[COLS+2];
- double poliv,pol2v,pliuv,plivv;
- hdim = 2 * Waves * Waves;
- if (PolyCreate) /* Generate filenames for polynomials */
- {
- sprintf(polin,"b6poli.T%d",Truncation);
- sprintf(pol2n,"b6pol2.T%d",Truncation);
- sprintf(pliun,"b6pliu.T%d",Truncation);
- sprintf(plivn,"b6pliv.T%d",Truncation);
- }
- else if (PolyDisk) /* Generate filenames for polynomials */
- {
- sprintf(polin,"/comm/T1365/b6poli.t%d",Truncation);
- sprintf(pol2n,"/comm/T1365/b6pol2.t%d",Truncation);
- sprintf(pliun,"/comm/T1365/b6pliu.t%d",Truncation);
- sprintf(plivn,"/comm/T1365/b6pliv.t%d",Truncation);
- polif = fopen(polin,"r");
- pol2f = fopen(pol2n,"r");
- pliuf = fopen(pliun,"r");
- plivf = fopen(plivn,"r");
- if (polif && pol2f && pliuf && plivf)
- sprintf(tb,"Legendre Polynomials read from disk");
- else
- {
- sprintf(tb,"Legendre Polynomials calculated");
- PolyDisk = 0;
- }
- CenterText(tb);
- }
- if (PolyDisk) pdim = Lats;
- else pdim = Lats * DimSP_half;
- poli = new double[pdim];
- pol2 = new double[pdim];
- pliu = new double[pdim];
- pliv = new double[pdim];
- pnm = new double[hdim];
- hnm = new double[hdim];
- ZTEMP1 = new double[Fouriers];
- ZTEMP2 = new double[Fouriers];
- // if gridtype for output is not selected, choose Gauss grid
- // for matching resolution and regular grid else
- if (GaussGrid < 0) GaussGrid = (Lats == Gats && Lons == Gons);
- Gaulat = new GauLat(Gats,"Gaulat"); // Gaussian latitudes of input grid
- Outlon = new RegLon(Lons,"Outlon"); // Regular longitudes of output grid
- if (GaussGrid) Outlat = new GauLat(Lats,"Outlat");
- else Outlat = new RegLat(Lats,"Outlat");
- if (Debug)
- {
- Gaulat->PrintArray();
- if (Lats != Gats || !GaussGrid) Outlat->PrintArray();
- Outlon->PrintArray();
- }
- if (PolyCreate)
- {
- polif = fopen(polin,"w");
- pol2f = fopen(pol2n,"w");
- pliuf = fopen(pliun,"w");
- plivf = fopen(plivn,"w");
- for (jlat = 0 ; jlat < Lats ; ++jlat)
- {
- gmusq = 1.0 - Outlat->gmu[jlat] * Outlat->gmu[jlat];
- zgmu = sqrt(gmusq);
- phcs(pnm,hnm,Waves,Outlat->gmu[jlat],ZTEMP1,ZTEMP2);
- for (jm = 0; jm < Waves; jm++)
- {
- for (jn = 0; jn < Waves - jm ; jn++)
- {
- jz = jm+jn;
- znn1 = 0.0;
- if (jz > 0) znn1 = 1.0 / (jz * (jz+1));
- poliv = pnm[jm*Waves+jn] * 2.0;
- fwrite(&poliv,sizeof(double),1,polif);
- pol2v = hnm[jm*Waves+jn] / PlanetRadius;
- fwrite(&pol2v,sizeof(double),1,pol2f);
- pliuv = pnm[jm*Waves+jn] * 2.0 * PlanetRadius * znn1 * jm / zgmu;
- fwrite(&pliuv,sizeof(double),1,pliuf);
- plivv = hnm[jm*Waves+jn] * 2.0 * PlanetRadius * znn1 / zgmu;
- fwrite(&plivv,sizeof(double),1,plivf);
- }
- }
- }
- }
- else if (PolyDisk)
- {
- for (jlat = 0 ; jlat < Lats ; ++jlat)
- {
- gmusq = 1.0 - Outlat->gmu[jlat] * Outlat->gmu[jlat];
- CosPhi[jlat] = sqrt(gmusq);
- RevCosPhi[jlat] = 1.0 / CosPhi[jlat];
- DerivationFactor[jlat] = RevCosPhi[jlat] / PlanetRadius;
- }
- }
- else /* Normal computation of polynomials */
- {
- for (jlat = 0 ; jlat < Lats ; ++jlat)
- {
- gmusq = 1.0 - Outlat->gmu[jlat] * Outlat->gmu[jlat];
- CosPhi[jlat] = sqrt(gmusq);
- RevCosPhi[jlat] = 1.0 / CosPhi[jlat];
- DerivationFactor[jlat] = RevCosPhi[jlat] / PlanetRadius;
- phcs(pnm,hnm,Waves,Outlat->gmu[jlat],ZTEMP1,ZTEMP2);
- jsp = jlat;
- for (jm = 0; jm < Waves; jm++)
- {
- for (jn = 0; jn < Waves - jm ; jn++)
- {
- jz = jm+jn;
- znn1 = 0.0;
- if (jz > 0) znn1 = 1.0 / (jz * (jz+1));
- poli[jsp] = pnm[jm*Waves+jn] * 2.0;
- pol2[jsp] = hnm[jm*Waves+jn] / PlanetRadius;
- pliu[jsp] = pnm[jm*Waves+jn] * 2.0 * PlanetRadius * znn1 * jm / sqrt(gmusq);
- pliv[jsp] = hnm[jm*Waves+jn] * 2.0 * PlanetRadius * znn1 / sqrt(gmusq);
- jsp += Lats;
- }
- }
- }
- }
- delete [] pnm;
- delete [] hnm;
- delete [] ZTEMP1;
- delete [] ZTEMP2;
- }
- void spvfc(double *sd, double *sz, double *fu, double *fv, int klev,int nlat,int nfc,int nt)
- {
- int lev,jmm,jfc,lat;
- double sdr,sdi,szr,szi;
- double *fur,*fui,*fvr,*fvi;
- double *poa,*pob;
- DoubleZero(fu,klev*nlat*nfc);
- DoubleZero(fv,klev*nlat*nfc);
- for (lev = 0; lev < klev; lev++)
- {
- if (PolyDisk)
- {
- rewind(pliuf);
- rewind(plivf);
- }
- poa = pliu;
- pob = pliv;
- for (jmm = 0; jmm <= nt; jmm++)
- {
- for (jfc = jmm; jfc <= nt; jfc++)
- {
- sdr = *sd++;
- sdi = *sd++;
- szr = *sz++;
- szi = *sz++;
- fur = fu ;
- fui = fu + nlat;
- fvr = fv ;
- fvi = fv + nlat;
- if (PolyDisk)
- {
- fread(poa=pliu,sizeof(double),Lats,pliuf);
- fread(pob=pliv,sizeof(double),Lats,plivf);
- }
- for (lat = 0; lat < nlat; lat++)
- {
- *fur += -*pob * szr + *poa * sdi;
- *fui += -*pob * szi - *poa * sdr;
- *fvr += *poa * szi + *pob * sdr;
- *fvi += -*poa * szr + *pob * sdi;
- fur++;
- fui++;
- fvr++;
- fvi++;
- poa++;
- pob++;
- }
- }
- fu += 2 * nlat;
- fv += 2 * nlat;
- }
- }
- }
- // ========================================
- // sp2fci - Inverse Legendre Transformation
- // ========================================
- void sp2fci(double *sa,double *fa,int klev)
- {
- int lev,m,n;
- double sar,sai;
- double *Far,*Fai,*pol;
- DoubleZero(fa,klev*DimFC);
- for (lev = 0; lev < klev; ++lev)
- {
- if (PolyDisk) rewind(polif);
- pol = poli;
- for (n = 0; n <= Truncation; ++n)
- {
- if (PolyDisk) fread(pol=poli,sizeof(double),Lats,polif);
- sar = *sa;
- sa += 2;
- for (Far=fa; Far < fa+Lats;++Far,++pol)
- {
- *Far += *pol * sar;
- }
- }
- fa += 2 * Lats;
- for (m = 1; m <= Truncation; ++m)
- {
- for (n = m; n <= Truncation; ++n)
- {
- if (PolyDisk) fread(pol=poli,sizeof(double),Lats,polif);
- sar = *sa++ ;
- sai = *sa++ ;
- for (Far=fa,Fai=fa+Lats; Far<fa+Lats; ++Far,++Fai,++pol)
- {
- *Far += *pol * sar;
- *Fai += *pol * sai;
- }
- }
- fa += 2 * Lats;
- }
- }
- }
- void sp2fcd(double *sa,double *fa,int klev,int nlat,int nfc,int nt)
- {
- int lev,jmm,jfc,lat;
- double sar,sai;
- double *Far,*fai,*pol;
- double zpo;
- DoubleZero(fa,klev*nlat*nfc);
- for (lev = 0; lev < klev; lev++)
- {
- pol = pol2;
- if (PolyDisk) rewind(pol2f);
- for (jmm = 0; jmm <= nt; jmm++)
- {
- for (jfc = jmm; jfc <= nt; jfc++)
- {
- sar = *sa++ ;
- sai = *sa++ ;
- Far = fa ;
- fai = fa + nlat ;
- if (PolyDisk) fread(pol=pol2,sizeof(double),Lats,pol2f);
- for (lat = 0; lat < nlat; lat++)
- {
- zpo = -2.0 * *pol * RevCosPhi[lat];
- *Far += zpo * sar;
- *fai += zpo * sai;
- Far++;
- fai++;
- pol++;
- }
- }
- fa += 2 * nlat;
- }
- }
- }
- void fc2sp(double *fa, double *sa, int klev, int nlat, int nt)
- {
- int lev,jmm,jfc,lat;
- double sar,sai,*Far,*fai,*pol;
- double zpo;
- for (lev = 0; lev < klev; lev++)
- {
- pol = poli;
- if (PolyDisk) rewind(polif);
- for (jmm = 0; jmm <= nt; jmm++)
- {
- for (jfc = jmm; jfc <= nt; jfc++)
- {
- Far = fa ;
- fai = fa + nlat ;
- sar = 0.0 ;
- sai = 0.0 ;
- if (PolyDisk) fread(pol=poli,sizeof(double),Lats,polif);
- for (lat = 0; lat < nlat; lat++)
- {
- zpo = *pol * 0.5 * Outlat->gwt[lat];
- sar += zpo * *Far;
- sai += zpo * *fai;
- Far++;
- fai++;
- pol++;
- }
- *sa++ = sar;
- *sa++ = sai;
- }
- fa += 2 * nlat;
- }
- }
- }
- void OMEGA(void)
- {
- int i,j;
- double DeltaHybrid;
- double Cterm;
- double Pterm;
- double *omega = &Omega->hgp[0];
- double *diver = &Divergence->hgp[0];
- double *halfp = &HalfPress->hgp[0];
- double *fullp = &FullPress->hgp[0];
- double *uwind = &u_wind->hgp[0];
- double *vwind = &v_wind->hgp[0];
- /* Compute half level part of vertical velocity */
- for (i = 0; i < DimGP ; i++) omega[i] = 0.0;
- for (j = 0; j < SigLevs; j++) {
- DeltaHybrid = vct[SigLevs+j+2] - vct[SigLevs+j+1];
- for (i = 0; i < DimGP; i++) {
- omega[DimGP] = *omega
- - *diver * (halfp[DimGP] - *halfp) - DeltaHybrid
- * (*uwind * dpsdx->hgp[i]
- + *vwind * dpsdy->hgp[i]);
- omega++;
- halfp++;
- diver++;
- uwind++;
- vwind++;
- }
- }
- /* interpolate to full levels */
- omega = &Omega->hgp[0];
- for (i = 0; i < Dim3GP; i++)
- omega[i] = 0.5 * (omega[i] + omega[i+DimGP]);
- /* compute full level part of vertical velocity */
- omega = &Omega->hgp[0];
- halfp = &HalfPress->hgp[0];
- fullp = &FullPress->hgp[0];
- uwind = &u_wind->hgp[0];
- vwind = &v_wind->hgp[0];
- for (j = 0; j < SigLevs; j++) {
- DeltaHybrid = vct[SigLevs+j+2] - vct[SigLevs+j+1];
- if (DeltaHybrid) {
- Cterm = vct[j+1] * vct[SigLevs+j+1] - vct[j] * vct[SigLevs+j+2];
- for (i = 0; i < DimGP; i++) {
- if (Cterm != 0.0) Pterm = Cterm /
- (halfp[DimGP] - *halfp) * log(halfp[DimGP] / *halfp);
- else Pterm = 0.0;
- *omega += *fullp *
- (*uwind * dpsdx->hgp[i] + *vwind * dpsdy->hgp[i])
- / (halfp[DimGP] - *halfp) * (DeltaHybrid + Pterm);
- omega++;
- halfp++;
- fullp++;
- uwind++;
- vwind++;
- }
- }
- else {
- omega += DimGP;
- halfp += DimGP;
- fullp += DimGP;
- uwind += DimGP;
- vwind += DimGP;
- }
- }
- }
- void Omega_w(double w[], double om[], double T[], double P[])
- {
- int i;
- for (i=0 ; i < Dim3GP ; ++i)
- {
- w[i] = -om[i] * RD * T[i] / (Grav * P[i]);
- }
- }
- void Extrap(double *slp, double *aph, double *apf,
- double *Geopotential, double *t, int nhor)
- {
- double zrg = 1.0 / Grav;
- double alpha,tstar,tmsl,ZPRT,ZPRTAL;
- int j;
- for (j = 0; j < nhor; ++j) {
- if (Geopotential[j] < 0.0001 && Geopotential[j] > -0.0001) slp[j] = aph[j];
- else {
- alpha = RD * RLAPSE * zrg;
- tstar = (1.0 + alpha * (aph[j]/apf[j] - 1.0)) * t[j];
- if (tstar < 255.0) tstar = 0.5 * (255.0 + tstar);
- tmsl = tstar + RLAPSE * zrg * Geopotential[j];
- if (tmsl > 290.5 && tstar > 290.5) {
- tstar = 0.5 * (290.5 + tstar);
- tmsl = tstar;
- }
- if (tmsl-tstar < 0.000001 && tstar-tmsl < 0.000001) alpha = 0.0;
- else if (Geopotential[j] > 0.0001 || Geopotential[j] < -0.0001)
- alpha = RD * (tmsl-tstar) / Geopotential[j];
- ZPRT = Geopotential[j] / (RD * tstar);
- ZPRTAL = ZPRT * alpha;
- slp[j] = aph[j] * exp(ZPRT*(1.0-ZPRTAL*(0.5-ZPRTAL/3.0)));
- }
- }
- }
- double ExtraT(double PRES, double APH, double APF, double GEOS, double T)
- {
- double zrg = 1.0 / Grav;
- double tstar,ztsz,Z1,ZTMSL,ZALPH,PEVAL,ZHTS,ZALP;
- tstar = (1.0 + RLAPSE * RD * zrg * (APH/APF - 1.0)) * T;
- ztsz = tstar;
- Z1 = tstar + RLAPSE * zrg * GEOS;
- if (tstar < 255.0) tstar = 0.5 * (255.0 + tstar);
- ZTMSL = tstar + RLAPSE * zrg * GEOS;
- if (ZTMSL > 290.5 && tstar > 290.5)
- {
- tstar = 0.5 * (290.5 + tstar);
- ZTMSL = tstar;
- }
- if (ZTMSL > 290.5 && tstar <= 290.5) ZTMSL=290.5;
- ZALPH=RD*RLAPSE*zrg;
- if ( ZTMSL-tstar < 0.000001 && tstar-ZTMSL < 0.000001) ZALPH=0.0;
- if ((ZTMSL-tstar > 0.000001 || tstar-ZTMSL > 0.000001) &&
- (GEOS > 0.0001 || GEOS < -0.0001))
- ZALPH=RD*(ZTMSL-tstar)/GEOS;
- if (PRES <= APH) PEVAL = ((APH-PRES)*T+ (PRES-APF)*tstar)/ (APH-APF);
- else
- {
- ZTMSL=Z1;
- tstar=ztsz;
- ZHTS=GEOS*zrg;
- if (ZHTS > 2000. && Z1 > 298.)
- {
- ZTMSL=298.;
- if (ZHTS < 2500.) ZTMSL=0.002*((2500.-ZHTS)*Z1+(ZHTS-2000.)*ZTMSL);
- }
- if ((ZTMSL-tstar) < 0.000001) ZALPH=0.;
- else if (GEOS > 0.0001 || GEOS < -0.0001) ZALPH=RD*(ZTMSL-tstar)/GEOS;
- else ZALPH=RD*RLAPSE*zrg;
- ZALP=ZALPH*log(PRES/APH);
- PEVAL=tstar*(1.0+ZALP*(1.0+ZALP*(0.5+0.16666666667*ZALP)));
- }
- return PEVAL;
- }
- double ExtraZ(double pres, double aph, double apf, double sg, double t)
- {
- double zrg = 1.0 / Grav;
- double alpha,tstar,tmsl,ZALP,ZALPAL;
- alpha = RD * RLAPSE * zrg;
- tstar = (1.0 + alpha * (aph/apf - 1.0)) * t;
- if (tstar < 255.0) tstar = 0.5 * (255.0 + tstar);
- tmsl = tstar + RLAPSE * zrg * sg;
- if (tmsl > 290.5 && tstar > 290.5)
- {
- tstar = 0.5 * (290.5 + tstar);
- tmsl = tstar;
- }
- if (tmsl > 290.5 && tstar <= 290.5) tmsl = 290.5;
- if (tmsl-tstar < 0.000001 && tstar-tmsl < 0.000001) alpha = 0.0;
- else if (sg > 0.0001 || sg < -0.0001) alpha = RD * (tmsl-tstar) / sg;
- ZALP = log(pres/aph);
- ZALPAL = ZALP * alpha;
- return (sg - RD * tstar * ZALP * (1.0 + ZALPAL * (0.5 + ZALPAL/6.0))) * zrg;
- }
- void Interpolate_T(int Code)
- {
- int lp, i;
- int nl,nh;
- double pres;
- int *nx = vert_index;
- double *gt = &All[Code].hgp[0];
- double *pt = &All[Code].pgp[0];
- double *pf = &FullPress->hgp[0];
- double *ph = &HalfPress->hgp[0];
-
- for (lp = 0; lp < OutLevs; lp++)
- {
- pres = level[lp];
- for (i = 0; i < DimGP; i++)
- {
- nl = i + DimGP * *nx;
- nh = nl + DimGP;
- if (nl < 0) // Above top level
- {
- *pt = gt[i];
- }
- else if (nh >= Dim3GP) // Below bottom level
- {
- if (!mars && Code == TCODE) *pt = ExtraT(pres,ph[nh],pf[nl],Orography[i],gt[nl]);
- else *pt = gt[nl];
- }
- else // Inside
- {
- *pt = gt[nl] + (pres-pf[nl]) * (gt[nh]-gt[nl]) / (pf[nh]-pf[nl]);
- }
- ++nx;
- ++pt;
- }
- }
- }
- void Interpolate_Z(void)
- {
- int lp, i;
- int nl,nh;
- double pres;
- int *nx = vert_index;
- double *gz = &GeopotHeight->hgp[0];
- double *pz = &GeopotHeight->pgp[0];
- double *gt = &Temperature->hgp[0];
- double *pf = &FullPress->hgp[0];
- double *ph = &HalfPress->hgp[0];
-
- for (lp = 0; lp < OutLevs; lp++)
- {
- pres = level[lp];
- for (i = 0; i < DimGP; i++)
- {
- nl = i + DimGP * *nx;
- if (pres > ph[nl+DimGP]) nl += DimGP;
- nh = nl + DimGP;
- if (nl < 0) // Above top level
- {
- *pz = gz[i];
- }
- else if (nl >= Dim3GP) // Below bottom level
- {
- if (mars) *pz = gz[nl-DimGP];
- else *pz = ExtraZ(pres,ph[nl], pf[nl-DimGP],Orography[i],gt[nl-DimGP]);
- }
- else // Inside
- {
- *pz = gz[nl] + (pres-ph[nl]) * (gz[nh]-gz[nl]) / (ph[nh] - ph[nl]);
- }
- ++nx;
- ++pz;
- }
- }
- }
- void CheckDependencies(void)
- {
- u_wind->needed = ( Divergence->needed && !Divergence->detected) ||
- ( Vorticity->needed && !Vorticity->detected) ||
- ( VeloPot->needed && !VeloPot->detected) ||
- ( StreamF->needed && !StreamF->detected) ||
- ( Omega->needed && !Omega->detected) ||
- ( speed->needed && !speed->detected) ||
- ( v_wind->needed && !v_wind->detected) ||
- u_wind->selected;
- v_wind->needed = ( Divergence->needed && !Divergence->detected) ||
- ( Vorticity->needed && !Vorticity->detected) ||
- ( VeloPot->needed && !VeloPot->detected) ||
- ( StreamF->needed && !StreamF->detected) ||
- ( Omega->needed && !Omega->detected) ||
- ( speed->needed && !speed->detected) ||
- ( u_wind->needed && !u_wind->detected) ||
- v_wind->selected;
- Divergence->needed = ( u_wind->needed && !u_wind->detected) ||
- ( v_wind->needed && !v_wind->detected) ||
- ( Omega->needed && !Omega->detected) ||
- ( VeloPot->needed && !VeloPot->detected) ||
- Divergence->selected;
- Vorticity->needed = ( u_wind->needed && !u_wind->detected) ||
- ( v_wind->needed && !v_wind->detected) ||
- ( StreamF->needed && !StreamF->detected) ||
- Vorticity->selected;
- Humidity->needed = (GeopotHeight->needed && !GeopotHeight->detected) ||
- ( Rhumidity->needed && !Rhumidity->detected) ||
- Humidity->selected;
- Ps->needed |= dpsdx->needed || dpsdy->needed ||
- Rhumidity->needed || Omega->needed;
- LnPs->needed |= Ps->needed;
- Temperature->needed = (GeopotHeight->needed && !GeopotHeight->detected) ||
- ( Rhumidity->needed && !Rhumidity->detected) ||
- ( SLP->needed && !SLP->detected) ||
- ( w_wind->needed && !w_wind->detected) ||
- Temperature->selected;
- All[176].needed = ( net_heat->needed && !net_heat->detected) ||
- ( net_bot->needed && !net_bot->detected) ||
- ( net_atm->needed && !net_atm->detected) ||
- ( sw_atm->needed && !sw_atm->detected) ||
- All[176].selected;
- All[177].needed = ( net_heat->needed && !net_heat->detected) ||
- ( net_bot->needed && !net_bot->detected) ||
- ( net_atm->needed && !net_atm->detected) ||
- ( lw_atm->needed && !lw_atm->detected) ||
- All[177].selected;
- All[178].needed = ( net_top->needed && !net_top->detected) ||
- ( net_atm->needed && !net_atm->detected) ||
- ( sw_atm->needed && !sw_atm->detected) ||
- All[178].selected;
- All[179].needed = ( net_top->needed && !net_top->detected) ||
- ( net_atm->needed && !net_atm->detected) ||
- ( lw_atm->needed && !lw_atm->detected) ||
- All[179].selected;
- }
- void CheckContent(void)
- {
- int code;
- for (code = 0; code < 256; code++)
- {
- if (code == GEOSCODE) continue;
- if (code == SLPCODE) continue;
- if (code == ZCODE) continue;
- if (code == STRCODE) continue;
- if (code == VELCODE) continue;
- if (code == UCODE) continue;
- if (code == VCODE) continue;
- if (code == WCODE) continue;
- if (code == RHCODE) continue;
- if (code == PSCODE) continue;
- if (code == WZCODE) continue;
- if (code == SHCODE)
- {
- if (All[code].needed && !All[code].selected &&
- All[code].hsp.size() == 0 &&
- All[code].hgp.size() == 0 &&
- HumInfo == 0)
- {
- printf("\n ********* I N F O **********\n");
- printf( " * No humidity in data file *\n");
- printf( " * Humidity set to zero ! *\n");
- printf( " ****************************\n");
- All[code].needed = FALSE;
- HumInfo = 1;
- }
- }
- else
- {
- if (All[code].needed &&
- All[code].hsp.size() == 0 &&
- All[code].hgp.size() == 0)
- {
- printf("\n ****** E R R O R ******\n");
- printf(" * Code %3d not found *\n",code);
- printf(" ***********************\n");
- exit(1);
- }
- }
- }
- }
- void Dependencies(void)
- {
- int code;
- for (code = 0; code < CODES; code++)
- All[code].needed = All[code].selected;
- CheckDependencies();
- if (OutRep >= PRE_GRID)
- {
- u_wind->needed |= Divergence->needed;
- v_wind->needed |= Divergence->needed;
- u_wind->needed |= Vorticity->needed;
- v_wind->needed |= Vorticity->needed;
- u_wind->needed |= VeloPot->needed;
- v_wind->needed |= VeloPot->needed;
- u_wind->needed |= StreamF->needed;
- v_wind->needed |= StreamF->needed;
- }
- Omega->needed |= w_wind->needed;
- dpsdx->needed |= Omega->needed;
- dpsdy->needed |= Omega->needed;
- if (VerType == 'p')
- {
- LnPs->needed = TRUE;
- Divergence->needed |= Omega->needed;
- u_wind->needed |= Omega->needed;
- v_wind->needed |= Omega->needed;
- u_wind->needed |= speed->needed;
- v_wind->needed |= speed->needed;
- Temperature->needed |= Omega->needed || SLP->needed;
- Humidity->needed |= GeopotHeight->needed || Rhumidity->needed;
- Temperature->needed |= GeopotHeight->needed || Rhumidity->needed ||
- ThetaF->needed;
- }
- Divergence->needed |= u_wind->needed || v_wind->needed;
- Vorticity->needed |= u_wind->needed || v_wind->needed;
- Divergence->needed |= VeloPot->needed;
- Vorticity->needed |= StreamF->needed;
- LnPs->needed |= HalfPress->needed || dpsdx->needed ||
- Ps->needed || Rhumidity->needed;
- All[139].needed |= ThetaF->selected;
- All[142].needed |= precip->selected || net_water->selected ||
- fresh_water->selected || surf_runoff->selected;
- All[143].needed |= precip->selected || net_water->selected ||
- fresh_water->selected || surf_runoff->selected;
- All[146].needed |= net_heat->selected; /* sensible heat */
- All[147].needed |= net_heat->selected; /* latent heat */
- All[160].needed |= net_water->selected; /* Runoff */
- All[176].needed |= net_heat->selected ||
- net_bot->selected ||
- net_atm->selected || sw_atm->selected;
- All[177].needed |= net_heat->selected ||
- net_bot->selected ||
- net_atm->selected || lw_atm->selected;
- All[178].needed |= net_top->selected ||
- net_atm->selected || sw_atm->selected;
- All[179].needed |= net_top->selected ||
- net_atm->selected || lw_atm->selected;
- All[182].needed |= net_water->selected ||
- fresh_water->selected || surf_runoff->selected;
- All[218].needed |= net_heat->selected; /* snow melt */
- All[221].needed |= surf_runoff->selected; /* snow depth change */
- }
- void Speed(double *speed, double *u, double *v)
- {
- int i;
- for (i = 0; i < Dim3GP; i++)
- speed[i] = sqrt(u[i] * u[i] + v[i] * v[i]);
- }
- // ======================================================
- // Compute derivation d(LnPs)/d(sin phi) in fourier space
- // ======================================================
- void Deriva(double field[], double derilam[])
- {
- int l,n;
- int i;
- i = 0;
- for (n = 0; n < Waves ; n++)
- {
- for (l = 0; l < Lats; l++,i++) // cosine coefficients
- derilam[i] = -n * field[i+Lats] * DerivationFactor[l];
- for (l = 0; l < Lats; l++,i++) // sine coefficients
- derilam[i] = n * field[i-Lats] * DerivationFactor[l];
- }
- }
- void scaluv(double *fu, double Factor[], int nlat, int nlot)
- {
- for (int lot = 0; lot < nlot; lot++)
- for (int lat = 0; lat < nlat; lat++)
- {
- *fu++ *= Factor[lat];
- }
- }
- void uv2dv(double *fu, double *fv, double *sd, double *sv,
- double *pol2, double *poli, int klev, int nlat, int nt)
- {
- int lev,jmm,jfc,lat;
- double dir,dii,vor,voi;
- double *ufr,*ufi,*vfr,*vfi;
- double *po2,*pod;
- double zo2, zod;
- double gmuq;
- for (lev = 0; lev < klev; lev++)
- {
- if (PolyDisk)
- {
- rewind(pol2f);
- rewind(polif);
- }
- po2 = pol2;
- pod = poli;
- for (jmm = 0; jmm <= nt; jmm++)
- {
- for (jfc = jmm; jfc <= nt; jfc++)
- {
- ufr = fu ;
- ufi = fu + nlat ;
- vfr = fv ;
- vfi = fv + nlat ;
- dir = 0.0 ;
- dii = 0.0 ;
- vor = 0.0 ;
- voi = 0.0 ;
- if (PolyDisk)
- {
- fread(po2=pol2,sizeof(double),Lats,pol2f);
- fread(pod=poli,sizeof(double),Lats,polif);
- }
- for (lat = 0; lat < nlat; lat++)
- {
- gmuq = 1.0 - Outlat->gmu[lat] * Outlat->gmu[lat];
- zod = *pod * 0.5 * jmm * Outlat->gwt[lat] / (PlanetRadius * gmuq);
- zo2 = *po2 * Outlat->gwt[lat] / gmuq;
- dir += *vfr * zo2 - *ufi * zod;
- dii += *vfi * zo2 + *ufr * zod;
- vor -= *ufr * zo2 + *vfi * zod;
- voi -= *ufi * zo2 - *vfr * zod;
- ufr++;
- ufi++;
- vfr++;
- vfi++;
- po2++;
- pod++;
- }
- *sd++ = dir;
- *sd++ = dii;
- *sv++ = vor;
- *sv++ = voi;
- }
- fu += 2 * nlat;
- fv += 2 * nlat;
- }
- }
- }
- void genind(int *Interpolation_Index, double lv[],
- double *Full_Level_Pressure, int DimGP, int OutLevs)
- {
- int h,k,l;
- int *nx;
- double Pressure,*pf;
- nx = Interpolation_Index;
- for (h=0 ; h < DimGP * OutLevs ; ++h) nx[h] = -1;
- for (k = 0; k<OutLevs; k++)
- {
- Pressure = lv[k];
- pf = Full_Level_Pressure;
- for (l = 0; l<SigLevs; l++)
- for (h = 0; h<DimGP ; h++)
- {
- if (Pressure > *pf) nx[h] = l;
- pf++;
- }
- nx += DimGP;
- }
- }
- void theta(double *PThetaF, double *PThetaH, double *PH, double *PS,
- double *TF, double *TS, int DimGP, int Dim3GP)
- {
- int h,l;
- double Kappa = RD / RCPD;
- double *ThetaH = PThetaH;
- double *ThetaF = PThetaF;
-
- for (h = 0; h < DimGP; h++) ThetaH[h] = 0.0;
- ThetaH += DimGP;
- for (l = 0; l < SigLevs - 1; l++)
- {
- for (h = 0; h < DimGP; h++)
- {
- ThetaH[h] = 0.5 * (TF[h] + TF[h+DimGP]) * pow((PS[h]/PH[h]),Kappa);
- }
- PH += DimGP;
- TF += DimGP;
- ThetaH += DimGP;
- }
- memcpy(ThetaH,TS,DimGP * sizeof(double));
- ThetaH = PThetaH;
- for (h = 0; h < Dim3GP; h++)
- {
- ThetaF[h] = 0.5 * (ThetaH[h] + ThetaH[h+DimGP]);
- }
- }
- void presh(double *pf, double *php, double *vct, double *ps)
- {
- int h,l;
- double zp,ze;
- double *ph = php;
- for (l = 0; l<SigLevs; l++)
- {
- zp = vct[l];
- ze = vct[l+SigLevs+1];
- for (h = 0; h<DimGP; h++) ph[h] = zp + ze * ps[h];
- ph += DimGP;
- }
- memcpy(ph,ps,DimGP * sizeof(double));
- ph = php;
- for (h = 0; h<Dim3GP; h++) pf[h] = 0.5 * (ph[h] + ph[h+DimGP]);
- }
- /*****************************/
- /* Compute relative humidity */
- /*****************************/
- double relhum(double q, double t, double p)
- {
- double rh;
- double gascon;
- double rv;
- double TMELT;
- double ra1;
- double ra2;
- double ra4;
- double rdbrv;
- double zqsat;
- rv = 461.51;
- TMELT = 273.16;
- gascon = 287.0 ;
- ra1 = 610.78;
- ra2 = 17.2693882;
- ra4 = 35.86;
- rdbrv = gascon / rv;
- zqsat = rdbrv * ra1 * exp(ra2 * (t-TMELT) / (t-ra4)) / p;
- zqsat *= 1.0 / (1.0 - (1.0 / rdbrv - 1.0) * zqsat);
- rh = q * 100.0 / zqsat;
- if (rh < 0.0) rh = 0.0;
- if (rh > 100.0) rh = 100.0;
- return rh;
- }
- /*****************************/
- /* Compute relative humidity */
- /*****************************/
- void sh2rh(double *sphum, double *rhum, double *t, int lev)
- {
- int jhor,jlev;
- double *pp; // pressure
- pp = &FullPress->hgp[0];
- for (jlev = 0; jlev < lev; jlev++)
- for (jhor = 0; jhor < DimGP; jhor++)
- *rhum++ = relhum(*sphum++,*t++,*pp++);
- }
- void dv2ps(double *div, double *pot, int lev)
- {
- for (int l = 0; l < lev ; l++)
- for (int m = 0; m <= Truncation; m++)
- for (int n = m; n <= Truncation; n++)
- {
- if (n)
- {
- *pot++ = *div++ * SQUARE_RADIUS / (n * n + n);
- *pot++ = *div++ * SQUARE_RADIUS / (n * n + n);
- }
- else
- {
- *pot++ = 0.0;
- *pot++ = 0.0;
- div += 2;
- }
- }
- }
- void MakeGeopotHeight(double *geop, double* gt, double *gq, double *ph, int nhor, int nlev)
- {
- int i;
- double VTMP = (RV / RD) - 1.0;
- double zrg = 1.0 / Grav;
- if (gq) /* Humidity is present */ {
- for (i = nhor * nlev - 1; i >= nhor; i--)
- geop[i] = geop[i+nhor] + RD * gt[i] * (1.0 + VTMP * gq[i])
- * log(ph[i+nhor] / ph[i]);
- for (i = 0; i < nhor; i++)
- geop[i] = geop[i+nhor] + RD * gt[i] * (1.0 + VTMP * gq[i])
- * 2.0 * log(2.0);
- }
- else /* No humidity */ {
- for (i = nhor * nlev - 1; i >= nhor; i--)
- geop[i] = geop[i+nhor] + RD * gt[i] * log(ph[i+nhor] / ph[i]);
- for (i = 0; i < nhor; i++)
- geop[i] = geop[i+nhor] + RD * gt[i] * 2.0 * log(2.0);
- }
- for (i = 0; i < nhor * (nlev+1); i++) geop[i] *= zrg;
- }
- void gp2fc_uv(void)
- {
- u_wind->SetPFour();
- v_wind->SetPFour();
- gp2fc(&u_wind->pgp[0],&u_wind->pfc[0],Lats,Lons,OutLevs,Fouriers);
- gp2fc(&v_wind->pgp[0],&v_wind->pfc[0],Lats,Lons,OutLevs,Fouriers);
- }
- void fc2sp_uv(void)
- {
- scaluv(&u_wind->pfc[0],CosPhi,Lats,Fouriers*OutLevs);
- scaluv(&v_wind->pfc[0],CosPhi,Lats,Fouriers*OutLevs);
- u_wind->SetPSpec();
- v_wind->SetPSpec();
- Divergence->SetPSpec();
- Vorticity->SetPSpec();
- fc2sp(&u_wind->pfc[0],&u_wind->psp[0],OutLevs,Lats,Truncation);
- fc2sp(&v_wind->pfc[0],&v_wind->psp[0],OutLevs,Lats,Truncation);
- uv2dv(&u_wind->pfc[0],&v_wind->pfc[0],
- &Divergence->psp[0],&Vorticity->psp[0],pol2,poli,OutLevs,Lats,Truncation);
- if (VeloPot->needed)
- {
- VeloPot->plev = OutLevs;
- VeloPot->SetPSpec();
- dv2ps(&Divergence->psp[0],&VeloPot->psp[0],OutLevs);
- }
- if (StreamF->needed)
- {
- StreamF->plev = OutLevs;
- StreamF->SetPSpec();
- dv2ps(&Vorticity->psp[0],&StreamF->psp[0],OutLevs);
- }
- }
- void sp2fc_uv(void)
- {
- for (int si = 0 ; si < 4 ; ++si)
- {
- int code = SpecialCodes[si];
- if (All[code].selected && All[code].psp.size())
- {
- All[code].SetPFour();
- sp2fci(&All[code].psp[0],&All[code].pfc[0],OutLevs);
- }
- }
- if (u_wind->selected && u_wind->pfc.size())
- scaluv(&u_wind->pfc[0],RevCosPhi,Lats,Fouriers*OutLevs);
- if (v_wind->selected && v_wind->pfc.size())
- scaluv(&v_wind->pfc[0],RevCosPhi,Lats,Fouriers*OutLevs);
- }
- void fc2gp_uv(void)
- {
- for (int si = 0 ; si < 4 ; ++si)
- {
- int code = SpecialCodes[si];
- if (All[code].selected && All[code].pfc.size())
- {
- All[code].SetPGrid();
- fc2gp(&All[code].pfc[0],&All[code].pgp[0],Lats,Lons,OutLevs,Fouriers);
- }
- }
- }
- void PumaProcess(void)
- {
- int code;
- MeanCount++; // Count term inside month
- TermCount++; // Count term
- #ifdef NETCDF_OUTPUT
- if (TermCount == 1 && NetCDF) NetVarDefine(); // Define NetCDF variables
- #endif
- if (MeanCount == 1) CheckContent(); // Everything OK ?
- if (TermCount > 60) Debug = 0; // Limit debug output
- // Reset level offset for all variables
- for (code = 0; code < CODES; code++) All[code].loff = 0;
- // Derive velocity potential and streamfunction from divergence and vorticity
- if (VeloPot->needed && !VeloPot->detected && VerType == 's')
- {
- VeloPot->SetHSpec(SigLevs,OutLevs,FALSE);
- dv2ps(&Divergence->hsp[0],&VeloPot->hsp[0],SigLevs);
- }
- if (StreamF->needed && !StreamF->detected && VerType == 's')
- {
- StreamF->SetHSpec(SigLevs,OutLevs,FALSE);
- dv2ps(&Vorticity->hsp[0],&StreamF->hsp[0],SigLevs);
- }
- // -------------------------
- // Output of spectral fields
- // -------------------------
- if (OutRep == HYB_SPEC)
- {
- HybSpec->Write_hspec();
- return;
- }
- // =====================================================
- // Transformation from spectral domain to fourier domain
- // =====================================================
- // Derive wind components u*cos(phi) and v*cos(phi)
- if ((u_wind->needed || v_wind->needed) &&
- (!u_wind->detected || !v_wind->detected))
- {
- u_wind->SetHFour(SigLevs,OutLevs,FALSE);
- v_wind->SetHFour(SigLevs,OutLevs,FALSE);
- spvfc(&Divergence->hsp[0],&Vorticity->hsp[0],
- &u_wind->hfc[0] ,&v_wind->hfc[0] ,
- Divergence->hlev ,Lats,Fouriers,Truncation);
- }
- // If divergence and vorticity were needed for u and v computation
- // only, they are now released
- Vorticity->needed = Vorticity->selected;
- Divergence->needed = Divergence->selected || Omega->needed;
- // Perform inverse Legendre transformation for all needed variables
- for (code = 0 ; code < CODES; code++)
- if (All[code].needed && All[code].hsp.size())
- {
- All[code].SetHFour(All[code].hlev,All[code].plev,All[code].twod);
- sp2fci(&All[code].hsp[0],&All[code].hfc[0],All[code].hlev);
- }
- // Compute d(Lnps)/dx and d(Lnps)/dy if needed
- if (dpsdx->needed || dpsdy->needed)
- {
- dpsdx->SetHFour(1,1,TRUE);
- dpsdy->SetHFour(1,1,TRUE);
- Deriva(&LnPs->hfc[0],&dpsdx->hfc[0]);
- sp2fcd(&LnPs->hsp[0],&dpsdy->hfc[0],1,Lats,Fouriers,Truncation);
- }
- /* ------------------------ */
- /* Output of fourier fields */
- /* ------------------------ */
- if (OutRep == HYB_FOUR)
- {
- HybFour->Write_hfour();
- return;
- }
- /* --------------------- */
- /* Output of zonal means */
- /* --------------------- */
- if (OutRep == HYB_ZONM)
- {
- HybSect->Write_hfour();
- return;
- }
- /* ============================ */
- /* Transformation to gridpoints */
- /* ============================ */
- if (SaveMemory) HybSpec->Clear_hspec();
- for (code = 0; code < CODES; code++)
- if (All[code].needed && All[code].hfc.size())
- {
- All[code].SetHGrid(All[code].hlev,All[code].plev,All[code].twod);
- fc2gp(&All[code].hfc[0],&All[code].hgp[0],Lats,Lons,All[code].hlev,Fouriers);
- }
- if (SaveMemory) HybSpec->Clear_hfour();
- if (Humidity->hgp.size()) // Remove spurious negative humidity
- {
- for (int i=0 ; i < Dim3GP ; ++i)
- if (Humidity->hgp[i] < 0.0) Humidity->hgp[i] = 0.0;
- }
- if (LnPs->hgp.size())
- {
- Ps->SetHGrid(1,1,TRUE);
- Ps->hgp = exp(LnPs->hgp);
- }
- LnPs->needed = LnPs->selected;
- if (Orography.size() != DimGP)
- {
- Orography.resize(DimGP);
- if (Geopotential->hgp.size()) Orography = Geopotential->hgp;
- else
- {
- if (Geopotential->selected || VerType == 'p')
- {
- CenterText("Orography not found - using zero orography");
- Orography = 0.0;
- }
- }
- }
- Geopotential->needed = Geopotential->selected;
- if (Geopotential->needed && !Geopotential->hgp.size())
- {
- Geopotential->SetHGrid(1,1,TRUE);
- Geopotential->hgp = Orography;
- }
- // This section is implemented for pressure level fields only
- if (VerType == 'p' || Omega->needed)
- {
- FullPress->SetHGrid(SigLevs ,OutLevs,FALSE);
- HalfPress->SetHGrid(SigLevs+1,OutLevs,FALSE);
- presh(&FullPress->hgp[0],&HalfPress->hgp[0],vct,&Ps->hgp[0]);
-
- if (ThetaF->needed)
- {
- ThetaF->SetHGrid(SigLevs,OutLevs,FALSE);
- ThetaH->SetHGrid(SigLevs,OutLevs,FALSE);
- theta(&ThetaF->hgp[0], &ThetaH->hgp[0], &HalfPress->hgp[0], &Ps->hgp[0],
- &Temperature->hgp[0], &Ts->hgp[0], DimGP, Dim3GP);
- }
-
- if (GeopotHeight->needed)
- {
- GeopotHeight->SetHGrid(SigLevs+1,OutLevs,FALSE);
- memcpy(&GeopotHeight->hgp[Dim3GP],&Orography[0],DimGP * sizeof(double));
- MakeGeopotHeight(&GeopotHeight->hgp[0],&Temperature->hgp[0],
- &Humidity->hgp[0],&HalfPress->hgp[0],DimGP,SigLevs);
- Humidity->needed = Humidity->selected;
- }
-
- if (dpsdx->needed) dpsdx->hgp *= Ps->hgp;
- if (dpsdy->needed) dpsdy->hgp *= Ps->hgp;
-
- if (Omega->needed)
- {
- Omega->SetHGrid(SigLevs+1,OutLevs,FALSE);
- OMEGA();
- dpsdx->needed = dpsdx->selected;
- dpsdy->needed = dpsdy->selected;
- }
-
- if (w_wind->needed)
- {
- w_wind->SetHGrid(SigLevs,OutLevs,FALSE);
- Omega_w(&w_wind->hgp[0],&Omega->hgp[0],&Temperature->hgp[0],&FullPress->hgp[0]);
- }
-
- if (Rhumidity->needed)
- {
- Rhumidity->SetHGrid(SigLevs,OutLevs,FALSE);
- sh2rh(&Humidity->hgp[0],&Rhumidity->hgp[0],
- &Temperature->hgp[0],SigLevs);
-
- Temperature->needed = Temperature->selected;
- Humidity->needed = Humidity->selected;
- }
-
- if (SLP->needed)
- {
- SLP->SetHGrid(1,1,TRUE);
- Extrap(&SLP->hgp[0],&HalfPress->hgp[0] + Dim3GP,
- &FullPress->hgp[0] + Dim3GP - DimGP , &Orography[0],
- &Temperature->hgp[0] + Dim3GP - DimGP , DimGP);
- Temperature->needed = Temperature->selected || GeopotHeight->selected;
- }
- } // endif (VerType == 'p')
- if (speed->needed)
- {
- speed->SetHGrid(SigLevs,OutLevs,FALSE);
- Speed(&speed->hgp[0],&u_wind->hgp[0],&v_wind->hgp[0]);
- }
-
- if (precip->needed)
- {
- precip->SetHGrid(1,1,TRUE);
- precip->hgp = All[142].hgp + All[143].hgp;
- }
- if (net_top->needed)
- {
- net_top->SetHGrid(1,1,TRUE);
- net_top->hgp = All[178].hgp + All[179].hgp;
- }
- if (net_bot->needed)
- {
- net_bot->SetHGrid(1,1,TRUE);
- net_bot->hgp = All[176].hgp + All[177].hgp;
- }
- if (net_heat->needed)
- {
- net_heat->SetHGrid(1,1,TRUE);
- net_heat->hgp = All[218].hgp * L_times_rhoH2O
- + All[176].hgp + All[177].hgp + All[146].hgp + All[147].hgp;
- }
- if (net_water->needed)
- {
- net_water->SetHGrid(1,1,TRUE);
- net_water->hgp = All[182].hgp - All[160].hgp + All[142].hgp + All[143].hgp;
- }
- if (sw_atm->needed)
- {
- sw_atm->SetHGrid(1,1,TRUE);
- sw_atm->hgp = All[178].hgp - All[176].hgp;
- }
- if (lw_atm->needed)
- {
- lw_atm->SetHGrid(1,1,TRUE);
- lw_atm->hgp = All[179].hgp - All[177].hgp;
- }
- if (net_atm->needed)
- {
- net_atm->SetHGrid(1,1,TRUE);
- net_atm->hgp = All[178].hgp + All[179].hgp - All[176].hgp - All[177].hgp;
- }
- if (surf_runoff->needed)
- {
- surf_runoff->SetHGrid(1,1,TRUE);
- surf_runoff->hgp = All[182].hgp - All[221].hgp + All[142].hgp + All[143].hgp;
- }
- if (fresh_water->needed)
- {
- fresh_water->SetHGrid(1,1,TRUE);
- fresh_water->hgp = All[142].hgp + All[143].hgp + All[182].hgp;
- }
- // =============================
- // Monthly means on hybrid grids
- // =============================
- if (Mean && OutRep == HYB_GRID)
- for (code = 0; code < CODES; code++)
- if (All[code].selected && All[code].hgp.size())
- {
- if (MeanCount == 1)
- {
- All[code].mgp.resize(All[code].hgp.size());
- All[code].mgp = All[code].hgp;
- All[code].hgp.resize(0);
- }
- else All[code].mgp += All[code].hgp;
- if (EndOfMonth)
- {
- double rmc = 1.0 / MeanCount;
- All[code].hgp = All[code].mgp * rmc;
- All[code].mgp.resize(0);
- }
- }
- // ----------------------------
- // Output of hybrid level grids
- // ----------------------------
- if (OutRep == HYB_GRID)
- {
- if (!Mean || EndOfMonth) HybGrid->Write_hgrid();
- if (SaveMemory) HybGrid->Clear_hgrid();
- return;
- }
- // ======================================
- // Vertical interpolation / extrapolation
- // ======================================
- if (vert_index == NULL) vert_index = new int[OutLevs*DimGP];
- genind(vert_index,level,&FullPress->hgp[0],DimGP,OutLevs);
- for (code = 0; code < CODES; code++)
- if (All[code].needed && All[code].hgp.size())
- {
- All[code].SetPGrid();
- if (!All[code].twod)
- {
- if (code == ZCODE) Interpolate_Z();
- else Interpolate_T(code);
- }
- }
- Temperature->needed = Temperature->selected;
- if (SaveMemory) HybGrid->Clear_hgrid();
- // ===========================
- // Computation of Montly Means
- // ===========================
- if (Mean)
- for (code = 0; code < CODES; code++)
- if (All[code].needed && All[code].pgp.size())
- {
- if (MeanCount == 1)
- {
- All[code].mgp.resize(All[code].pgp.size());
- All[code].mgp = All[code].pgp;
- All[code].pgp.resize(0);
- }
- else All[code].mgp += All[code].pgp;
- if (EndOfMonth)
- {
- double rmc = 1.0 / MeanCount;
- All[code].pgp = All[code].mgp * rmc;
- All[code].mgp.resize(0);
- }
- }
- if (Mean && !EndOfMonth)
- {
- if (SaveMemory) HybGrid->Clear_pgrid();
- return;
- }
- // ------------------------------
- // Output of pressure level grids
- // ------------------------------
- if (OutRep == PRE_GRID)
- {
- if (SpecialUV)
- {
- gp2fc_uv();
- fc2sp_uv();
- sp2fc_uv();
- fc2gp_uv();
- }
- HybGrid->Write_pgrid();
- if (SaveMemory) HybGrid->Clear_pgrid();
- return;
- }
- // ===============================
- // Transformation to fourier space
- // ===============================
- for (code = 0; code < CODES; code++)
- if (All[code].needed && All[code].pgp.size())
- {
- if (!All[code].pfc.size()) All[code].SetPFour();
- gp2fc(&All[code].pgp[0],&All[code].pfc[0],
- Lats,Lons,All[code].plev,Fouriers);
- }
- if (SaveMemory) HybGrid->Clear_pgrid();
- // ---------------------------------------
- // Output of fourier fields or zonal means
- // ---------------------------------------
- if (OutRep == PRE_FOUR || OutRep == PRE_ZONM)
- {
- if (SpecialUV)
- {
- fc2sp_uv();
- sp2fc_uv();
- }
- if (OutRep == PRE_FOUR) HybFour->Write_pfour();
- else HybSect->Write_pfour();
- if (SaveMemory) HybFour->Clear_pfour();
- return;
- }
- // ================================
- // Transformation to spectral space
- // ================================
- if (!SpecialUV && u_wind->pfc.size() && v_wind->pfc.size())
- {
- scaluv(&u_wind->pfc[0],CosPhi,Lats,Fouriers*OutLevs);
- scaluv(&v_wind->pfc[0],CosPhi,Lats,Fouriers*OutLevs);
- }
- for (code = 0; code < CODES; code++)
- if (All[code].needed && All[code].pfc.size() && !All[code].psp.size())
- {
- All[code].SetPSpec();
- fc2sp(&All[code].pfc[0],&All[code].psp[0],All[code].plev,Lats,Truncation);
- }
- if (SpecialUV) fc2sp_uv();
- if (SaveMemory) HybFour->Clear_pfour();
- // -------------------------
- // Output of spectral fields
- // -------------------------
- if (OutRep == PRE_SPEC)
- {
- HybSpec->Write_pspec();
- if (SaveMemory) HybSpec->Clear_pspec();
- return;
- }
- }
- void PostProcess(void)
- {
- int l;
- char tb[COLS+2];
- if (EndOfMonth)
- {
- sprintf(tb,"Processed Month %2d Year %4d", OldMonth,OldDate.tm_year);
- l = strlen(tb);
- if (MeanCount > 1)
- {
- if (Mean) sprintf(tb+l," (Mean of %3d Terms)",MeanCount);
- else sprintf(tb+l," Terms %3d",MeanCount);
- }
- LeftText(tb);
- EndOfMonth = FALSE;
- MeanCount = 0;
- MonthCount++ ;
- }
- }
- /* ================= */
- /* switch input file */
- /* ================= */
- void SwitchFile(void)
- {
- int l,YY,MM;
- fclose(fpi);
- l = strlen(ifile);
- if (l > 4 && ifile[l-4] == '.' && atoi(ifile+l-3) != 0) // .YYY
- {
- YY = atoi(ifile+l-3) + 1;
- sprintf(ifile+l-3,"%03d",YY);
- }
- else if (l > 5 && ifile[l-5] == '_' && atoi(ifile+l-4) != 0) // _YYYY
- {
- YY = atoi(ifile+l-4) + 1;
- sprintf(ifile+l-4,"%04d",YY);
- }
- else if (l > 7 && ifile[l-7] == '_' && atoi(ifile+l-6) != 0) // _YYYYMM
- {
- MM = atoi(ifile+l-2);
- YY = atoi(ifile+l-6);
- if (MM == 12) YY += 88;
- if (YY > 1) sprintf(ifile+l-6,"%06d",++YY);
- }
- else if (l > 5 && atoi(ifile+l-5) != 0) // "YYYMM" at end
- {
- MM = atoi(ifile+l-2);
- YY = atoi(ifile+l-5);
- if (MM == 12) YY += 88;
- if (YY > 1) sprintf(ifile+l-5,"%05d",++YY);
- }
- else if (l > 4 && atoi(ifile+l-4) != 0) // "YYMM" at end
- {
- MM = atoi(ifile+l-2);
- YY = atoi(ifile+l-4);
- if (MM == 12) YY += 88;
- if (YY > 1) sprintf(ifile+l-4,"%04d",++YY);
- }
- Multi--;
- printf("Continuation File: %s\n",ifile);
- fpi = fopen(ifile,"rb");
- }
- /* ====================================== */
- /* Interpolate gauss grid to regular grid */
- /* ====================================== */
- void Regauss(double *r, double *g, double *Ghi)
- {
- int j,jlon,jlat;
- double np,sp,fn,fs,fe,fw;
- double rphi,rlam,gdx,rdx;
- double *Gam;
- Gam = new double[Gons];
- gdx = 360.0 / Gons;
- rdx = 360.0 / Lons;
- np = sp = 0.0;
- for (jlon = 0 ; jlon < Gons ; ++jlon)
- {
- np += g[jlon];
- sp += g[jlon + DimGG - Gons];
- }
- np /= Gons;
- sp /= Gons;
- for (jlat = 0 ; jlat < Lats ; ++jlat)
- {
- rphi = Outlat->Phi[jlat];
- if (rphi > Ghi[0]) // far north
- {
- fn = (rphi - Ghi[0]) / (90.0 - Ghi[0]);
- fs = 1.0 - fn;
- for (jlon = 0 ; jlon < Gons ; ++jlon)
- Gam[jlon] = fn * np + fs * g[jlon];
- }
- else if (rphi < Ghi[Gats-1]) // far south
- {
- fs = (Ghi[Gats-1] - rphi) / (Ghi[Gats-1] + 90.0);
- fn = 1.0 - fs;
- for (jlon = 0 ; jlon < Gons ; ++jlon)
- Gam[jlon] = fn * g[jlon + DimGG - Gons] + fs * sp;
- }
- else // inside
- {
- j = 0; // search neighboured gauss latitudes
- while (j < Gats-1 && rphi < Ghi[j]) ++j;
- fn = (rphi - Ghi[j]) / (Ghi[j-1] - Ghi[j]);
- fs = 1.0 - fn;
- for (jlon = 0 ; jlon < Gons ; ++jlon)
- Gam[jlon] = fn * g[jlon+(j-1)*Gons] + fs * g[jlon+j*Gons];
- }
- for (jlon = 0 ; jlon < Lons ; ++jlon)
- {
- rlam = jlon * rdx;
- j = (int)floor(rlam / gdx);
- fe = (rlam - j * gdx) / gdx;
- fw = 1.0 - fe;
- if (j >= Gons-1) r[jlon + jlat * Lons] = fw * Gam[j] + fe * Gam[0];
- else r[jlon + jlat * Lons] = fw * Gam[j] + fe * Gam[j+1];
- }
- }
- delete Gam;
- }
- /*******************/
- /* SetOutputHeader */
- /*******************/
- void SetOutputHeader(void)
- {
- int MM,DD,HH;
- if (DPM > 99) // Workaround for months with more than 99 days
- {
- MM = (TermCount / DPM) % 12 + 1;
- HeadOu[2] = OldDate.tm_year * 10000 + MM * 100;
- HeadOu[3] = 0;
- if (!Mean) // Add day & hour info
- {
- HeadOu[2] += (TermCount % DPM) / DayDivisor + 1;
- HeadOu[3] = 100 * (24 / DayDivisor) * ((TermCount % DPM) % DayDivisor);
- }
- }
- else
- {
- HeadOu[2] = OldDate.tm_year * 10000 + OldDate.tm_mon * 100;
- HeadOu[3] = 0;
- if (!Mean)
- {
- HeadOu[2] += OldDate.tm_mday;
- HeadOu[3] = OldDate.tm_hour * 100 + OldDate.tm_min;
- }
- }
- }
- /*****************/
- /* Puma Control */
- /*****************/
- void PumaControl(void)
- {
- int i;
- int LevelOffset;
- int Eof;
- char tb[COLS+2];
- struct tm D1;
- struct tm D2;
- while (1)
- {
- Eof = ReadHeaderRecord();
- if (Eof && Multi)
- {
- SwitchFile();
- if (fpi) Eof = ReadHeaderRecord();
- }
- if (DataStep < 0.01) // Compute time interval
- {
- if (HeadIn[2] != HeadSt[2] || HeadIn[3] != HeadSt[3])
- {
- HeadToDate(HeadSt,&D1);
- HeadToDate(HeadIn,&D2);
- DeltaDy = D2.tm_mday - D1.tm_mday;
- DeltaHr = D2.tm_hour - D1.tm_hour;
- DeltaMn = D2.tm_min - D1.tm_min ;
- if (DeltaDy < 0) DeltaDy = 1; // month changed after 1.st term
- DataStep = DeltaDy + DeltaHr / 24.0 + DeltaMn / 1440.0;
- }
- }
- if ((HeadIn[2] / 100 % 100) > LastMonth && DayDivisor == 0) // Ignore rest of file
- {
- Eof = 1;
- if (Multi)
- {
- SwitchFile();
- if (fpi) Eof = ReadHeaderRecord();
- }
- }
- if (Eof) // Process last read term and finish
- {
- EndOfMonth = TRUE;
- SetOutputHeader();
- PumaProcess();
- PostProcess();
- Dependencies();
- return;
- }
- DecodePumaHeader();
- if (NewMonth < FirstMonth) /* Skip months before FirstMonth */
- {
- SkipPumaArray();
- if (Debug)
- {
- if (RepGrib == REP_SPECTRAL) sprintf(tb,"T%04d",Truncation);
- else sprintf(tb,"N%04d",Lons);
- sprintf(tb+5," SKIPPED Code %3d Level%6d %2.2d.%2.2d.%2.2d %2.2d:%2.2d",
- PumaCode,PumaLevel,NewDate.tm_mday,NewDate.tm_mon,NewDate.tm_year,
- NewDate.tm_hour,NewDate.tm_min);
- LeftText(tb);
- }
- continue;
- }
- if (Debug)
- {
- if (RepGrib == REP_SPECTRAL) sprintf(tb,"T%04d",Truncation);
- else sprintf(tb,"N%04d",Lons);
- sprintf(tb+5," Code %3d Level%6d %2.2d.%2.2d.%2.2d %2.2d:%2.2d",
- PumaCode,PumaLevel,NewDate.tm_mday,NewDate.tm_mon,NewDate.tm_year,
- NewDate.tm_hour,NewDate.tm_min);
- LeftText(tb);
- }
- if (OldMonth > 0)
- {
- EndOfMonth = NewMonth != OldMonth;
- EndOfTerm = memcmp(&NewDate,&OldDate,sizeof(struct tm));
- if (EndOfTerm && MeanCount == DPM-1) EndOfMonth = 1;
- if (EndOfTerm)
- {
- SetOutputHeader();
- PumaProcess();
- PostProcess();
- Dependencies();
- }
- }
- OldDate = NewDate;
- OldMonth = NewMonth;
- if (All[PumaCode].needed)
- {
- if (RepGrib == REP_SPECTRAL) // Spectral array
- {
- if (PumaLevel) All[PumaCode].SetHSpec(SigLevs,OutLevs,FALSE);
- else All[PumaCode].SetHSpec( 1, 1,TRUE );
- if (VerType != 's' || mom[PumaLevel])
- {
- ReadPumaArray(&All[PumaCode].hsp[0]+All[PumaCode].loff);
- All[PumaCode].loff += DimSP;
- }
- else SkipPumaArray();
- }
- else // Gridpoint array
- {
- if (PumaLevel) All[PumaCode].SetHGrid(SigLevs,OutLevs,FALSE);
- else All[PumaCode].SetHGrid( 1, 1,TRUE );
- if (VerType != 's' || mom[PumaLevel])
- {
- if (DimGP == DimGG)
- ReadPumaArray(&All[PumaCode].hgp[0]+All[PumaCode].loff);
- else
- {
- double *ArrayBuffer;
- ArrayBuffer = new double[DimGG];
- ReadPumaArray(ArrayBuffer);
- Regauss(&All[PumaCode].hgp[0]+All[PumaCode].loff,ArrayBuffer,Gaulat->Phi);
- delete ArrayBuffer;
- }
- All[PumaCode].loff += DimGP;
- }
- else SkipPumaArray();
- }
- }
- else SkipPumaArray();
- }
- }
- char *amatch(char *msr, const char *sub)
- {
- int i,nm,ns;
- nm = strlen(msr);
- ns = strlen(sub);
- for (i = 0; i < nm-ns; i++)
- if (strncmp(msr+i,sub,ns) == 0) return (msr+i+ns);
- return NULL;
- }
- int scanpar(const char *name, int def)
- {
- char *cp;
- int value;
- char tb[COLS+2];
- cp = amatch(namelist,name);
- if (cp == NULL)
- {
- value = def;
- sprintf(tb,"%10.10s = %8d (default)",name,value);
- }
- else
- {
- value = atoi(cp);
- sprintf(tb,"%10.10s = %8d ",name,value);
- }
- LeftText(tb);
- return value;
- }
-
- double scanreal(const char *name, double def)
- {
- char *cp;
- double value;
- char tb[COLS+2];
- cp = amatch(namelist,name);
- if (cp == NULL)
- {
- value = def;
- sprintf(tb,"%10.10s = %8.3f (default)",name,value);
- }
- else
- {
- value = strtod(cp,NULL);
- sprintf(tb,"%10.10s = %8.3f ",name,value);
- }
- LeftText(tb);
- return value;
- }
-
- char scantex(const char *name, const char choice[])
- {
- char *cp;
- char value;
- int i;
- char tb[COLS+2];
- value = choice[0];
- cp = amatch(namelist,name);
- if (cp)
- {
- while (isspace(*cp)) ++cp;
- for (i=1 ; i < strlen(choice) ; ++i)
- {
- if (*cp == choice[i]) value = *cp;
- }
- }
- sprintf(tb,"%10.10s = %c ",name,value);
- LeftText(tb);
- return value;
- }
-
- void scantime(void)
- {
- char *cp,*icp;
- int time,i;
- char tb[512];
- nrqh = 0;
- cp = amatch(namelist,"timesel");
- if (cp == NULL)
- {
- hours[nrqh++] = -1;
- sprintf(tb,"%10.10s = all ","timesel");
- LeftText(tb);
- return;
- }
- time = strtol(cp,&icp,10);
- while ((char *)icp != (char *)cp && nrqh < MAX_HOURS) {
- hours[nrqh++] = time;
- cp = icp;
- time = strtol(cp,&icp,10);
- }
- sprintf(tb,"%10.10s = ","timesel");
- for (time = 0 ; time < nrqh ; ++time)
- {
- i = strlen(tb);
- sprintf(tb+i," %02d",hours[time]);
- }
- LeftText(tb);
- }
- void PrintCodes(void)
- {
- int code;
- char tb[COLS+2];
- DashLine();
- CenterText("Code Id Name Units ");
- DashLine();
- for (code=0 ; code < MAXCODES ; ++code) if (strncmp(All[code].Na,"Code",4))
- {
- sprintf(tb,"%4d %-8.8s %-32.32s %-16.16s",code,All[code].Id,All[code].Na,All[code].Un);
- CenterText(tb);
- }
- }
- int CodeOrName(char *a, char **b)
- {
- int l,code;
- while (*a == ' ') ++a;
- if (*a == '+' || *a == '-' || (*a >= '0' && *a <='9'))
- return strtol(a,b,10);
- for (code = 0 ; code < CODES ; ++code)
- {
- l = strlen(All[code].Id);
- if (!strncmp(All[code].Id,a,l) && *(a+l) == ' ')
- {
- *b = a+l;
- return code;
- }
- }
- return 0;
- }
-
- void scancode(void)
- {
- char *cp,*icp;
- int code;
- char tb[COLS+2];
- cp = amatch(namelist,"code");
- if (cp == NULL) Abort(" *** No code selected for output ***");
- code = CodeOrName(cp,&icp);
- DashLine();
- while (code > 0 && code < CODES)
- {
- sprintf(tb,"Code %5d = %-6.6s %-24.24s",code,All[code].Id,All[code].Na);
- LeftText(tb);
- All[code].selected = 1;
- cp = icp;
- code = CodeOrName(cp,&icp);
- }
- }
- void scanmol(void)
- {
- char *cp,*icp;
- int lev;
- nrml = 0;
- cp = amatch(namelist,"modlev");
- if (cp == NULL) return;
- lev = strtol(cp,&icp,10);
- while (lev > 0 && nrml < MAX_LEVELS)
- {
- mol[nrml++] = lev;
- mom[lev] = 1;
- cp = icp;
- lev = strtol(cp,&icp,10);
- }
- }
- void scanhPa(void)
- {
- char *cp,*icp;
- double lev;
- nrpl = 0;
- cp = amatch(namelist,"hpa");
- if (!cp) return;
- lev = strtod(cp,&icp);
- while (lev > 0 && nrpl < MAX_LEVELS)
- {
- hPa[nrpl++] = lev;
- cp = icp;
- lev = strtod(cp,&icp);
- }
- }
- void scanattributes(void)
- {
- char *cp;
- int i;
- nattr = 0;
- cp = amatch(namelist,"attributes");
- if (!cp) return;
- while (nattr < ATTR_MAX)
- {
- i = 0;
- while (*cp == ':' || isspace(*cp)) ++cp;
- while ((isalnum(*cp) || *cp == '_') && i < 80) AttrNam[nattr][i++] = *cp++;
- while (isspace(*cp)) ++cp;
- if (*cp != '=') break;
- else ++cp;
- while (isspace(*cp)) ++cp;
- if (*cp != '"') break;
- else ++cp;
- i = 0;
- while (*cp != '"' && i < 80) AttrVal[nattr][i++] = *cp++;
- ++cp;
- while (isspace(*cp)) ++cp;
- if (*cp != ';') break;
- ++cp;
- ++nattr;
- }
- }
- void InitAll(void)
- {
- char Id[MAX_ID_LEN];
- char Na[MAX_NA_LEN];
-
- for (int code = 0 ; code < MAXCODES ; ++code)
- {
- sprintf(Id,"var%3.3d",code);
- sprintf(Na,"Code[%d]",code);
- All[code].Init(Id,Na,"1",0);
- All[code].code = code;
- }
- All[110].Init("mld" ,"mixed_layer_depth" ,"m" ,1); // Not standard
- All[129].Init("sg" ,"surface_geopotential" ,"m2 s-2" ,1);
- All[130].Init("ta" ,"air_temperature" ,"K" ,0);
- All[131].Init("ua" ,"eastward_wind" ,"m s-1" ,0);
- All[132].Init("va" ,"northward_wind" ,"m s-1" ,0);
- All[133].Init("hus" ,"specific_humidity" ,"1" ,0);
- All[134].Init("ps" ,"surface_air_pressure" ,"hPa" ,1);
- All[135].Init("wap" ,"vertical_air_velocity" ,"Pa s-1" ,0); // shortened
- All[137].Init("wa" ,"upward_wind" ,"m s-1" ,0); // Not standard
- All[138].Init("zeta" ,"atm_relative_vorticity" ,"s-1" ,0);
- All[139].Init("ts" ,"surface_temperature" ,"K" ,1);
- All[140].Init("mrso" ,"lwe_of_soil_moisture_content" ,"m" ,1); // shortened
- All[141].Init("snd" ,"surface_snow_thickness" ,"m" ,1);
- All[142].Init("prl" ,"lwe_of_large_scale_precipitation","m s-1" ,1); // rate !!
- All[143].Init("prc" ,"convective_precipitation_rate" ,"m s-1" ,1);
- All[144].Init("prsn" ,"lwe_of_snowfall_amount" ,"m s-1" ,1); // rate !!
- All[145].Init("bld" ,"dissipation_in_atmosphere_bl" ,"W m-2" ,1); // shortened
- All[146].Init("hfss" ,"surface_sensible_heat_flux" ,"W m-2" ,1); // shortened
- All[147].Init("hfls" ,"surface_latent_heat_flux" ,"W m-2" ,1); // shortened
- All[148].Init("stf" ,"streamfunction" ,"m2 s-2" ,0); // Not standard
- All[149].Init("psi" ,"velocity_potential" ,"m2 s-2" ,0); // Not standard
- All[151].Init("psl" ,"air_pressure_at_sea_level" ,"hPa" ,1);
- All[152].Init("pl" ,"log_surface_pressure" ,"1" ,1);
- All[155].Init("d" ,"divergence_of_wind" ,"s-1" ,0);
- All[156].Init("zg" ,"geopotential_height" ,"m" ,0);
- All[157].Init("hur" ,"relative_humidity" ,"1" ,0);
- All[158].Init("tps" ,"tendency_of_surface_air_pressure","Pa s-1" ,1);
- All[159].Init("u3" ,"ustar" ,"m3 s-3" ,1); // Not standard
- All[160].Init("mrro" ,"surface_runoff" ,"m s-1" ,1); // Not standard
- All[161].Init("clw" ,"liquid_water_content" ,"1" ,0); // Not standard
- All[162].Init("cl" ,"cloud_area_fraction_in_layer" ,"1" ,0); // Not standard
- All[163].Init("tcc" ,"total_cloud_cover" ,"1" ,1); // Not standard
- All[164].Init("clt" ,"cloud_area_fraction" ,"1" ,1);
- All[165].Init("uas" ,"eastward_wind_10m" ,"m s-1" ,1); // shortened
- All[166].Init("vas" ,"northward_wind_10m" ,"m s-1" ,1); // shortened
- All[167].Init("tas" ,"air_temperature_2m" ,"K" ,1); // shortened
- All[168].Init("td2m" ,"dew_point_temperature_2m" ,"K" ,1); // shortened
- All[169].Init("tsa" ,"surface_temperature_accumulated" ,"K" ,1); // Not standard
- All[170].Init("tsod" ,"deep_soil_temperature" ,"K" ,1);
- All[171].Init("dsw" ,"deep_soil_wetness" ,"1" ,1);
- All[172].Init("lsm" ,"land_binary_mask" ,"1" ,1);
- All[173].Init("z0" ,"surface_roughness_length" ,"m" ,1);
- All[174].Init("alb" ,"surface_albedo" ,"1" ,1); // Not standard
- All[175].Init("as" ,"surface_albedo" ,"1" ,1); // Not standard
- All[176].Init("rss" ,"surface_net_shortwave_flux" ,"W m-2" ,1); // shortened
- All[177].Init("rls" ,"surface_net_longwave_flux" ,"W m-2" ,1); // shortened
- All[178].Init("rst" ,"toa_net_shortwave_flux" ,"W m-2" ,1); // shortened
- All[179].Init("rlut" ,"toa_net_longwave_flux" ,"W m-2" ,1); // shortened
- All[180].Init("tauu" ,"surface_eastward_stress" ,"Pa" ,1); // shortened
- All[181].Init("tauv" ,"surface_northward_stress" ,"Pa" ,1); // shortened
- All[182].Init("evap" ,"lwe_of_water_evaporation" ,"m s-1" ,1); // rate !!
- All[183].Init("tso" ,"climate_deep_soil_temperature" ,"K" ,1); // Not standard
- All[184].Init("wsoi" ,"climate_deep_soil_wetness" ,"1" ,1);
- All[199].Init("vegc" ,"vegetation_cover" ,"1" ,1); // Not standard
- All[203].Init("rsut" ,"toa_outgoing_shortwave_flux" ,"W m-2" ,1); // Not standard
- All[204].Init("ssru" ,"surface_solar_radiation_upward" ,"W m-2" ,1); // Not standard
- All[205].Init("stru" ,"surface_thermal_radiation_upward","W m-2" ,1); // Not standard
- All[207].Init("tso2" ,"soil_temperature_level_2" ,"K" ,1); // Not standard
- All[208].Init("tso3" ,"soil_temperature_level_3" ,"K" ,1); // Not standard
- All[209].Init("tso4" ,"soil_temperature_level_4" ,"K" ,1); // Not standard
- All[210].Init("sic" ,"sea_ice_cover" ,"1" ,1); // Not standard
- All[211].Init("sit" ,"sea_ice_thickness" ,"m" ,1); // Not standard
- All[212].Init("vegf" ,"forest_cover" ,"1" ,1); // Not standard
- All[218].Init("snm" ,"snow_melt" ,"m s-1" ,1); // Not standard
- All[221].Init("sndc" ,"snow_depth_change" ,"m s-1" ,1); // Not standard
- All[230].Init("prw" ,"atmosphere_water_vapor_content" ,"kg m-2" ,1); // Not standard
- All[232].Init("glac" ,"glacier_cover" ,"1" ,1); // Not standard
- All[238].Init("tsn" ,"snow_temperature" ,"K" ,1);
- All[259].Init("spd" ,"wind_speed" ,"m s-1" ,0); // Not standard
- All[260].Init("pr" ,"total_precipitation" ,"m s-1" ,1); // Not standard
- All[261].Init("ntr" ,"net_top_radiation" ,"W m-2" ,1); // Not standard
- All[262].Init("nbr" ,"net_bottom_radiation" ,"W m-2" ,1); // Not standard
- All[263].Init("hfns" ,"surface_downward_heat_flux" ,"W m-2" ,1); // shortened
- All[264].Init("wfn" ,"net_water_flux" ,"m s-1" ,1); // Not standard
- All[273].Init("dpdx" ,"d(ps)/dx" ,"Pa m-1" ,1); // Not standard
- All[274].Init("dpdy" ,"d(ps)/dy" ,"Pa m-1" ,1); // Not standard
- All[277].Init("hlpr" ,"half_level_pressure" ,"Pa" ,0); // Not standard
- All[278].Init("flpr" ,"full_level_pressure" ,"Pa" ,0); // Not standard
- }
- void Usage(void)
- {
- char Line[132];
- fpi = fopen("/usr/local/doc/burn7.txt","r");
- if (fpi)
- do
- {
- fgets(Line,130,fpi);
- printf("%s",Line);
- }
- while (!feof(fpi) && Line[0] != '#');
- if (fpi) fclose(fpi);
- printf("\nburn7 [options] InputFile OutputFile <namelist >printout\n");
- printf(" option -h : help (this output)\n");
- printf(" option -c : print available codes and names\n");
- printf(" option -d : debug mode (verbose output)\n");
- printf(" option -m : Mean=1 output (override namelist option)\n");
- printf(" option -n : NetCDF output (override namelist option)\n");
- printf(" option -s : Save memory (increases CPU time)\n");
- printf(" InputFile : PUMA or PlaSim data file\n");
- #ifdef NETCDF_OUTPUT
- printf(" <OutputFile> : SERVICE, or NetCDF format file\n");
- #else
- printf(" <OutputFile> : SERVICE format file\n");
- #endif
- printf(" namelist is read from <stdin>\n");
- printf(" printout is written to <stdout>\n\n");
- exit(1);
- }
- void parini(void)
- {
- char c;
- unsigned int i;
- int jind;
- int lc;
- char tb[COLS+2];
- i = 1;
- namelist[0] = ' ';
- lc = 1;
- c = getchar();
- while (!feof(stdin) && i < MAX_NL)
- {
- if (c == ':' ) lc = 0; // No conversion to lower case
- if (c == '\n') lc = 1;
- if (c == '#') // Skip comment
- {
- while (!feof(stdin) && c != '\n') c = getchar();
- }
- if (lc)
- {
- if ((c >= '0' && c <= '9') ||
- c == '-' || c == '.') namelist[i++] = c;
- else if (c >= 'a' && c <= 'z') namelist[i++] = c;
- else if (c >= 'A' && c <= 'Z') namelist[i++] = tolower(c);
- else c = ' ';
- if (c == ' ' && namelist[i-1] != ' ') namelist[i++] = c;
- }
- else namelist[i++] = c;
- c = getchar();
- }
- namelist[i++] = ' ';
- namelist[i] = 0;
- if (Debug)
- {
- sprintf(tb,"Length of namelist: %d bytes",(int)strlen(namelist));
- LeftText(tb);
- for (i = 0; i<strlen(namelist); i+=40)
- {
- sprintf(tb,"namelist[%02d]=%-40.40s",i,namelist+i);
- LeftText(tb);
- }
- StarLine();
- }
- Lats = scanpar("lats",Lats);
- Lons = scanpar("lons",Lons);
- DPM = scanpar("dpm",0);
- if (DPM > 99 && DPM < 2400) /* Days Per Month */
- {
- DayDivisor = DPM / 100 + 1;
- while (24 % DayDivisor && DayDivisor < 24) ++DayDivisor;
- sprintf(tb,"%10.10s = %8d ","daydivisor",DayDivisor);
- LeftText(tb);
- }
- DPY = scanpar("dpy",0);
- if (DPY > 0) DaysPerYear = DPY;
- Cyclical = scanpar("cyclical",Cyclical);
- if (Cyclical) Cyclical = 1;
- if (VerType == 0 || HorType == 0)
- {
- VerType = scantex("vtype" ,"ps"); // 1. char is default value (p)
- HorType = scantex("htype" ,"gsfz"); // 1. char is default value (g)
- }
- Multi = scanpar("multi" ,0);
- LevelFactor = scanreal("levelfactor",1.0);
- if (NetCDF == 0) NetCDF = scanpar("netcdf",0);
- HeadOu[6] = scanpar("head7",0);
- mars = scanpar("mars" ,0);
- FirstMonth = scanpar("first",1);
- LastMonth = scanpar("last",12);
- PlanetRadius = scanreal("radius",EARTH_RADIUS);
- Grav = scanreal("gravity",EARTH_GRAV);
- SigmaTop = scanreal("sigmatop",0.0);
- vct[SigLevs] = SigmaTop;
- if (FirstMonth < 1) FirstMonth = 1;
- if (LastMonth > 12) LastMonth = 12;
- if (LastMonth < FirstMonth) LastMonth = FirstMonth;
- if (VerType == 's')
- {
- switch (HorType)
- {
- case 's': OutRep = HYB_SPEC; break;
- case 'f': OutRep = HYB_FOUR; break;
- case 'z': OutRep = HYB_ZONM; break;
- case 'g': OutRep = HYB_GRID; break;
- }
- }
- if (VerType == 'p')
- {
- switch (HorType)
- {
- case 's': OutRep = PRE_SPEC; break;
- case 'f': OutRep = PRE_FOUR; break;
- case 'z': OutRep = PRE_ZONM; break;
- case 'g': OutRep = PRE_GRID; break;
- }
- }
- if (Mean == 0) Mean = scanpar("mean" ,1);
- if (Mean && OutRep < HYB_GRID)
- {
- sprintf(tb," mean = 1 ignored for spectral data on sigma levels");
- LeftText(tb);
- Mean = 0;
- }
- if (Multi) --Multi;
- if (mars) {
- Grav = MARS_GRAV;
- PlanetRadius = MARS_RADIUS;
- RD = MARS_RD;
- }
- scantime();
- scancode();
- DashLine();
- if (VerType == 's') /* model levels */
- {
- scanmol();
- mom[0] = 1; // surface arrays are selected always
- if (nrml) /* Sigma levels explicitely given */
- {
- nrml = 0;
- for (i=1 ; i <= SigLevs ; ++i)
- {
- if (mom[i])
- {
- level[nrml] = mol[nrml] = i;
- nrml++;
- }
- }
- SigLevs = OutLevs = nrml;
- }
- else /* No sigma levels specified -> select all */
- {
- OutLevs = nrml = SigLevs;
- for (i=0 ; i < OutLevs ; ++i)
- {
- level[i] = mol[i] = mom[i+1] = i+1;
- }
- }
- for (i=0 ; i < OutLevs ; ++i)
- {
- jind = mol[i] - 1;
- LevelUnits[i] = mol[i];
- SigmaF[i] = (int)(500000.0 * (vct[jind+1] - vct[jind])); // sigma * 1E6
- sprintf(tb,"Level %4d = %10.6f",i+1,
- 0.5 * (vct[SigLevs+mol[i]]+vct[SigLevs+mol[i]+1]));
- LeftText(tb);
- }
- }
- else /* pressure levels */
- {
- scanhPa();
- if (nrpl)
- {
- OutLevs = nrpl;
- for (i=0 ; i < OutLevs ; ++i)
- {
- level[i] = 100.0 * hPa[i];
- if (hPa[i] < 0.0) Abort("pressure level < 0.0 is illegal");
- // if (hPa[i] > 2000.0) Abort("pressure level > 2000 hPa is illegal");
- }
- }
- else
- {
- OutLevs = nrpl = 10;
- for (i=0 ; i < OutLevs ; ++i)
- {
- hPa[i] = (i+1) * 100.0;
- level[i] = 100.0 * hPa[i];
- }
- }
- for (i=0 ; i < OutLevs ; ++i)
- {
- LevelUnits[i] = (int)(LevelFactor * 100.0 * hPa[i] + 0.5);
- sprintf(tb,"Level %4d = %14.4f hPa",i+1,hPa[i]);
- LeftText(tb);
- }
- }
- DashLine();
- scanattributes();
- for (i=0 ; i < nattr ; ++i)
- {
- sprintf(tb,"NetCDF attribute[%2d] :%s = \"%s\" ;",
- i,AttrNam[i],AttrVal[i]);
- LeftText(tb);
- }
- }
- void dimcalc(void)
- {
- PolyDisk = Lats == 2048; // Currently T1365 only
- Waves = Truncation + 1;
- Fouriers = Waves * 2;
- DimSP = (Truncation + 1) * (Truncation + 2);
- DimFC = Lats * Fouriers;
- DimGP = Lats * Lons;
- DimGG = Gats * Gons;
- Dim3GP = SigLevs * DimGP;
- Dim3GG = SigLevs * DimGG;
- Dim3FC = SigLevs * DimFC;
- Dim3SP = SigLevs * DimSP;
- DimSP_half = DimSP / 2;
- DimAB = MAX(DimGG,DimGP) + MAX(Lons,Gons);
- DashLine();
- if (VerType == 's') LeftText("Vertical Type = Sigma [S]");
- if (VerType == 'p') LeftText("Vertical Type = Pressure [P]");
- if (HorType == 's') LeftText("Horizontal Type = Spherical Harmonics [S]");
- if (HorType == 'f') LeftText("Horizontal Type = Fourier Coefficients [F]");
- if (HorType == 'z') LeftText("Horizontal Type = Zonal Means [Z]");
- if (HorType == 'g')
- {
- if (Lons == Gons && Lats == Gats)
- {
- LeftText("Horizontal Type = Gaussian Grid [G]");
- GaussianOutput = 1;
- }
- else
- {
- LeftText("Horizontal Type = Grid (Lons x Lats) [G]");
- GaussianOutput = 0;
- }
- }
- DashLine();
- Record_double = new double[DimAB];
- Record_float = (float *)Record_double;
- Record_int = (int *)Record_double;
- Record_short = (unsigned short *)Record_double;
- Record_char = (char *)Record_double;
- CosPhi = new double[Lats];
- RevCosPhi = new double[Lats];
- DerivationFactor = new double[Lats];
- }
- /* ------------------------------------------------------ */
- /* Check file OutRep and decode level number and truncation */
- /* ------------------------------------------------------ */
- void AnalyzeFile(void)
- {
- int i;
- LONG fcb,fce; /* Fortran Record Control Words */
- char Id[8];
- char tb[COLS+2];
-
- union EndianCheck
- {
- char b[sizeof(int)];
- int i;
- } ec;
- ec.i = 8;
- CoreBigEndian = ec.b[0] == 0;
- fread(Id,1,8,fpi); // Read first 8 bytes
- FileBigEndian = Id[0] == 0;
- Endian = CoreBigEndian != FileBigEndian;
- if (FileBigEndian)
- {
- if (Id[3] == 0) LongFCW = 1;
- }
- else
- {
- if (Id[4] == 0) LongFCW = 1;
- }
- rewind(fpi);
- HeadSize = fcb = ReadFCW();
- if (fcb != 8 && fcb != 32 && fcb != 64) Abort("Not a PUMA/PLASIM file");
- CenterText("Found PUMA/Planet Simulator data set");
- if (CoreBigEndian) CenterText("Running on BIG endian machine");
- else CenterText("Running on little endian machine");
- if (FileBigEndian) CenterText("File is in BIG endian format");
- else CenterText("File is in little endian format");
- if (Endian) CenterText("Endian swap activated");
- if (LongFCW) CenterText("Record control words have 64 bits");
- else CenterText("Record control words have 32 bits");
- if (fcb == 8) CenterText("Header format: PUMA-II ");
- if (fcb == 32) CenterText("Header format: Service 32 bit");
- if (fcb == 64) CenterText("Header format: Service 64 bit");
- BlankLine();
- if (fcb == 8)
- {
- HeadSize = 32;
- i = fread(Id,1,8,fpi);
- if (strncmp(Id,"PUMA-II ",8)) Abort("PUMA-II header missing");
-
- fce = ReadFCW();
- if (check_fcw(fcb,fce)) Abort("Wrong FORTRAN control word after PUMA header");
-
- Truncation = ReadINTRecord();
- Gats = ReadINTRecord();
- AllLevs = SigLevs = ReadINTRecord();
- if (SigLevs < 1 || SigLevs > 1000) Abort("Illegal value for Level");
- SingleLevel = (SigLevs == 1);
- nvct = 2 * SigLevs + 2;
-
- /* Check length of sigma vector and determine precision */
-
- fcb = ReadFCW();
- RealSize = fcb / SigLevs; // Should be float (4) or double (8)
- if (RealSize != sizeof(float) && RealSize != sizeof(double))
- Abort("FCW error on level record");
- for (i = 0 ; i < SigLevs ; i++)
- {
- if (RealSize == sizeof(float)) vct[i+SigLevs+2] = ReadFLOAT();
- else vct[i+SigLevs+2] = ReadDOUBLE();
- }
- fce = ReadFCW();
- if (check_fcw(fcb,fce)) Abort("FCW mismatch on level record");
-
-
- /* Header = "PUMA-II " Truncation Lats SigLevs sigmah */
- /* 2-FCW FCW-1-FCW FCW-1-FCW FCW-1-FCW FCW-SigLevs-FCW */
-
- HeaderWords = SigLevs * RealSize / 4 + 5 + 9 * (1 + LongFCW);
-
- ReadHeaderRecord();
- if (HeadIn[7] > 100) DaysPerYear = HeadIn[7];
- }
- else
- {
- rewind(fpi);
- ReadHeaderRecord();
- if (HeadIn[0] != 333) Abort("Initial code 333 was not found");
- Gats = HeadIn[5];
- AllLevs = SigLevs = HeadIn[6];
- SingleLevel = (SigLevs == 1);
- nvct = 2 * SigLevs + 2;
- Truncation = HeadIn[7];
- /* Check length of array and determine precision */
-
- fcb = ReadFCW();
- RealSize = fcb / (Gats * Gats * 2); // Should be float (4) or double (8)
- fseek(fpi,-4*LongFCW,SEEK_CUR);
- if (RealSize != sizeof(float) && RealSize != sizeof(double))
- Abort("FCW error on first array");
- for (i = 0 ; i < SigLevs ; i++)
- {
- if (RealSize == sizeof(float)) vct[i+SigLevs+2] = ReadFLOAT();
- else vct[i+SigLevs+2] = ReadDOUBLE();
- }
- if (RealSize == sizeof(float)) DaysPerYear = ReadFLOAT();
- else DaysPerYear = ReadDOUBLE();
- }
- HeadSt = HeadIn;
- sprintf(tb,"Truncation = %6d",Truncation);
- CenterText(tb);
- sprintf(tb,"Latitudes = %6d",Gats);
- CenterText(tb);
- sprintf(tb,"Longitudes = %6d",Gats*2);
- CenterText(tb);
- sprintf(tb,"Sigma Levels = %6d",SigLevs);
- CenterText(tb);
- if (RealSize == 8)
- sprintf(tb,"Double precision data: Bytes = %6d",RealSize);
- else if (RealSize == 4)
- sprintf(tb,"Single precision data: Bytes = %6d",RealSize);
- else
- sprintf(tb,"Size of real data = %6d",RealSize);
- CenterText(tb);
- BlankLine();
- sprintf(tb,"Half Level [p] [sigma]");
- CenterText(tb);
- for (i = 0; i<nvct/2; i++)
- {
- sprintf(tb,"%10.1f %14.4f %14.4f",(float)i,vct[i],vct[i+nvct/2]);
- CenterText(tb);
- }
- StarLine();
-
- rewind(fpi);
- }
- const char *MoName[13] = {"Nix","Jan","Feb","Mar","Apr","May","Jun",
- "Jul","Aug","Sep","Oct","Nov","Dec"};
- void WriteGradsCtl()
- {
- int i,j,yy,mm,dd,code,varcodes;
- FILE *fp;
- double DelLon;
- fp = fopen(gfile,"w");
- if (HorType == 'z')
- fprintf(fp,"DSET ^%s\n",rfile);
- else
- fprintf(fp,"DSET ^%s\n",ofile);
- fprintf(fp,"UNDEF 9e09i\n");
- if (HorType == 'z')
- fprintf(fp,"XDEF 1 LINEAR 0 1\n");
- else
- {
- DelLon = 360.0 / Gons;
- fprintf(fp,"XDEF %5d LINEAR 0.0 %14.8f\n",Gons,DelLon);
- }
- fprintf(fp,"OPTIONS YREV\n");
- fprintf(fp,"YDEF %5d LEVELS\n",Gats);
- for (j=Gats-1 ; j >= 0 ; j-=8)
- {
- for (i=j ; i >= 0 && i> j-8 ; --i)
- fprintf(fp,"%14.8f",Outlat->Phi[i]);
- fprintf(fp,"\n");
- }
- if (HorType != 'z')
- {
- fprintf(fp,"OPTIONS SEQUENTIAL\n");
- fprintf(fp,"XYHEADER %d\n",40 + 8 * LongFCW);
- }
- if (OutLevs < 2)
- {
- if (VerType == 'p') fprintf(fp,"ZDEF 1 LINEAR %14.8f 1\n",hPa[0]);
- else fprintf(fp,"ZDEF 1 LINEAR %d 1\n",mol[0]);
- }
- else
- {
- fprintf(fp,"ZDEF %d LEVELS\n",OutLevs);
- if (VerType == 'p')
- {
-
- for (j=0 ; j < OutLevs ; j+=8)
- {
- for (i=j ; i < OutLevs && i < j+8 ; ++i)
- if (HorType == 'z' && hPa[0] < hPa[OutLevs-1])
- fprintf(fp,"%14.8f",hPa[OutLevs-1-i]);
- else
- fprintf(fp,"%14.8f",hPa[i]);
- fprintf(fp,"\n");
- }
- if (HorType == 'z' && hPa[0] < hPa[OutLevs-1])
- fprintf(fp,"OPTIONS ZREV\n");
- }
- else
- {
- for (j=0 ; j < OutLevs ; j+=8)
- {
- for (i=j ; i < OutLevs && i < j+8 ; ++i)
- if (HorType == 'z' && mol[0] < mol[OutLevs-1])
- fprintf(fp,"%10d",mol[OutLevs-1-i]);
- else
- fprintf(fp,"%10d",mol[i]);
- fprintf(fp,"\n");
- }
- if (HorType == 'z' && mol[0] < mol[OutLevs-1])
- fprintf(fp,"OPTIONS ZREV\n");
- }
- }
- yy = HeadSt[2] / 10000;
- mm = HeadSt[2] / 100 % 100;
- dd = HeadSt[2] % 100;
- if (Mean)
- fprintf(fp,"TDEF %d LINEAR 00:00z%d%s%d 1mo\n",
- MonthCount,dd,MoName[mm],yy);
- else if (DeltaMn > 0)
- fprintf(fp,"TDEF %d LINEAR 00:00z%d%s%d %dmn\n",
- TermCount,dd,MoName[mm],yy,DeltaMn);
- else if (DeltaHr > 0)
- fprintf(fp,"TDEF %d LINEAR 00:00z%d%s%d %dhr\n",
- TermCount,dd,MoName[mm],yy,DeltaHr);
- else
- fprintf(fp,"TDEF %d LINEAR 00:00z%d%s%d %ddy\n",
- TermCount,dd,MoName[mm],yy,DeltaDy);
- varcodes = 0;
- for (code = 0 ; code < CODES ; ++code)
- if (All[code].selected) ++varcodes;
- fprintf(fp,"VARS %d\n",varcodes);
- for (code = 0 ; code < CODES ; ++code)
- if (All[code].selected)
- fprintf(fp,"%s %d 99 %s\n",
- All[code].Id,All[code].plev,All[code].Na);
- fprintf(fp,"ENDVARS\n");
- fclose(fp);
- }
- int main(int argc, char *argv[])
- {
- int i,l;
- int wdim;
- char tb[COLS+2];
- time_t StartTime;
- StartTime = time(NULL);
- /*********************/
- /* print information */
- /*********************/
-
- StarLine();
- CenterText(V0);
- CenterText(V1);
- DashLine();
- CenterText(V2);
- CenterText(V3);
- CenterText(V4);
- StarLine();
- sprintf(tb,"Run started at %s",ctime(&StartTime));
- strcpy(tb+strlen(tb)-1," local time");
- CenterText(tb);
- StarLine();
-
- InitAll();
- /***********************/
- /* options & filenames */
- /***********************/
- for (i = 1 ; i < argc ; ++i) {
- if (argv[i][0] == '-') {
- if (argv[i][1] == 'c') {PrintCodes(); exit(1);}
- else if (argv[i][1] == 'd') Debug = 1;
- else if (argv[i][1] == 'v') Debug = 1;
- else if (argv[i][1] == 'n') NetCDF = 1;
- else if (argv[i][1] == 'g') Grads = 1;
- else if (argv[i][1] == 'm') Mean = 1;
- else if (argv[i][1] == 'p') PolyCreate = 1;
- else if (argv[i][1] == 'i') GaussGrid = 1;
- else if (argv[i][1] == 'r') GaussGrid = 0;
- else if (argv[i][1] == 's') SaveMemory = 1;
- else Usage();
- }
- else if (ifile[0] == '\0') strcpy(ifile,argv[i]);
- else if (ofile[0] == '\0') strcpy(ofile,argv[i]);
- else if (strcmp("Debug",argv[i]) == 0) Debug = 1;
- else Usage();
- }
- if (NetCDF) Grads = 0;
- if (ifile[0] == '\0' || ofile[0] == '\0') {
- printf("*** Missing filename ***\n");
- Usage();
- }
- /*******************/
- /* open input file */
- /*******************/
-
- fpi = fopen(ifile,"rb");
- if (fpi == 0) {
- printf("could not open input file %s\n",ifile);
- exit(1);
- }
- /******************/
- /* pre-processing */
- /******************/
- AnalyzeFile();
- Gons = Gats * 2;
- Lats = Gats;
- Lons = Gons;
- /*******************/
- /* initializations */
- /*******************/
- parini();
- l = strlen(ofile);
- if (NetCDF) // Add ".nc" extension for NetCDF filename if not specified
- {
- if (l < 4 || strcmp(ofile+l-3,".nc")) strcat(ofile,".nc");
- }
- else // Add ".srv" extension for Service format if not specified
- {
- if (l > 4 && !strcmp(ofile+l-4,".srv")) l -= 4;
- ofile[l] = 0;
- strcpy(gfile,ofile);
- strcpy(rfile,ofile);
- strcat(ofile,".srv");
- strcat(gfile,".ctl");
- strcat(rfile,".gra");
- }
- sprintf(tb," Input File: %s",ifile); LeftText(tb);
- sprintf(tb,"Output File: %s",ofile); LeftText(tb);
- if (Grads) {sprintf(tb,"Grads File: %s",gfile); LeftText(tb);}
- if (Grads && HorType == 'z')
- {sprintf(tb,"Grads Data: %s",rfile); LeftText(tb);}
- if (Debug) LeftText("Debug on");
- #ifndef NETCDF_OUTPUT
- if (NetCDF) Abort("This executable was not compiled for NetCDF");
- #endif
- /********************/
- /* open output file */
- /********************/
- if (!NetCDF)
- {
- gp = fopen(ofile,"wb");
- if (gp == 0)
- {
- printf("could not open output file <%s>\n",ofile);
- exit(1);
- }
- }
- dimcalc();
-
- HybSpec = new ServiceGrid(gp,DimSP,1);
- HybFour = new ServiceGrid(gp,Lats,Fouriers);
- HybGrid = new ServiceGrid(gp,Lons,Lats);
- HybSect = new ServiceSect(gp,Lats,OutLevs);
- /* FFT initialization */
- if (OutLevs <= SigLevs) wdim = (Lons + 3) * Lats * SigLevs;
- else wdim = (Lons + 3) * Lats * OutLevs ;
- wfc = new double[wdim];
- wgp = new double[wdim];
- fft_set(Lons);
- filename = strrchr(ifile,'/');
- if (filename == 0) filename = ifile;
- else filename++ ;
- HeadOu[7] = atol(filename);
- if (VerType == 'p' &&
- (Divergence->selected || VeloPot->selected ||
- Vorticity->selected || StreamF->selected))
- SpecialUV = 1;
- Dependencies();
- // Check correct vertical coordinate
- if (GeopotHeight->selected && VerType != 'p')
- {
- printf("\n ****************** E R R O R ************************\n");
- printf(" * Geopotential height (156) requires pressure level *\n");
- printf(" *****************************************************\n");
- exit(1);
- }
- Geopotential->needed |= OutRep >= PRE_GRID
- || SLP->needed || GeopotHeight->needed;
- if (OutRep) legini();
- if (PolyCreate) exit(0); /* Called for Legendre Polynomials only */
- #ifdef NETCDF_OUTPUT
- if (NetCDF) NetOpen(ofile);
- #endif
- PumaControl();
- if (gp) fclose(gp);
- #ifdef NETCDF_OUTPUT
- if (NetCDF) NetClose();
- #endif
- if (Grads) WriteGradsCtl();
- StarLine();
- if (DaysPerYear < 1) DaysPerYear = 360;
- if (DPM > 99) DaysPerYear = DPM * 12;
- sprintf(tb,"Using %d day calendar",DaysPerYear);
- CenterText(tb);
- sprintf(tb,"Data interval = %6.2f hours",DataStep * 24.0);
- CenterText(tb);
- StarLine();
- {
- double ut,st;
- struct rusage ru;
- getrusage(RUSAGE_SELF,&ru);
- ut = ru.ru_utime.tv_sec + 0.000001 * ru.ru_utime.tv_usec;
- st = ru.ru_stime.tv_sec + 0.000001 * ru.ru_stime.tv_usec;
- sprintf(tb,"User time: %10.3lf seconds",ut);
- LeftText(tb);
- sprintf(tb,"System time: %10.3lf seconds",st);
- LeftText(tb);
- sprintf(tb,"Total time: %10.3lf seconds",ut+st);
- LeftText(tb);
- if (ru.ru_maxrss > 0)
- {
- sprintf(tb,"Memory usage: %10.3lf MBytes",0.000001 * ru.ru_maxrss);
- LeftText(tb);
- }
- if (ru.ru_minflt > 0)
- {
- sprintf(tb,"Page reclaims: %10ld page",ru.ru_minflt);
- if (ru.ru_minflt != 1) strcat(tb,"s");
- LeftText(tb);
- }
- if (ru.ru_majflt > 0)
- {
- sprintf(tb,"Page faults: %10ld page",ru.ru_majflt);
- if (ru.ru_majflt != 1) strcat(tb,"s");
- LeftText(tb);
- }
- if (ru.ru_nswap > 0)
- {
- sprintf(tb,"Swaps : %10ld",ru.ru_nswap);
- LeftText(tb);
- }
- if (ru.ru_inblock > 0)
- {
- sprintf(tb,"Disk read: %10ld block",ru.ru_inblock);
- if (ru.ru_inblock != 1) strcat(tb,"s");
- LeftText(tb);
- }
- if (ru.ru_oublock > 0)
- {
- sprintf(tb,"Disk Write: %10ld block",ru.ru_oublock);
- if (ru.ru_oublock != 1) strcat(tb,"s");
- LeftText(tb);
- }
- StarLine();
- }
- return 0;
- }
|