burn7.cpp 171 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335
  1. /* c++ -O2 -o burn7.x burn7.cpp -lm -lnetcdf_c++ -lnetcdf */
  2. #define NETCDF_OUTPUT
  3. #define V0 "burn 7.7 (02-Feb-2017)"
  4. #define V1 "KlimaCampus"
  5. #define V2 "Usage: burn7 [-help|-c|-d|-m|-n|-r|-s] <modelfile> <resultfile>"
  6. #define V3 "New: option <-g> writes Grads ctl for service plotting"
  7. #define V4 "New: comments (#) are allowed in namelist file"
  8. /* ============= */
  9. /* include files */
  10. /* ============= */
  11. #include <ctype.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <math.h>
  16. #include <time.h>
  17. #include <sys/resource.h>
  18. #include <vector>
  19. #include <valarray>
  20. #ifdef OPEN_MP
  21. #include <omp.h>
  22. #endif
  23. #ifdef NETCDF_OUTPUT
  24. #include <netcdfcpp.h>
  25. #endif
  26. using namespace std;
  27. #define LONG long long
  28. #ifndef M_PI
  29. #define M_PI 3.1415926535
  30. #endif
  31. #ifndef M_SQRT2
  32. #define M_SQRT2 1.4142136
  33. #endif
  34. #ifndef MAX
  35. #define MAX(v1,v2) ((v1) > (v2) ? (v1) : (v2))
  36. #endif
  37. #ifndef min
  38. #define min(v1,v2) ((v1) < (v2) ? (v1) : (v2))
  39. #endif
  40. #ifndef abs
  41. #define abs(x) ((x) >= 0 ? (x) : -(x))
  42. #endif
  43. #ifndef TRUE
  44. #define TRUE 1
  45. #endif
  46. #ifndef FALSE
  47. #define FALSE 0
  48. #endif
  49. #define LEV_SURFACE 1
  50. #define LEV_99 99
  51. #define LEV_ISOBARIC 100
  52. #define LEV_MEANSEA 102
  53. #define LEV_ALTITUDE 103
  54. #define LEV_HEIGHT 105
  55. #define LEV_SIGMA 107
  56. #define LEV_HYBRID 109
  57. #define LEV_GROUND 112
  58. #define REP_REGULAR 0
  59. #define REP_GAUSS 4
  60. #define REP_SPECTRAL 50
  61. #define MAX_HOURS 4
  62. #define MAX_LEVELS 99
  63. #define MAX_NVCT (MAX_LEVELS * 2 + 2)
  64. #define L_TIMES_RHOH2O (-333700000.0)
  65. #define EARTH_RADIUS 6371220.0
  66. #define MARS_RADIUS 3400000.0
  67. #define SQUARE_RADIUS (-PlanetRadius * PlanetRadius)
  68. #define EARTH_GRAV 9.80665
  69. #define MARS_GRAV 3.728
  70. #define RG (1.0 / Grav)
  71. #define MARS_RD (189.0 )
  72. /* ************************************** */
  73. /* Thermodynamical constants adopted from */
  74. /* ECMWF IFS-Code */
  75. /* ************************************** */
  76. #define RKBOL (1.380658e-23)
  77. #define RNAVO (6.0221367e+23)
  78. #define R (RKBOL * RNAVO)
  79. #define RMD (28.9644)
  80. #define RMV (18.0153)
  81. #define EARTH_RD (1000. * R / RMD)
  82. #define RV (1000. * R / RMV)
  83. #define RCPD (3.5 * RD)
  84. #define RCPV (4.0 * RV)
  85. #define RETV (RV / RD - 1.)
  86. #define RCW (4218.)
  87. #define RCS (2106.)
  88. #define RTT (273.16)
  89. #define RLVTT (2.5008e+6)
  90. #define RLSTT (2.8345e+6)
  91. #define RESTT (611.14)
  92. #define RLAPSE (0.0065)
  93. #ifdef NETCDF_OUTPUT
  94. NcFile *NetFile;
  95. NcVar *LonVar;
  96. NcVar *LatVar;
  97. NcVar *LevVar;
  98. NcVar *TimVar;
  99. NcDim *LonDim;
  100. NcDim *LatDim;
  101. NcDim *LevDim;
  102. NcDim *TimDim;
  103. #endif
  104. int SaveMemory = 0; /* Switch on for dynamic memory usage */
  105. int PolyCreate = 0; /* Create polynomials files for hires T1365 and more */
  106. int PolyDisk = 0; /* Read polynomials from disk */
  107. int GaussGrid = -1; /* 1: use Gaussian grid, 0: use regular grid */
  108. int DPM = 0; /* Days Per Month */
  109. int DPY = 0; /* Days Per Year */
  110. int DayDivisor = 0; /* Use for day adjustment if more than 99 days per month */
  111. char VerType; /* s=Sigma p=Pressure */
  112. char HorType; /* s=Spherical f=Fourier z=Zonal Mean g=Gauss Grid */
  113. char *filename;
  114. char ifile[256]; // name of input file (PUMA-II format)
  115. char ofile[256]; // Name of output file (Service or NetCDF format)
  116. char gfile[256]; // Name of Grads control file
  117. char rfile[256]; // Name of Grads data file (for zonal means only)
  118. #define MAX_NL 40960
  119. char namelist[MAX_NL];
  120. char AllocName[256];
  121. int PumaCode;
  122. int PumaLevel;
  123. int RepGrib;
  124. int Debug;
  125. int Dim3FC ;
  126. int Dim3SP ;
  127. int Dim3GG ;
  128. int Dim3GP ;
  129. int DimFC ; // Dimension of fourier array
  130. int DimGP ; // Dimension of output grid
  131. int DimGG ; // Dimension of Gauss grid
  132. int DimAB ; // Dimension of array buffer
  133. int DimSP ;
  134. int DimSP_half ;
  135. int CoreBigEndian ; // Do we run on a big endian machine ?
  136. int FileBigEndian ;
  137. int Endian = 0 ; /* Marker for reverse endian format */
  138. int LongFCW = 0 ; /* Flag for 64bit (1) or 32bit (0) FCW's */
  139. int RealSize = 4 ; /* Size of real data (4 = float) (8 = double) */
  140. int HeadSize = 32 ; // 32:Service single 64:Service double
  141. int EndOfMonth ;
  142. int EndOfTerm ;
  143. int Fouriers ;
  144. int HumInfo ; // Flag for humidity info issued
  145. double Grav = EARTH_GRAV;
  146. double SigmaTop = 0.0;
  147. int NetCDF ;
  148. int GaussianOutput = 1;
  149. int Grads ;
  150. int HeaderWords ; /* Length of file header in 32-bit words */
  151. int Gats ;
  152. int Lats ;
  153. int AllLevs = 0 ; // # of sigma levels in data file
  154. int SigLevs = 0 ; // # of sigma levels used
  155. int SingleLevel = 0 ; // Set to true for SAM/SOM models
  156. double LevelFactor = 1.0 ; // Multiplier for head(2)
  157. int LevelType ;
  158. int Gons ;
  159. int Lons ;
  160. int Cyclical = 0 ; // 1 = Cyclical completion (Lons from 0 to 360)
  161. double L_times_rhoH2O = L_TIMES_RHOH2O;
  162. int mars ;
  163. int Mean ;
  164. int MeanCount ; // Count terms during month
  165. int Multi ;
  166. int FirstMonth = 1;
  167. int LastMonth = 12;
  168. double PlanetRadius= EARTH_RADIUS;
  169. double RD = EARTH_RD;
  170. int Spectral = FALSE;
  171. int TermCount ;
  172. int MonthCount ;
  173. int OutputCount ;
  174. int Truncation = 0;
  175. int Waves ;
  176. int SpecialUV ;
  177. struct tm NewDate;
  178. struct tm OldDate;
  179. int NewMonth;
  180. int OldMonth;
  181. // Some functions for a nice printout
  182. #define COLS 72
  183. void Stars(int n) {while (n--) putchar('*');}
  184. void ErrStars(int n) {while (n--) putc('*',stderr);}
  185. void Blanks(int n) {while (n--) putchar(' ');}
  186. void Dashes(int n) {while (n--) putchar('-');}
  187. void NewLine(void) {putchar('\n');}
  188. void ErrNewLine(void) {putc('\n',stderr);}
  189. void StarLine(void) {Stars(COLS); NewLine();}
  190. /* ==================================== */
  191. /* Abort - Print error message and exit */
  192. /* ==================================== */
  193. void Abort(const char *errtext)
  194. {
  195. Stars(min(80,strlen(errtext))); NewLine();
  196. puts(errtext); NewLine();
  197. Stars(min(80,strlen(errtext))); NewLine();
  198. ErrStars(min(80,strlen(errtext))); ErrNewLine();
  199. fputs(errtext,stderr); ErrNewLine();
  200. ErrStars(min(80,strlen(errtext))); ErrNewLine();
  201. exit(1);
  202. }
  203. void BlankLine(void)
  204. {
  205. putchar('*');
  206. Blanks(COLS-2);
  207. putchar('*');
  208. NewLine();
  209. }
  210. void DashLine(void)
  211. {
  212. putchar('*');
  213. putchar(' ');
  214. Dashes(COLS-4);
  215. putchar(' ');
  216. putchar('*');
  217. NewLine();
  218. }
  219. void CenterText(const char *t)
  220. {
  221. int i,j,l;
  222. l = strlen(t);
  223. if (l < 1) return;
  224. if (l > COLS-4) puts(t);
  225. else
  226. {
  227. i = (COLS - 4 - l) / 2;
  228. j = (COLS - 4 - l - i);
  229. putchar('*');
  230. Blanks(i+1);
  231. fputs(t,stdout);
  232. Blanks(j+1);
  233. putchar('*');
  234. NewLine();
  235. }
  236. }
  237. void LeftText(const char *t)
  238. {
  239. int l;
  240. l = strlen(t);
  241. if (l < 1) return;
  242. if (l > COLS-4) puts(t);
  243. else
  244. {
  245. putchar('*');
  246. putchar(' ');
  247. fputs(t,stdout);
  248. Blanks(COLS - l - 3);
  249. putchar('*');
  250. NewLine();
  251. }
  252. }
  253. #define MAX_ID_LEN 8
  254. #define MAX_NA_LEN 32
  255. #define MAX_UN_LEN 16
  256. class Control
  257. {
  258. public:
  259. int readit ;
  260. int needed ;
  261. int selected ;
  262. int detected ;
  263. int hlev ;
  264. int plev ;
  265. int loff ;
  266. int twod ;
  267. int code ;
  268. valarray<double>hsp;
  269. valarray<double>hfc;
  270. valarray<double>hgp;
  271. valarray<double>pgp;
  272. valarray<double>mgp;
  273. valarray<double>pfc;
  274. valarray<double>psp;
  275. char Id[MAX_ID_LEN];
  276. char Na[MAX_NA_LEN];
  277. char Un[MAX_UN_LEN];
  278. #ifdef NETCDF_OUTPUT
  279. NcVar *NetVar ;
  280. #endif
  281. void Status(void);
  282. void Init(const char* Idf, const char *Name, const char *Units, int TwoD);
  283. void SetHSpec(int Hlev, int Plev, int Twod);
  284. void SetHFour(int Hlev, int Plev, int Twod);
  285. void SetHGrid(int Hlev, int Plev, int Twod);
  286. void SetPGrid(void);
  287. void SetPFour(void);
  288. void SetPSpec(void);
  289. };
  290. void Control::Status(void)
  291. {
  292. printf("\nStatus for code %3d: %s\n",code,Id);
  293. printf("-------------------------\n");
  294. printf("needed: %5d\n",needed);
  295. printf("selected: %5d\n",selected);
  296. printf("detected: %5d\n",detected);
  297. printf("hlev: %5d\n",hlev);
  298. printf("plev: %5d\n",plev);
  299. printf("twod: %5d\n",twod);
  300. printf("hsp: %5ld\n",hsp.size());
  301. printf("hfc: %5ld\n",hfc.size());
  302. printf("hgp: %5ld\n",hgp.size());
  303. printf("pgp: %5ld\n",pgp.size());
  304. printf("mean: %5ld\n",mgp.size());
  305. printf("pfc: %5ld\n",pfc.size());
  306. printf("psp: %5ld\n",psp.size());
  307. if (hgp.size()) printf("mean of hgp: %16.10lf\n",hgp.sum() / hgp.size());
  308. if (pgp.size()) printf("mean of pgp: %16.10lf\n",pgp.sum() / pgp.size());
  309. };
  310. void Control::Init(const char* Idf, const char *Name, const char *Units, int TwoD)
  311. {
  312. strncpy(Id,Idf ,MAX_ID_LEN-1);
  313. strncpy(Na,Name ,MAX_NA_LEN-1);
  314. strncpy(Un,Units,MAX_UN_LEN-1);
  315. twod = TwoD;
  316. }
  317. void Control::SetHSpec(int Hlev, int Plev, int Twod)
  318. {
  319. int OldSize;
  320. int NewSize;
  321. hlev = Hlev;
  322. plev = Plev;
  323. twod = Twod;
  324. OldSize = hsp.size();
  325. NewSize = Hlev * DimSP;
  326. if (NewSize == OldSize) return;
  327. hsp.resize(NewSize);
  328. if (Debug)
  329. {
  330. char tb[COLS];
  331. if (OldSize == 0)
  332. sprintf(tb,"Alloc: %p %6s[%3d].hsp %6ld double",&hsp[0],Id,code,hsp.size());
  333. else
  334. sprintf(tb,"Realloc: %p %6s[%3d].hsp %6ld double",&hsp[0],Id,code,hsp.size());
  335. LeftText(tb);
  336. }
  337. }
  338. void Control::SetHFour(int Hlev, int Plev, int Twod)
  339. {
  340. if (hfc.size() == Hlev * DimFC) return;
  341. hlev = Hlev;
  342. plev = Plev;
  343. twod = Twod;
  344. hfc.resize(hlev * DimFC);
  345. if (Debug)
  346. {
  347. char tb[COLS];
  348. sprintf(tb,"Alloc: %p %6s[%3d].hfc %6ld double",&hfc[0],Id,code,hfc.size());
  349. LeftText(tb);
  350. }
  351. }
  352. void Control::SetPFour(void)
  353. {
  354. if (pfc.size() == plev * DimFC) return;
  355. pfc.resize(plev * DimFC);
  356. if (Debug)
  357. {
  358. char tb[COLS];
  359. sprintf(tb,"Alloc: %p %6s[%3d].pfc %6ld double",&pfc[0],Id,code,pfc.size());
  360. LeftText(tb);
  361. }
  362. }
  363. void Control::SetHGrid(int Hlev, int Plev, int Twod)
  364. {
  365. if (hgp.size() == Hlev * DimGP) return;
  366. hlev = Hlev;
  367. plev = Plev;
  368. twod = Twod;
  369. hgp.resize(hlev * DimGP);
  370. if (Debug)
  371. {
  372. char tb[COLS];
  373. sprintf(tb,"Alloc: %p %6s[%3d].hgp %6d double",&hgp[0],Id,code,hlev*DimGP);
  374. LeftText(tb);
  375. }
  376. }
  377. void Control::SetPGrid(void)
  378. {
  379. if (twod && hgp.size())
  380. {
  381. pgp.resize(DimGP);
  382. pgp = hgp;
  383. hgp.resize(0);
  384. if (Debug)
  385. {
  386. char tb[COLS];
  387. sprintf(tb,"Moved: %p %6s[%3d].hgp to pgp",&pgp[0],Id,code);
  388. LeftText(tb);
  389. }
  390. }
  391. else if (pgp.size() != plev * DimGP)
  392. {
  393. pgp.resize(plev * DimGP);
  394. if (Debug)
  395. {
  396. char tb[COLS];
  397. sprintf(tb,"Alloc: %p %6s[%3d].pgp %6d double",&pgp[0],Id,code,plev*DimGP);
  398. LeftText(tb);
  399. }
  400. }
  401. }
  402. void Control::SetPSpec(void)
  403. {
  404. int OldSize;
  405. int NewSize;
  406. OldSize = psp.size();
  407. NewSize = plev * DimSP;
  408. if (NewSize == OldSize) return;
  409. psp.resize(NewSize);
  410. if (Debug)
  411. {
  412. char tb[COLS];
  413. if (OldSize == 0)
  414. sprintf(tb,"Alloc: %p %6s[%3d].psp %6ld double",&psp[0],Id,code,psp.size());
  415. else
  416. sprintf(tb,"Realloc: %p %6s[%3d].psp %6ld double",&psp[0],Id,code,psp.size());
  417. LeftText(tb);
  418. }
  419. }
  420. #define CODES 512
  421. #define MAXCODES (CODES+5)
  422. #define GEOSCODE 129
  423. #define TCODE 130
  424. #define UCODE 131
  425. #define VCODE 132
  426. #define SHCODE 133
  427. #define PSCODE 134
  428. #define WCODE 135
  429. #define WZCODE 137
  430. #define VORCODE 138
  431. #define STRCODE 148
  432. #define VELCODE 149
  433. #define SLPCODE 151
  434. #define LNPSCODE 152
  435. #define DIVCODE 155
  436. #define ZCODE 156
  437. #define RHCODE 157
  438. int SpecialCodes[4] = {DIVCODE,VORCODE,STRCODE,VELCODE};
  439. Control All[MAXCODES];
  440. Control *Geopotential = &All[129];
  441. Control *Temperature = &All[130];
  442. Control *u_wind = &All[131];
  443. Control *v_wind = &All[132];
  444. Control *Humidity = &All[133];
  445. Control *Ps = &All[134];
  446. Control *Omega = &All[135];
  447. Control *w_wind = &All[137];
  448. Control *Vorticity = &All[138];
  449. Control *Ts = &All[139];
  450. Control *StreamF = &All[148];
  451. Control *VeloPot = &All[149];
  452. Control *SLP = &All[151];
  453. Control *LnPs = &All[152];
  454. Control *Divergence = &All[155];
  455. Control *GeopotHeight = &All[156];
  456. Control *Rhumidity = &All[157];
  457. Control *speed = &All[259];
  458. Control *precip = &All[260];
  459. Control *net_top = &All[261];
  460. Control *net_bot = &All[262];
  461. Control *net_heat = &All[263];
  462. Control *net_water = &All[264];
  463. Control *sw_atm = &All[268];
  464. Control *lw_atm = &All[269];
  465. Control *net_atm = &All[270];
  466. Control *surf_runoff = &All[271];
  467. Control *dpsdx = &All[273];
  468. Control *dpsdy = &All[274];
  469. Control *fresh_water = &All[275];
  470. Control *HalfPress = &All[277];
  471. Control *FullPress = &All[278];
  472. Control *ThetaH = &All[279];
  473. Control *ThetaF = &All[280];
  474. int *vert_index;
  475. valarray<double>Orography;
  476. double *poli;
  477. double *pol2;
  478. double *pliu;
  479. double *pliv;
  480. char polin[80]; /* filenames for polynomial files */
  481. char pol2n[80];
  482. char pliun[80];
  483. char plivn[80];
  484. FILE *polif;
  485. FILE *pol2f;
  486. FILE *pliuf;
  487. FILE *plivf;
  488. int OutLevs; /* number of requested output levels */
  489. int nrpl; /* number of requested pressure levels */
  490. int nrml; /* number of requested model levels */
  491. int nrqh;
  492. #define ATTR_MAX 20
  493. int nattr; /* number of global attributes (NetCDF) */
  494. char AttrNam[ATTR_MAX][80];
  495. char AttrVal[ATTR_MAX][80];
  496. int nvct = 0;
  497. double vct[MAX_NVCT];
  498. int DaysPerYear = 360;
  499. double DataStep = 0.0;
  500. int DeltaDy;
  501. int DeltaHr;
  502. int DeltaMn;
  503. vector<int>HeadSt(8,0); // First header vector
  504. vector<int>HeadIn(8,0); // Input header vector
  505. vector<int>HeadOu(8,0); // Output header vector
  506. #define HYB_SPEC 0
  507. #define HYB_FOUR 1
  508. #define HYB_ZONM 2
  509. #define HYB_GRID 3
  510. #define PRE_GRID 4
  511. #define PRE_FOUR 5
  512. #define PRE_ZONM 6
  513. #define PRE_SPEC 7
  514. int OutRep = HYB_SPEC; // Output Representation
  515. int hours[MAX_HOURS+1];
  516. double level[MAX_LEVELS+1];
  517. int LevelFound[MAX_LEVELS+1];
  518. double hPa[MAX_LEVELS];
  519. int mol[MAX_LEVELS];
  520. int mom[MAX_LEVELS]; /* Mask for selected levels */
  521. int LevelUnits[MAX_LEVELS];
  522. int SigmaF[MAX_LEVELS];
  523. double *Record_double;
  524. float *Record_float; // Buffer for FORTRAN records
  525. int *Record_int; // All share the same space
  526. unsigned short *Record_short;
  527. char *Record_char;
  528. double *CosPhi; /* Cosine of Phi (Latitude) */
  529. double *RevCosPhi; /* 1.0 / CosPhi */
  530. double *DerivationFactor;
  531. double *wfc; /* FFT work array */
  532. double *wgp; /* FFT work array */
  533. int ifax[10]; /* FFT factorization */
  534. FILE *fpi;
  535. FILE *gp;
  536. class RegLon // class for equidistant longituinal array
  537. {
  538. char Name[16]; // Array name
  539. double DeltaLam; // Distance of Longitudes
  540. public:
  541. int Lons; // Number of latitudes
  542. double *Lam; // Coordinate in degrees
  543. RegLon(int, const char *); // Constructor
  544. ~RegLon(void); // Destructor
  545. void PrintArray(void); // Print table
  546. };
  547. RegLon::RegLon(int n, const char *name)
  548. {
  549. int jlon;
  550. Lons = n;
  551. DeltaLam = 360.0 / Lons;
  552. Lam = new double[Lons+1];
  553. for (jlon=0 ; jlon < Lons ; ++jlon)
  554. {
  555. Lam[jlon] = jlon * DeltaLam;
  556. }
  557. Lam[Lons] = 360.0;
  558. strncpy(Name,name,15);
  559. }
  560. RegLon::~RegLon(void)
  561. {
  562. delete Lam;
  563. }
  564. void RegLon::PrintArray(void)
  565. {
  566. int jlon;
  567. printf("*******************************\n");
  568. printf("* %16.16s Longitude *\n",Name);
  569. printf("*******************************\n");
  570. for (jlon=0 ; jlon < Lons ; ++jlon)
  571. printf("* %16d %10.4f *\n",jlon,Lam[jlon]);
  572. printf("*******************************\n");
  573. }
  574. class RegLat // class for equidistant latitudinal array
  575. {
  576. char Name[16]; // Array name
  577. double DeltaPhi; // Distance of latitudes
  578. double FirstPhi; // First latitude
  579. public:
  580. int Lats; // Number of latitudes
  581. double *Phi; // Coordinate in degrees
  582. double *gmu; // Sine of phi
  583. double *gwt; // Gaussian weight
  584. RegLat(int, const char *); // Constructor
  585. ~RegLat(void); // Destructor
  586. void PrintArray(void); // Print table
  587. };
  588. RegLat::RegLat(int n, const char *name)
  589. {
  590. int jlat;
  591. Lats = n;
  592. DeltaPhi = 180.0 / (Lats - 1);
  593. Phi = new double[Lats];
  594. gmu = new double[Lats];
  595. gwt = new double[Lats];
  596. if (Lats & 1) /* odd -> start with DeltaPhi */
  597. {
  598. DeltaPhi = 180.0 / (Lats + 1);
  599. FirstPhi = 90.0 - DeltaPhi;
  600. }
  601. else /* even -> start with 0.5 DeltaPhi */
  602. {
  603. DeltaPhi = 180.0 / Lats;
  604. FirstPhi = 90.0 - 0.5 * DeltaPhi;
  605. }
  606. for (jlat=0 ; jlat < Lats ; ++jlat)
  607. {
  608. Phi[jlat] = FirstPhi - jlat * DeltaPhi;
  609. gmu[jlat] = sin(Phi[jlat] * M_PI / 180.0);
  610. gwt[jlat] = 0.0;
  611. }
  612. strncpy(Name,name,15);
  613. }
  614. RegLat::~RegLat(void)
  615. {
  616. delete Phi;
  617. delete gmu;
  618. delete gwt;
  619. }
  620. void RegLat::PrintArray(void)
  621. {
  622. int jlat;
  623. printf("*******************************\n");
  624. printf("* %16.16s Latitude *\n",Name);
  625. printf("*******************************\n");
  626. for (jlat=0 ; jlat < Lats ; ++jlat)
  627. printf("* %16d %10.4f *\n",jlat,Phi[jlat]);
  628. printf("*******************************\n");
  629. }
  630. class GauLat : public RegLat
  631. {
  632. public:
  633. GauLat(int, const char *); // Constructor
  634. ~GauLat(void); // Destructor
  635. private:
  636. void IniGau(void);
  637. double nlp(int, double);
  638. double dlp(int, double);
  639. };
  640. GauLat::GauLat(int n, const char *name) : RegLat(n, name)
  641. {
  642. int jlat;
  643. IniGau();
  644. for (jlat = 0 ; jlat < Lats ; ++jlat)
  645. Phi[jlat] = 180.0 * asin(gmu[jlat]) / M_PI;
  646. }
  647. GauLat::~GauLat(void)
  648. {
  649. }
  650. /* ============================== */
  651. /* Calculate Legendre Polynomials */
  652. /* ============================== */
  653. double GauLat::nlp(int k, double p) // After Nodorp (1988)
  654. {
  655. int j;
  656. double z0,z1,z2,z3,z4;
  657. z0 = acos(p);
  658. z1 = 1.0;
  659. z2 = 0.0;
  660. z3 = 0.0;
  661. for (j=k ; j >= 0 ; j-=2)
  662. {
  663. z3 = z1 * cos(j * z0);
  664. z2 += z3;
  665. z4 = (k-j+1) * (k+j)/2;
  666. z1 *= z4 / (z4+j-1);
  667. }
  668. if (k % 2 == 0) z2 -= 0.5 * z3;
  669. z0 = sqrt(2.0);
  670. for (j=1; j <= k ; ++j)
  671. z0 *= sqrt(1.0 - 0.25/(j*j));
  672. return (z0*z2);
  673. }
  674. /* ============================================= */
  675. /* Calculate Derivatives of Legendre Polynomials */
  676. /* ============================================= */
  677. double GauLat::dlp(int k, double p) // After Nodorp (1988)
  678. {
  679. double z0,z3,z4;
  680. if (!k) return 0.0;
  681. z0 = 1.0 / (p*p - 1.0);
  682. z3 = sqrt((k+k+1.0)/(k+k-1.0));
  683. z4 = p * nlp(k,p) - z3 * nlp(k-1,p);
  684. return(k*z0*z4);
  685. }
  686. void GauLat::IniGau(void)
  687. {
  688. int jlat,Iter;
  689. double z0, z1, z2, z3;
  690. double eps=1.e-15;
  691. z0 = M_PI / (2 * Lats + 1);
  692. z1 = 1.0 / (8 * Lats * Lats);
  693. for (jlat=0 ; jlat < Lats/2 ; ++jlat) // North to Equator
  694. {
  695. z2 = (2 * jlat + 1.5) * z0;
  696. z2 = cos(z2 + z1 / tan(z2));
  697. Iter = 0;
  698. do
  699. {
  700. z3 = nlp(Lats,z2) / dlp(Lats,z2);
  701. z2 -= z3;
  702. } while ((z3 < -eps || z3 > eps) && ++Iter < 1000);
  703. gmu[jlat] = z2;
  704. gmu[Lats-1-jlat] = -z2;
  705. }
  706. z1 = 2.0 / (Lats * Lats);
  707. for (jlat=0 ; jlat < Lats/2 ; ++jlat) // North to Equator
  708. {
  709. z0 = nlp(Lats-1,gmu[jlat]) / sqrt(Lats - 0.5);
  710. z0 = z0 * z0;
  711. gwt[jlat] = z1 * (1.0 - gmu[jlat] * gmu[jlat]) / z0;
  712. gwt[Lats-1-jlat] = gwt[jlat];
  713. }
  714. }
  715. RegLon *Outlon;
  716. RegLat *Outlat;
  717. GauLat *Gaulat;
  718. #ifdef NETCDF_OUTPUT
  719. #define TITLE "PUMA/PLASIM DATA"
  720. #define HISTORY "Created by PumaBurner 7.4"
  721. void NetOpen(char *NetFileName)
  722. {
  723. int yy,mm,dd;
  724. int jlev;
  725. int jvar;
  726. int londim;
  727. double *Outlev;
  728. const char *title=TITLE;
  729. const char *conv="CF-1.0";
  730. const char *hist=HISTORY;
  731. char cale[80];
  732. char t_unit[80];
  733. int BaseDate[4];
  734. Outlev = new double[OutLevs];
  735. if (VerType == 's') // sigma
  736. {
  737. for (jlev = 0 ; jlev < OutLevs ; ++jlev)
  738. Outlev[jlev] = 0.5 *
  739. (vct[SigLevs+mol[jlev]]+vct[SigLevs+mol[jlev]+1]);
  740. }
  741. else // pressure levels [hPa]
  742. {
  743. for (jlev = 0 ; jlev < OutLevs ; ++jlev) Outlev[jlev] = hPa[jlev];
  744. }
  745. BaseDate[0] = yy = HeadSt[2] / 10000;
  746. BaseDate[1] = mm = HeadSt[2] / 100 % 100;
  747. BaseDate[2] = dd = HeadSt[2] % 100;
  748. BaseDate[3] = 0;
  749. if (Mean)
  750. {
  751. sprintf(t_unit,"months since %04d-%02d-%02d 00:00:00",yy,mm,dd);
  752. sprintf(cale,"360_day");
  753. }
  754. else
  755. {
  756. sprintf(t_unit,"days since %04d-%02d-%02d 00:00:00",yy,mm,dd);
  757. if (DaysPerYear != 365) sprintf(cale,"%d_day",DaysPerYear);
  758. else sprintf(cale,"proleptic_gregorian");
  759. }
  760. /* Create NetCDF file */
  761. NetFile = new NcFile(NetFileName,NcFile::Replace,NULL,0,NcFile::Offset64Bits);
  762. if (!NetFile->is_valid()) Abort("Could not open NetCDF file");
  763. /* Define dimensions */
  764. if (OutRep == HYB_ZONM || OutRep == PRE_ZONM) londim = 1;
  765. else londim = Lons + Cyclical;
  766. LonDim = NetFile->add_dim("lon" , londim);
  767. LatDim = NetFile->add_dim("lat" , Lats );
  768. LevDim = NetFile->add_dim("lev" , OutLevs );
  769. TimDim = NetFile->add_dim("time" );
  770. LonVar = NetFile->add_var("lon" , ncDouble, LonDim);
  771. LatVar = NetFile->add_var("lat" , ncDouble, LatDim);
  772. LevVar = NetFile->add_var("lev" , ncDouble, LevDim);
  773. TimVar = NetFile->add_var("time", ncDouble, TimDim);
  774. LonVar->add_att("axis" ,"X" );
  775. LonVar->add_att("long_name" ,"longitude" );
  776. LonVar->add_att("standard_name","longitude" );
  777. LonVar->add_att("units" ,"degrees_east" );
  778. LatVar->add_att("axis" ,"Y" );
  779. LatVar->add_att("long_name" ,"latitude" );
  780. LatVar->add_att("standard_name","latitude" );
  781. LatVar->add_att("units" ,"degrees_north");
  782. if (VerType == 's') // sigma level
  783. {
  784. LevVar->add_att("axis" ,"Z" );
  785. LevVar->add_att("long_name" ,"sigma at layer midpoints" );
  786. LevVar->add_att("standard_name","atmosphere_sigma_coordinate");
  787. LevVar->add_att("positive" ,"down" );
  788. LevVar->add_att("units" ,"level" );
  789. }
  790. else // pressure level
  791. {
  792. LevVar->add_att("axis" ,"Z" );
  793. LevVar->add_att("long_name" ,"pressure" );
  794. LevVar->add_att("standard_name","pressure" );
  795. LevVar->add_att("units" ,"hPa" );
  796. }
  797. TimVar->add_att("calendar" ,cale );
  798. TimVar->add_att("units" ,t_unit );
  799. TimVar->add_att("base_date", 4 ,BaseDate );
  800. NetFile->add_att("title" , title);
  801. NetFile->add_att("history" , hist );
  802. NetFile->add_att("Conventions", conv );
  803. for (jvar = 0 ; jvar < nattr ; ++jvar)
  804. {
  805. NetFile->add_att(AttrNam[jvar],AttrVal[jvar]);
  806. }
  807. LonVar->put(Outlon->Lam,londim );
  808. LatVar->put(Outlat->Phi,Lats );
  809. LevVar->put(Outlev ,OutLevs);
  810. }
  811. void NetVarDefine(void)
  812. {
  813. int jvar;
  814. for (jvar = 0 ; jvar < CODES ; ++jvar)
  815. if (All[jvar].selected)
  816. {
  817. if (All[jvar].twod)
  818. {
  819. if (RealSize == 8)
  820. All[jvar].NetVar = NetFile->add_var(All[jvar].Id,ncDouble,TimDim,LatDim,LonDim);
  821. else
  822. All[jvar].NetVar = NetFile->add_var(All[jvar].Id,ncFloat ,TimDim,LatDim,LonDim);
  823. }
  824. else
  825. {
  826. if (RealSize == 8)
  827. All[jvar].NetVar = NetFile->add_var(All[jvar].Id,ncDouble,TimDim,LevDim,LatDim,LonDim);
  828. else
  829. All[jvar].NetVar = NetFile->add_var(All[jvar].Id,ncFloat ,TimDim,LevDim,LatDim,LonDim);
  830. }
  831. All[jvar].NetVar->add_att("long_name" ,All[jvar].Na);
  832. All[jvar].NetVar->add_att("standard_name",All[jvar].Na);
  833. All[jvar].NetVar->add_att("units" ,All[jvar].Un);
  834. All[jvar].NetVar->add_att("code" , jvar );
  835. if (GaussianOutput)
  836. All[jvar].NetVar->add_att("grid_type" ,"gaussian" );
  837. }
  838. }
  839. void NetBuffer(double *d, float *f)
  840. {
  841. for (int jdim = 0 ; jdim < DimGP ; ++jdim) *f++ = *d++;
  842. }
  843. void NetScale(float *f, int dim, double s)
  844. {
  845. int j;
  846. for (j = 0 ; j < dim ; ++j) *f++ *= s;
  847. }
  848. void NetScale(double *f, int dim, double s)
  849. {
  850. int j;
  851. for (j = 0 ; j < dim ; ++j) *f++ *= s;
  852. }
  853. void NetWrite32(int code, double *Var)
  854. {
  855. int jlev;
  856. if (All[code].twod)
  857. {
  858. NetBuffer(Var,Record_float);
  859. if (code==SLPCODE || code==PSCODE)
  860. NetScale(Record_float,Lats*(Lons+Cyclical),0.01);
  861. All[code].NetVar->set_cur(OutputCount);
  862. All[code].NetVar->put(Record_float,1,Lats,Lons+Cyclical);
  863. }
  864. else
  865. {
  866. for (jlev = 0 ; jlev < OutLevs ; ++jlev, Var += DimGP)
  867. {
  868. NetBuffer(Var,Record_float);
  869. if (code==WCODE)
  870. NetScale(Record_float,Lats*(Lons+Cyclical),0.01);
  871. All[code].NetVar->set_cur(OutputCount,jlev);
  872. All[code].NetVar->put(Record_float,1,1,Lats,Lons+Cyclical);
  873. }
  874. }
  875. }
  876. void NetWrite64(int code, double *Var)
  877. {
  878. int jlev;
  879. if (All[code].twod)
  880. {
  881. memcpy(Record_double,Var,DimGP * sizeof(double));
  882. if (code==SLPCODE || code==PSCODE)
  883. NetScale(Record_double,Lats*(Lons+Cyclical),0.01);
  884. All[code].NetVar->set_cur(OutputCount);
  885. All[code].NetVar->put(Record_double,1,Lats,Lons+Cyclical);
  886. }
  887. else
  888. {
  889. for (jlev = 0 ; jlev < OutLevs ; ++jlev, Var += DimGP)
  890. {
  891. memcpy(Record_double,Var,DimGP * sizeof(double));
  892. if (code==WCODE)
  893. NetScale(Record_double,Lats*(Lons+Cyclical),0.01);
  894. All[code].NetVar->set_cur(OutputCount,jlev);
  895. All[code].NetVar->put(Record_double,1,1,Lats,Lons+Cyclical);
  896. }
  897. }
  898. }
  899. void NetWriteSection(int code, double *Var)
  900. {
  901. int jvar,jlev;
  902. double *vp;
  903. for (jlev = 0 ; jlev < OutLevs ; ++jlev)
  904. {
  905. vp = Var + jlev * DimFC;
  906. if (code==SLPCODE || code==PSCODE || code==WCODE)
  907. {
  908. for (jvar = 0 ; jvar < Lats ; ++jvar)
  909. {
  910. Record_float[jvar] = vp[jvar] * 0.01;
  911. }
  912. }
  913. else
  914. {
  915. for (jvar = 0 ; jvar < Lats ; ++jvar)
  916. {
  917. Record_float[jvar] = vp[jvar];
  918. }
  919. }
  920. All[code].NetVar->set_cur(OutputCount,jlev);
  921. All[code].NetVar->put(Record_float,1,1,Lats,1);
  922. }
  923. }
  924. void NetClose(void)
  925. {
  926. int jt;
  927. double * Outtim;
  928. Outtim = new double[OutputCount];
  929. for (jt = 0 ; jt < OutputCount ; jt++) Outtim[jt] = jt;
  930. if (Mean == 0 && (DataStep < 0.99999 || DataStep > 1.00001))
  931. for (jt = 0 ; jt < OutputCount ; jt++) Outtim[jt] *= DataStep;
  932. TimVar->put(Outtim,OutputCount);
  933. delete Outtim;
  934. delete NetFile;
  935. }
  936. #endif
  937. class ServiceGrid
  938. {
  939. int HeadControl;
  940. FILE *File;
  941. float *FloatBuffer;
  942. public:
  943. int h4; // head[4] = 1st dimension
  944. int h5; // head[5] = 2nd dimension
  945. int Dim; // total dimension
  946. int FieldControl;
  947. ServiceGrid(FILE *, int, int);
  948. ~ServiceGrid(void);
  949. void Write(int *, double *);
  950. void WriteCode(int code, double *field, int twod);
  951. void Write_hspec(void);
  952. void Write_pspec(void);
  953. void Write_hfour(void);
  954. void Write_pfour(void);
  955. void Write_hgrid(void);
  956. void Write_pgrid(void);
  957. void Clear_hspec(void);
  958. void Clear_pspec(void);
  959. void Clear_hfour(void);
  960. void Clear_pfour(void);
  961. void Clear_hgrid(void);
  962. void Clear_pgrid(void);
  963. };
  964. ServiceGrid::ServiceGrid(FILE *fd, int Dim1, int Dim2)
  965. {
  966. h4 = Dim1;
  967. h5 = Dim2;
  968. Dim = Dim1 * Dim2;
  969. HeadControl = 8 * RealSize;
  970. FieldControl = Dim * RealSize;
  971. File = fd;
  972. FloatBuffer = new float[Dim];
  973. }
  974. ServiceGrid::~ServiceGrid(void)
  975. {
  976. delete FloatBuffer;
  977. }
  978. void ServiceGrid::Write(int *Head, double *Array)
  979. {
  980. int i,j;
  981. LONG lhc,lfc;
  982. if (Debug) // Check for NaN (Not A Number)
  983. {
  984. for (j=0 ; j<Dim ; ++j)
  985. {
  986. if (isnan(Array[j]))
  987. {
  988. printf("\n Head: ");
  989. for (i=0 ; i<6 ; i++) printf(" %d",Head[i]);
  990. printf("\n Array[%d] = NaN\n",j);
  991. exit(1);
  992. }
  993. }
  994. }
  995. if (RealSize == 4)
  996. {
  997. for (j=0 ; j<Dim ; ++j) FloatBuffer[j] = Array[j];
  998. if (LongFCW)
  999. {
  1000. lhc = HeadControl;
  1001. lfc = FieldControl;
  1002. fwrite(&lhc ,sizeof(lhc) ,1 ,File);
  1003. fwrite( Head ,sizeof(int) ,8 ,File);
  1004. fwrite(&lhc ,sizeof(lhc) ,1 ,File);
  1005. fwrite(&lfc ,sizeof(lfc) ,1 ,File);
  1006. fwrite( FloatBuffer,sizeof(float),Dim,File);
  1007. fwrite(&lfc ,sizeof(lfc) ,1 ,File);
  1008. }
  1009. else
  1010. {
  1011. fwrite(&HeadControl ,sizeof(int) ,1 ,File);
  1012. fwrite( Head ,sizeof(int) ,8 ,File);
  1013. fwrite(&HeadControl ,sizeof(int) ,1 ,File);
  1014. fwrite(&FieldControl,sizeof(int) ,1 ,File);
  1015. fwrite( FloatBuffer ,sizeof(float),Dim,File);
  1016. fwrite(&FieldControl,sizeof(int) ,1 ,File);
  1017. }
  1018. }
  1019. else // RealSize == 8
  1020. {
  1021. if (LongFCW)
  1022. {
  1023. lhc = HeadControl;
  1024. lfc = FieldControl;
  1025. fwrite(&lhc ,sizeof(lhc) ,1 ,File);
  1026. fwrite( Head ,sizeof(int) ,8 ,File);
  1027. fwrite(&lhc ,sizeof(lhc) ,1 ,File);
  1028. fwrite(&lfc ,sizeof(lfc) ,1 ,File);
  1029. fwrite( Array ,sizeof(double),Dim,File);
  1030. fwrite(&lfc ,sizeof(lfc) ,1 ,File);
  1031. }
  1032. else
  1033. {
  1034. long LongHead[8];
  1035. for (int i=0 ; i<8 ; ++i) LongHead[i] = Head[i];
  1036. fwrite(&HeadControl ,sizeof(int) ,1 ,File);
  1037. fwrite( LongHead ,RealSize ,8 ,File);
  1038. fwrite(&HeadControl ,sizeof(int) ,1 ,File);
  1039. fwrite(&FieldControl,sizeof(int) ,1 ,File);
  1040. fwrite( Array ,RealSize ,Dim,File);
  1041. fwrite(&FieldControl,sizeof(int) ,1 ,File);
  1042. }
  1043. }
  1044. }
  1045. void ServiceGrid::WriteCode(int code, double *field, int twod)
  1046. {
  1047. int jlev;
  1048. if (field == NULL)
  1049. {
  1050. fprintf(stderr, "*** Error in ServiceGrid::WriteCode\n");
  1051. fprintf(stderr, " Code %d not defined for this OutRep\n",code);
  1052. fprintf(stderr, " Skipping this record\n\n");
  1053. return;
  1054. }
  1055. HeadOu[0] = code;
  1056. HeadOu[4] = h4;
  1057. HeadOu[5] = h5;
  1058. if (twod)
  1059. {
  1060. HeadOu[1] = 0;
  1061. HeadOu[7] = 0;
  1062. Write(&HeadOu[0],field);
  1063. }
  1064. else for (jlev = 0; jlev < OutLevs; jlev++)
  1065. {
  1066. HeadOu[1] = LevelUnits[jlev];
  1067. HeadOu[7] = SigmaF[jlev];
  1068. Write(&HeadOu[0], field + jlev * Dim);
  1069. }
  1070. }
  1071. void ServiceGrid::Write_hspec(void)
  1072. {
  1073. for (int code = 0; code < CODES; code++)
  1074. if (All[code].selected)
  1075. WriteCode(code,&All[code].hsp[0],All[code].twod);
  1076. }
  1077. void ServiceGrid::Write_pspec(void)
  1078. {
  1079. for (int code = 0; code < CODES; code++)
  1080. if (All[code].selected)
  1081. WriteCode(code,&All[code].psp[0],All[code].twod);
  1082. }
  1083. void ServiceGrid::Clear_hspec(void)
  1084. {
  1085. for (int code = CODES-1 ; code >= 0 ; --code)
  1086. if (All[code].hsp.size() && !All[code].twod)
  1087. {
  1088. if (Debug)
  1089. {
  1090. char tb[COLS];
  1091. sprintf(tb,"Clear: %p %6s[%3d].hsp",
  1092. &All[code].hsp[0],All[code].Id,code);
  1093. LeftText(tb);
  1094. }
  1095. All[code].hsp.resize(0);
  1096. }
  1097. }
  1098. void ServiceGrid::Clear_hfour(void)
  1099. {
  1100. for (int code = CODES-1 ; code >= 0 ; --code)
  1101. if (All[code].hfc.size() && !All[code].twod)
  1102. {
  1103. if (Debug)
  1104. {
  1105. char tb[COLS];
  1106. sprintf(tb,"CLear: %p %6s[%3d].hfc",&All[code].hfc[0],All[code].Id,code);
  1107. LeftText(tb);
  1108. }
  1109. All[code].hfc.resize(0);
  1110. }
  1111. }
  1112. void ServiceGrid::Clear_hgrid(void)
  1113. {
  1114. for (int code = CODES-1 ; code >= 0 ; --code)
  1115. if (All[code].hgp.size())
  1116. {
  1117. if (Debug)
  1118. {
  1119. char tb[COLS];
  1120. sprintf(tb,"CLear: %p %6s[%3d].hgp",&All[code].hgp[0],All[code].Id,code);
  1121. LeftText(tb);
  1122. }
  1123. All[code].hgp.resize(0);
  1124. }
  1125. }
  1126. void ServiceGrid::Clear_pgrid(void)
  1127. {
  1128. for (int code = CODES-1 ; code >= 0 ; --code)
  1129. if (All[code].pgp.size())
  1130. {
  1131. if (Debug)
  1132. {
  1133. char tb[COLS];
  1134. sprintf(tb,"CLear: %p %6s[%3d].pgp",&All[code].pgp[0],All[code].Id,code);
  1135. LeftText(tb);
  1136. }
  1137. All[code].pgp.resize(0);
  1138. }
  1139. }
  1140. void ServiceGrid::Clear_pfour(void)
  1141. {
  1142. for (int code = CODES-1 ; code >= 0 ; --code)
  1143. if (All[code].pfc.size())
  1144. {
  1145. if (Debug)
  1146. {
  1147. char tb[COLS];
  1148. sprintf(tb,"CLear: %p %6s[%3d].pfc",&All[code].pfc[0],All[code].Id,code);
  1149. LeftText(tb);
  1150. }
  1151. All[code].pfc.resize(0);
  1152. }
  1153. }
  1154. void ServiceGrid::Clear_pspec(void)
  1155. {
  1156. for (int code = CODES-1 ; code >= 0 ; --code)
  1157. if (All[code].psp.size())
  1158. {
  1159. if (Debug)
  1160. {
  1161. char tb[COLS];
  1162. sprintf(tb,"CLear: %p %6s[%3d].psp",&All[code].psp[0],All[code].Id,code);
  1163. LeftText(tb);
  1164. }
  1165. All[code].psp.resize(0);
  1166. }
  1167. }
  1168. void ServiceGrid::Write_hfour(void)
  1169. {
  1170. int code;
  1171. for (code = 0; code < CODES; code++)
  1172. if (All[code].selected)
  1173. WriteCode(code,&All[code].hfc[0],All[code].twod);
  1174. }
  1175. void ServiceGrid::Write_pfour(void)
  1176. {
  1177. int code;
  1178. for (code = 0; code < CODES; code++)
  1179. if (All[code].selected)
  1180. WriteCode(code,&All[code].pfc[0],All[code].twod);
  1181. }
  1182. void ServiceGrid::Write_hgrid(void)
  1183. {
  1184. int code;
  1185. for (code = 0; code < CODES; code++)
  1186. if (All[code].selected)
  1187. {
  1188. if (All[code].hgp.size() == 0)
  1189. {
  1190. fprintf(stderr, "*** Error in ServiceGrid::Write_hgrid\n");
  1191. fprintf(stderr, " Code %d is not available on sigma level\n",code);
  1192. fprintf(stderr, " Skipping this record\n\n");
  1193. return;
  1194. }
  1195. #ifdef NETCDF_OUTPUT
  1196. if (NetCDF)
  1197. {
  1198. if (RealSize == 8) NetWrite64(code,&All[code].hgp[0]);
  1199. else NetWrite32(code,&All[code].hgp[0]);
  1200. }
  1201. else
  1202. #endif
  1203. WriteCode(code,&All[code].hgp[0],All[code].twod);
  1204. }
  1205. OutputCount++;
  1206. }
  1207. void ServiceGrid::Write_pgrid(void)
  1208. {
  1209. int code;
  1210. for (code = 0; code < CODES; code++)
  1211. if (All[code].selected)
  1212. {
  1213. #ifdef NETCDF_OUTPUT
  1214. if (NetCDF)
  1215. {
  1216. if (RealSize == 8) NetWrite64(code,&All[code].pgp[0]);
  1217. else NetWrite32(code,&All[code].pgp[0]);
  1218. }
  1219. else
  1220. #endif
  1221. WriteCode(code,&All[code].pgp[0],All[code].twod);
  1222. }
  1223. OutputCount++;
  1224. }
  1225. class ServiceSect : public ServiceGrid
  1226. {
  1227. double *Buffer;
  1228. public:
  1229. ServiceSect(FILE *, int, int);
  1230. ~ServiceSect(void);
  1231. void WriteCode(int code, double *field, int twod);
  1232. void Write_hfour(void);
  1233. void Write_pfour(void);
  1234. };
  1235. ServiceSect::ServiceSect(FILE *fd, int Dim1, int Dim2) :
  1236. ServiceGrid(fd,Dim1,Dim2)
  1237. {
  1238. Buffer = new double[Dim1*Dim2];
  1239. }
  1240. ServiceSect::~ServiceSect(void)
  1241. {
  1242. delete Buffer;
  1243. }
  1244. void ServiceSect::WriteCode(int code, double *field, int twod)
  1245. {
  1246. int jlev;
  1247. HeadOu[0] = code;
  1248. HeadOu[1] = -1;
  1249. HeadOu[7] = 0;
  1250. if (twod)
  1251. {
  1252. h5 = 1;
  1253. memcpy(Buffer,field,Lats * sizeof(double));
  1254. }
  1255. else
  1256. {
  1257. h5 = OutLevs;
  1258. for (jlev=0 ; jlev < OutLevs ; ++jlev)
  1259. memcpy(Buffer+jlev*Lats,field+jlev*DimFC,Lats*sizeof(double));
  1260. }
  1261. HeadOu[4] = h4;
  1262. HeadOu[5] = h5;
  1263. Dim = h4 * h5;
  1264. FieldControl = Dim * sizeof(float);
  1265. Write(&HeadOu[0],Buffer);
  1266. }
  1267. void ServiceSect::Write_hfour(void)
  1268. {
  1269. int code;
  1270. for (code = 0; code < CODES; code++)
  1271. if (All[code].selected)
  1272. {
  1273. #ifdef NETCDF_OUTPUT
  1274. if (NetCDF)
  1275. NetWriteSection(code,&All[code].hfc[0]);
  1276. else
  1277. #endif
  1278. WriteCode(code,&All[code].hfc[0],All[code].twod);
  1279. }
  1280. OutputCount++;
  1281. }
  1282. void ServiceSect::Write_pfour(void)
  1283. {
  1284. int code;
  1285. for (code = 0; code < CODES; code++)
  1286. if (All[code].selected)
  1287. {
  1288. #ifdef NETCDF_OUTPUT
  1289. if (NetCDF)
  1290. NetWriteSection(code,&All[code].pfc[0]);
  1291. else
  1292. #endif
  1293. WriteCode(code,&All[code].pfc[0],All[code].twod);
  1294. }
  1295. OutputCount++;
  1296. }
  1297. ServiceGrid *HybSpec;
  1298. ServiceGrid *HybFour;
  1299. ServiceGrid *HybGrid;
  1300. ServiceSect *HybSect;
  1301. void HeadToDate(vector<int>Head, struct tm *Date)
  1302. {
  1303. Date->tm_year = Head[2] / 10000;
  1304. Date->tm_mon = Head[2] / 100 % 100;
  1305. Date->tm_mday = Head[2] % 100;
  1306. Date->tm_hour = Head[3] / 100;
  1307. Date->tm_min = Head[3] % 100;
  1308. }
  1309. /* ============================================== */
  1310. /* DoubleZero - Set array of type double to zero */
  1311. /* ============================================== */
  1312. inline void DoubleZero(double *field, int words)
  1313. {
  1314. memset((char *)field,0,words * sizeof(double));
  1315. }
  1316. /* ====================== */
  1317. /* Fast Fourier Transform */
  1318. /* ====================== */
  1319. /* constants in math.h :
  1320. #define M_E 2.71828182845904523536
  1321. #define M_LOG2E 1.44269504088896340736
  1322. #define M_LOG10E 0.434294481903251827651
  1323. #define M_LN2 0.693147180559945309417
  1324. #define M_LN10 2.30258509299404568402
  1325. #define M_PI 3.14159265358979323846
  1326. #define M_PI_2 1.57079632679489661923
  1327. #define M_PI_4 0.785398163397448309616
  1328. #define M_1_PI 0.318309886183790671538
  1329. #define M_2_PI 0.636619772367581343076
  1330. #define M_1_SQRTPI 0.564189583547756286948
  1331. #define M_2_SQRTPI 1.12837916709551257390
  1332. #define M_SQRT2 1.41421356237309504880
  1333. #define M_SQRT_2 0.707106781186547524401
  1334. */
  1335. #define QUA 0.25
  1336. #define QT5 0.559016994374947
  1337. #define S36 0.587785252292473
  1338. #define S60 0.866025403784437
  1339. #define S72 0.951056516295154
  1340. #define SQ2 0.707106781186547524401
  1341. #define D60 (S60+S60)
  1342. #define FORK for(k=la;k<=kstop;k+=la){
  1343. #define LOOP for(l=0;l<la;++l){i=ibase;j=jbase;for(ijk=0;ijk<lot;++ijk){
  1344. #define ENDL i+=inc3;j+=inc4;}ibase++;jbase++;}
  1345. void fft_set(int n)
  1346. {
  1347. int j,k,nfax;
  1348. nfax = 0;
  1349. for (k = 0; k < 9; ++k) ifax[k] = 0;
  1350. ifax[9] = n;
  1351. if (n % 8 == 0) {ifax[++nfax] = 8; n /= 8;}
  1352. while (n % 6 == 0) {ifax[++nfax] = 6; n /= 6;}
  1353. while (n % 5 == 0) {ifax[++nfax] = 5; n /= 5;}
  1354. while (n % 4 == 0) {ifax[++nfax] = 4; n /= 4;}
  1355. while (n % 3 == 0) {ifax[++nfax] = 3; n /= 3;}
  1356. if (n % 2 == 0) {ifax[++nfax] = 2; n /= 2;}
  1357. ifax[0] = nfax;
  1358. for (k = 0; k < nfax/2; ++k)
  1359. {
  1360. j = ifax[k+1];
  1361. ifax[k+1] = ifax[nfax-k];
  1362. ifax[nfax-k] = j;
  1363. }
  1364. }
  1365. int rpassc(double *a, double *b, double *c, double *d,
  1366. int inc3, int inc4,
  1367. int lot , int n , int ifac, int la )
  1368. {
  1369. /*
  1370. rpassc' - performs one pass through data as part;
  1371. of multiple real fft (fourier synthesis) routine;
  1372. a is first real input vector
  1373. b is equivalent to a + la
  1374. c is first real output vector
  1375. d is equivalent to c + ifac * la
  1376. inc3 is the increment between input vectors a;
  1377. inc4 is the increment between output vectors c;
  1378. lot is the number of vectors;
  1379. n is the length of the vectors;
  1380. ifac is the current factor of n;
  1381. la is the product of previous factors;
  1382. ierr is an error indicator:;
  1383. 0 - pass completed without error;
  1384. 2 - ifac not catered for;
  1385. 3 - ifac only catered for if la=n/ifac;
  1386. */
  1387. int i0,i1,i2,i3,i4,i5,i6,i7;
  1388. int j0,j1,j2,j3,j4,j5,j6,j7;
  1389. int ia,ib,ic,id,ie,iF;
  1390. int ja,jb,jc,jd,je,jf;
  1391. int i,j,k,ijk,l,m;
  1392. int ibase,jbase;
  1393. int iink,jink;
  1394. int jump;
  1395. int kstop;
  1396. double c1,c2,c3,c4,c5;
  1397. double s1,s2,s3,s4,s5;
  1398. double kpidn;
  1399. double angle;
  1400. double qqrt5;
  1401. double ssin36;
  1402. double ssin72;
  1403. double pin;
  1404. double a10,a11,a20,a21;
  1405. double b10,b11,b20,b21;
  1406. m = n / ifac;
  1407. iink = la;
  1408. jink = la;
  1409. jump = (ifac-1) * jink;
  1410. kstop = (n-ifac) / (2*ifac);
  1411. pin = 2.0 * M_PI / n;
  1412. ibase = 0;
  1413. jbase = 0;
  1414. switch (ifac)
  1415. {
  1416. case 2:
  1417. {
  1418. double a0m1,b0p1;
  1419. i0 = j0 = 0;
  1420. i1 = i0 + (m+m-la);
  1421. j1 = j0 + jink;
  1422. if (la != m)
  1423. {
  1424. LOOP
  1425. c[j0+j] = a[i0+i] + a[i1+i];
  1426. c[j1+j] = a[i0+i] - a[i1+i];
  1427. ENDL
  1428. i0 += iink;
  1429. iink += iink;
  1430. i1 -= iink;
  1431. ibase = 0;
  1432. jbase += jump;
  1433. jump += jump + jink;
  1434. if (i0 != i1)
  1435. {
  1436. FORK
  1437. angle = k * pin;
  1438. c1 = cos(angle);
  1439. s1 = sin(angle);
  1440. ibase = 0;
  1441. LOOP
  1442. a0m1 = a[i0+i] - a[i1+i];
  1443. b0p1 = b[i0+i] + b[i1+i];
  1444. c[j0+j] = a[i0+i] + a[i1+i];
  1445. d[j0+j] = b[i0+i] - b[i1+i];
  1446. c[j1+j] = c1 * a0m1 - s1 * b0p1;
  1447. d[j1+j] = s1 * a0m1 + c1 * b0p1;
  1448. ENDL
  1449. i0 += iink;
  1450. i1 -= iink;
  1451. jbase += jump;
  1452. } /* End FORK */
  1453. if (i0 > i1) return 0;
  1454. } /* End (i0 != i1) */
  1455. ibase = 0;
  1456. LOOP
  1457. c[j0+j] = a[i0+i];
  1458. c[j1+j] = -b[i0+i];
  1459. ENDL
  1460. }
  1461. else /* (la != m) */ {
  1462. LOOP
  1463. c[j0+j] = 2.0 * (a[i0+i] + a[i1+i]);
  1464. c[j1+j] = 2.0 * (a[i0+i] - a[i1+i]);
  1465. ENDL
  1466. }
  1467. return 0;
  1468. }
  1469. case 3: {
  1470. double afa1,a1p2,a1m2,a0mm,a0mp;
  1471. double bfa1,b1p2,b1m2,b0mm,b0mp;
  1472. i0 = j0 = 0 ;
  1473. i1 = i0 + (m+m-la);
  1474. i2 = i1;
  1475. j1 = j0 + jink;
  1476. j2 = j1 + jink;
  1477. if (la != m) {
  1478. LOOP
  1479. afa1 = a[i0+i] - 0.5 * a[i1+i];
  1480. bfa1 = S60 * b[i1+i];
  1481. c[j0+j] = a[i0+i] + a[i1+i];
  1482. c[j1+j] = afa1 - bfa1;
  1483. c[j2+j] = afa1 + bfa1;
  1484. ENDL
  1485. i0 += iink;
  1486. iink += iink;
  1487. i1 += iink;
  1488. i2 -= iink;
  1489. jbase += jump;
  1490. jump += jump + jink;
  1491. if (i0 != i2) {
  1492. FORK
  1493. angle = k * pin;
  1494. c1 = cos(angle);
  1495. s1 = sin(angle);
  1496. angle += angle;
  1497. c2 = cos(angle);
  1498. s2 = sin(angle);
  1499. ibase = 0;
  1500. LOOP
  1501. a1p2 = a[i0+i] - 0.5 * (a[i1+i] + a[i2+i]);
  1502. b1m2 = b[i0+i] - 0.5 * (b[i1+i] - b[i2+i]);
  1503. a1m2 = S60 * (a[i1+i] - a[i2+i]);
  1504. b1p2 = S60 * (b[i1+i] + b[i2+i]);
  1505. a0mm = a1p2 - b1p2;
  1506. a0mp = a1p2 + b1p2;
  1507. b0mm = b1m2 - a1m2;
  1508. b0mp = b1m2 + a1m2;
  1509. c[j0+j] = a[i0+i] + a[i1+i] + a[i2+i];
  1510. d[j0+j] = b[i0+i] + b[i1+i] - b[i2+i];
  1511. c[j1+j] = c1 * a0mm - s1 * b0mp;
  1512. d[j1+j] = s1 * a0mm + c1 * b0mp;
  1513. c[j2+j] = c2 * a0mp - s2 * b0mm;
  1514. d[j2+j] = s2 * a0mp + c2 * b0mm;
  1515. ENDL
  1516. i0 += iink;
  1517. i1 += iink;
  1518. i2 -= iink;
  1519. jbase += jump;
  1520. } /* End FORK */
  1521. if (i0 > i2) return 0;
  1522. } /* End (i0 != i2) */
  1523. ibase=0;
  1524. LOOP
  1525. a0mp = 0.5 * a[i0+i];
  1526. b0mp = S60 * b[i0+i];
  1527. c[j0+j] = a[i0+i] + a[i1+i];
  1528. c[j1+j] = a0mp - a[i1+i] - b0mp;
  1529. c[j2+j] = a[i1+i] - a0mp - b0mp;
  1530. ENDL
  1531. }
  1532. else /* (la != m) */ {
  1533. LOOP
  1534. a0mp = 2.0 * a[i0+i] - a[i1+i];
  1535. b0mp = D60 * b[i1+i];
  1536. c[j0+j] = 2.0 * (a[i0+i] + a[i1+i]);
  1537. c[j1+j] = a0mp - b0mp;
  1538. c[j2+j] = a0mp + b0mp;
  1539. ENDL
  1540. }
  1541. return 0;
  1542. }
  1543. case 4: {
  1544. double a0m1,a0p2,a1p3,a0m2,a1m3,a0p2ma1p3,a0m2pb1p3,a0m2mb1p3;
  1545. double b0p1,b0p2,b1p3,b0m2,b1m3,b0p2pa1m3,b0p2ma1m3,b0m2mb1m3;
  1546. i0 = j0 = 0;
  1547. i1 = i3 = i0 + (m+m-la);
  1548. i2 = i1 + (m+m);
  1549. j1 = j0 + jink;
  1550. j2 = j1 + jink;
  1551. j3 = j2 + jink;
  1552. if (la != m) {
  1553. LOOP
  1554. a0p2 = a[i0+i] + a[i2+i];
  1555. a0m2 = a[i0+i] - a[i2+i];
  1556. c[j0+j] = a0p2 + a[i1+i];
  1557. c[j1+j] = a0m2 - b[i1+i];
  1558. c[j2+j] = a0p2 - a[i1+i];
  1559. c[j3+j] = a0m2 + b[i1+i];
  1560. ENDL
  1561. i0 += iink;
  1562. iink += iink;
  1563. i1 += iink;
  1564. i2 -= iink;
  1565. i3 -= iink;
  1566. jbase += jump;
  1567. jump += jump + jink;
  1568. if (i1 != i2) {
  1569. FORK
  1570. angle = kpidn = k * pin;
  1571. c1 = cos(angle);
  1572. s1 = sin(angle);
  1573. angle += kpidn;
  1574. c2 = cos(angle);
  1575. s2 = sin(angle);
  1576. angle += kpidn;
  1577. c3 = cos(angle);
  1578. s3 = sin(angle);
  1579. ibase=0;
  1580. LOOP
  1581. a0p2 = a[i0+i] + a[i2+i];
  1582. a0m2 = a[i0+i] - a[i2+i];
  1583. a1p3 = a[i1+i] + a[i3+i];
  1584. a1m3 = a[i1+i] - a[i3+i];
  1585. b0p2 = b[i0+i] + b[i2+i];
  1586. b0m2 = b[i0+i] - b[i2+i];
  1587. b1p3 = b[i1+i] + b[i3+i];
  1588. b1m3 = b[i1+i] - b[i3+i];
  1589. a0p2ma1p3 = a0p2 - a1p3;
  1590. a0m2pb1p3 = a0m2 + b1p3;
  1591. a0m2mb1p3 = a0m2 - b1p3;
  1592. b0p2pa1m3 = b0p2 + a1m3;
  1593. b0p2ma1m3 = b0p2 - a1m3;
  1594. b0m2mb1m3 = b0m2 - b1m3;
  1595. c[j0+j] = a0p2 + a1p3;
  1596. d[j0+j] = b0m2 + b1m3;
  1597. c[j2+j] = c2 * a0p2ma1p3 - s2 * b0m2mb1m3;
  1598. d[j2+j] = s2 * a0p2ma1p3 + c2 * b0m2mb1m3;
  1599. c[j1+j] = c1 * a0m2mb1p3 - s1 * b0p2pa1m3;
  1600. d[j1+j] = s1 * a0m2mb1p3 + c1 * b0p2pa1m3;
  1601. c[j3+j] = c3 * a0m2pb1p3 - s3 * b0p2ma1m3;
  1602. d[j3+j] = s3 * a0m2pb1p3 + c3 * b0p2ma1m3;
  1603. ENDL
  1604. i0 += iink;
  1605. i1 += iink;
  1606. i2 -= iink;
  1607. i3 -= iink;
  1608. jbase += jump;
  1609. } /* End FORK */
  1610. if (i1 > i2) return 0;
  1611. } /* End (i1 != i2) */
  1612. ibase=0;
  1613. LOOP
  1614. a0m1 = a[i0+i] - a[i1+i];
  1615. b0p1 = b[i0+i] + b[i1+i];
  1616. c[j0+j] = a[i0+i] + a[i1+i];
  1617. c[j2+j] = b[i1+i] - b[i0+i];
  1618. c[j1+j] = SQ2 * (a0m1 - b0p1);
  1619. c[j3+j] = -SQ2 * (a0m1 + b0p1);
  1620. ENDL
  1621. }
  1622. else /* (la != m) */ {
  1623. LOOP
  1624. a0p2 = a[i0+i] + a[i2+i];
  1625. a0m2 = a[i0+i] - a[i2+i];
  1626. c[j0+j] = 2.0 * (a0p2 + a[i1+i]);
  1627. c[j1+j] = 2.0 * (a0m2 - b[i1+i]);
  1628. c[j2+j] = 2.0 * (a0p2 - a[i1+i]);
  1629. c[j3+j] = 2.0 * (a0m2 + b[i1+i]);
  1630. ENDL
  1631. }
  1632. return 0;
  1633. }
  1634. case 5: {
  1635. double a1p2,a1m2,a0mm,a0mp,b136,b172,b236,b272;
  1636. i0 = j0 = 0;
  1637. i1 = i4 = i0 + (m+m-la);
  1638. i2 = i3 = i1 + (m+m);
  1639. j1 = j0 + jink;
  1640. j2 = j1 + jink;
  1641. j3 = j2 + jink;
  1642. j4 = j3 + jink;
  1643. if (la != m) {
  1644. LOOP
  1645. a1p2 = QUA * (a[i1+i] + a[i2+i]);
  1646. a1m2 = QT5 * (a[i1+i] - a[i2+i]);
  1647. a0mp = a[i0+i] - a1p2 + a1m2;
  1648. a0mm = a[i0+i] - a1p2 - a1m2;
  1649. b136 = b[i1+i] * S36;
  1650. b172 = b[i1+i] * S72;
  1651. b236 = b[i2+i] * S36;
  1652. b272 = b[i2+i] * S72;
  1653. c[j0+j] = a[i0+i] + a[i1+i] + a[i2+i];
  1654. c[j1+j] = a0mp - b172 - b236;
  1655. c[j2+j] = a0mm - b136 + b272;
  1656. c[j3+j] = a0mm + b136 - b272;
  1657. c[j4+j] = a0mp + b172 + b236;
  1658. ENDL
  1659. i0 += iink;
  1660. iink += iink;
  1661. i1 += iink;
  1662. i2 += iink;
  1663. i3 -= iink;
  1664. i4 -= iink;
  1665. jbase += jump;
  1666. jump += jump + jink;
  1667. if (i1 != i3) {
  1668. FORK
  1669. angle = kpidn = k * pin;
  1670. c1 = cos(angle);
  1671. s1 = sin(angle);
  1672. angle += kpidn;
  1673. c2 = cos(angle);
  1674. s2 = sin(angle);
  1675. angle += kpidn;
  1676. c3 = cos(angle);
  1677. s3 = sin(angle);
  1678. angle += kpidn;
  1679. c4 = cos(angle);
  1680. s4 = sin(angle);
  1681. ibase=0;
  1682. LOOP
  1683. a10=(a[i0+i]-0.25*((a[i1+i]+a[i4+i])+(a[i2+i]+a[i3+i])))
  1684. +QT5*((a[i1+i]+a[i4+i])-(a[i2+i]+a[i3+i]));
  1685. a20=(a[i0+i]-0.25*((a[i1+i]+a[i4+i])+(a[i2+i]+a[i3+i])))
  1686. -QT5*((a[i1+i]+a[i4+i])-(a[i2+i]+a[i3+i]));
  1687. b10=(b[i0+i]-0.25*((b[i1+i]-b[i4+i])+(b[i2+i]-b[i3+i])))
  1688. +QT5*((b[i1+i]-b[i4+i])-(b[i2+i]-b[i3+i]));
  1689. b20=(b[i0+i]-0.25*((b[i1+i]-b[i4+i])+(b[i2+i]-b[i3+i])))
  1690. -QT5*((b[i1+i]-b[i4+i])-(b[i2+i]-b[i3+i]));
  1691. a11=S72*(b[i1+i]+b[i4+i])+S36*(b[i2+i]+b[i3+i]);
  1692. a21=S36*(b[i1+i]+b[i4+i])-S72*(b[i2+i]+b[i3+i]);
  1693. b11=S72*(a[i1+i]-a[i4+i])+S36*(a[i2+i]-a[i3+i]);
  1694. b21=S36*(a[i1+i]-a[i4+i])-S72*(a[i2+i]-a[i3+i]);
  1695. c[j0+j]=a[i0+i]+((a[i1+i]+a[i4+i])+(a[i2+i]+a[i3+i]));
  1696. d[j0+j]=b[i0+i]+((b[i1+i]-b[i4+i])+(b[i2+i]-b[i3+i]));
  1697. c[j1+j]=c1*(a10-a11)-s1*(b10+b11);
  1698. d[j1+j]=s1*(a10-a11)+c1*(b10+b11);
  1699. c[j4+j]=c4*(a10+a11)-s4*(b10-b11);
  1700. d[j4+j]=s4*(a10+a11)+c4*(b10-b11);
  1701. c[j2+j]=c2*(a20-a21)-s2*(b20+b21);
  1702. d[j2+j]=s2*(a20-a21)+c2*(b20+b21);
  1703. c[j3+j]=c3*(a20+a21)-s3*(b20-b21);
  1704. d[j3+j]=s3*(a20+a21)+c3*(b20-b21);
  1705. ENDL
  1706. i0 += iink;
  1707. i1 += iink;
  1708. i2 += iink;
  1709. i3 -= iink;
  1710. i4 -= iink;
  1711. jbase += jump;
  1712. } /* End FORK */
  1713. if (i1 > i3) return 0;
  1714. } /* End (i1 != i3) */
  1715. ibase=0;
  1716. LOOP
  1717. c[j0+j] = a[i0+i] + a[i1+i] + a[i2+i];
  1718. c[j1+j] = (QT5 * (a[i0+i]-a[i1+i])
  1719. + (0.25 * (a[i0+i]+a[i1+i])-a[i2+i]))
  1720. - (S36 * b[i0+i]+S72*b[i1+i]);
  1721. c[j4+j] =-(QT5 * (a[i0+i]-a[i1+i])
  1722. + (0.25 * (a[i0+i]+a[i1+i])-a[i2+i]))
  1723. - (S36 * b[i0+i]+S72*b[i1+i]);
  1724. c[j2+j] = (QT5 * (a[i0+i]-a[i1+i])
  1725. - (0.25 * (a[i0+i]+a[i1+i])-a[i2+i]))
  1726. - (S72 * b[i0+i]-S36*b[i1+i]);
  1727. c[j3+j] =-(QT5 * (a[i0+i]-a[i1+i])
  1728. - (0.25 * (a[i0+i]+a[i1+i])-a[i2+i]))
  1729. - (S72 * b[i0+i]-S36*b[i1+i]);
  1730. ENDL
  1731. } else {
  1732. qqrt5 = 2.0 * QT5 ;
  1733. ssin36 = 2.0 * S36;
  1734. ssin72 = 2.0 * S72;
  1735. LOOP
  1736. c[j0+j]= 2.0 *(a[i0+i]+a[i1+i]+a[i2+i]);
  1737. c[j1+j]=(2.0 *(a[i0+i]-0.25*(a[i1+i]+a[i2+i]))
  1738. +qqrt5*(a[i1+i]-a[i2+i]))-(ssin72*b[i1+i]+ssin36*b[i2+i]);
  1739. c[j2+j]=(2.0 *(a[i0+i]-0.25*(a[i1+i]+a[i2+i]))
  1740. -qqrt5*(a[i1+i]-a[i2+i]))-(ssin36*b[i1+i]-ssin72*b[i2+i]);
  1741. c[j3+j]=(2.0 *(a[i0+i]-0.25*(a[i1+i]+a[i2+i]))
  1742. -qqrt5*(a[i1+i]-a[i2+i]))+(ssin36*b[i1+i]-ssin72*b[i2+i]);
  1743. c[j4+j]=(2.0 *(a[i0+i]-0.25*(a[i1+i]+a[i2+i]))
  1744. +qqrt5*(a[i1+i]-a[i2+i]))+(ssin72*b[i1+i]+ssin36*b[i2+i]);
  1745. ENDL
  1746. }
  1747. return 0;
  1748. }
  1749. case 6: {
  1750. ia = 0;
  1751. ib = ia+(2*m-la);
  1752. ic = ib+2*m;
  1753. id = ic+2*m;
  1754. ie = ic;
  1755. iF = ib;
  1756. ja = 0;
  1757. jb = ja+jink;
  1758. jc = jb+jink;
  1759. jd = jc+jink;
  1760. je = jd+jink;
  1761. jf = je+jink;
  1762. if (la != m) /* go to 690 */ {
  1763. LOOP
  1764. c[ja+j] = (a[ia+i]+a[id+i]) + (a[ib+i]+a[ic+i]) ;
  1765. c[jd+j] = (a[ia+i]-a[id+i]) - (a[ib+i]-a[ic+i]) ;
  1766. c[jb+j] = ((a[ia+i]-a[id+i]) +0.5*(a[ib+i]-a[ic+i]))
  1767. - S60*(b[ib+i]+b[ic+i]);
  1768. c[jf+j] = ((a[ia+i]-a[id+i]) +0.5*(a[ib+i]-a[ic+i]))
  1769. + S60*(b[ib+i]+b[ic+i]);
  1770. c[jc+j] = ((a[ia+i]+a[id+i]) -0.5*(a[ib+i]+a[ic+i]))
  1771. - S60*(b[ib+i]-b[ic+i]);
  1772. c[je+j] = ((a[ia+i]+a[id+i]) -0.5*(a[ib+i]+a[ic+i]))
  1773. + S60*(b[ib+i]-b[ic+i]);
  1774. ENDL
  1775. ia += iink;
  1776. iink += iink;
  1777. ib += iink;
  1778. ic += iink;
  1779. id -= iink;
  1780. ie -= iink;
  1781. iF -= iink;
  1782. jbase += jump;
  1783. jump += jump+jink;
  1784. if (ic != id) /* go to 660 */ {
  1785. FORK
  1786. angle = kpidn = k * pin;
  1787. c1 = cos(angle);
  1788. s1 = sin(angle);
  1789. angle += kpidn;
  1790. c2 = cos(angle);
  1791. s2 = sin(angle);
  1792. angle += kpidn;
  1793. c3 = cos(angle);
  1794. s3 = sin(angle);
  1795. angle += kpidn;
  1796. c4 = cos(angle);
  1797. s4 = sin(angle);
  1798. angle += kpidn;
  1799. c5 = cos(angle);
  1800. s5 = sin(angle);
  1801. ibase=0;
  1802. LOOP
  1803. a11 = a[ie+i] + a[ib+i] + a[ic+i] + a[iF+i];
  1804. a20 = a[ia+i] + a[id+i] - 0.5 * a11;
  1805. a21 = S60*((a[ie+i]+a[ib+i])-(a[ic+i]+a[iF+i]));
  1806. b11 = b[ib+i] - b[ie+i] + b[ic+i] - b[iF+i];
  1807. b20 = b[ia+i] - b[id+i] - 0.5 * b11;
  1808. b21 = S60*((b[ib+i]-b[ie+i])-(b[ic+i]-b[iF+i]));
  1809. c[ja+j] = a[ia+i] + a[id+i] + a11;
  1810. d[ja+j] = b[ia+i] - b[id+i] + b11;
  1811. c[jc+j] = c2*(a20-b21)-s2*(b20+a21);
  1812. d[jc+j] = s2*(a20-b21)+c2*(b20+a21);
  1813. c[je+j] = c4*(a20+b21)-s4*(b20-a21);
  1814. d[je+j] = s4*(a20+b21)+c4*(b20-a21);
  1815. a11 = (a[ie+i]-a[ib+i]) + (a[ic+i]-a[iF+i]);
  1816. b11 = (b[ie+i]+b[ib+i]) - (b[ic+i]+b[iF+i]);
  1817. a20 = (a[ia+i]-a[id+i]) - 0.5 * a11;
  1818. a21 = S60 * ((a[ie+i]-a[ib+i]) - (a[ic+i]-a[iF+i]));
  1819. b20 = (b[ia+i]+b[id+i]) + 0.5 * b11;
  1820. b21 = S60 * ((b[ie+i]+b[ib+i]) + (b[ic+i]+b[iF+i]));
  1821. c[jd+j] = c3*(a[ia+i] - a[id+i] + a11)
  1822. - s3*(b[ia+i] + b[id+i] - b11);
  1823. d[jd+j] = s3*(a[ia+i] - a[id+i] + a11)
  1824. + c3*(b[ia+i] + b[id+i] - b11);
  1825. c[jb+j] = c1*(a20-b21)-s1*(b20-a21);
  1826. d[jb+j] = s1*(a20-b21)+c1*(b20-a21);
  1827. c[jf+j] = c5*(a20+b21)-s5*(b20+a21);
  1828. d[jf+j] = s5*(a20+b21)+c5*(b20+a21);
  1829. ENDL
  1830. ia += iink;
  1831. ib += iink;
  1832. ic += iink;
  1833. id -= iink;
  1834. ie -= iink;
  1835. iF -= iink;
  1836. jbase += jump;
  1837. }
  1838. if (ic > id) return 0;
  1839. }
  1840. ibase=0;
  1841. LOOP
  1842. c[ja+j]= a[ib+i] + (a[ia+i] + a[ic+i]);
  1843. c[jd+j]= b[ib+i] - (b[ia+i] + b[ic+i]);
  1844. c[jb+j]= (S60*(a[ia+i]-a[ic+i]))-(0.5*(b[ia+i]+b[ic+i])+b[ib+i]);
  1845. c[jf+j]=-(S60*(a[ia+i]-a[ic+i]))-(0.5*(b[ia+i]+b[ic+i])+b[ib+i]);
  1846. c[jc+j]= S60*(b[ic+i]-b[ia+i]) +(0.5*(a[ia+i]+a[ic+i])-a[ib+i]);
  1847. c[je+j]= S60*(b[ic+i]-b[ia+i]) -(0.5*(a[ia+i]+a[ic+i])-a[ib+i]);
  1848. ENDL
  1849. } else {
  1850. LOOP
  1851. c[ja+j]=(2.0*(a[ia+i]+a[id+i]))+(2.0*(a[ib+i]+a[ic+i]));
  1852. c[jd+j]=(2.0*(a[ia+i]-a[id+i]))-(2.0*(a[ib+i]-a[ic+i]));
  1853. c[jb+j]=(2.0*(a[ia+i]-a[id+i])+(a[ib+i]-a[ic+i]))
  1854. -(D60*(b[ib+i]+b[ic+i]));
  1855. c[jf+j]=(2.0*(a[ia+i]-a[id+i])+(a[ib+i]-a[ic+i]))
  1856. +(D60*(b[ib+i]+b[ic+i]));
  1857. c[jc+j]=(2.0*(a[ia+i]+a[id+i])-(a[ib+i]+a[ic+i]))
  1858. -(D60*(b[ib+i]-b[ic+i]));
  1859. c[je+j]=(2.0*(a[ia+i]+a[id+i])-(a[ib+i]+a[ic+i]))
  1860. +(D60*(b[ib+i]-b[ic+i]));
  1861. ENDL
  1862. }
  1863. return 0;
  1864. }
  1865. case 8: {
  1866. double a0p7,a1p5,a2p6,p073,p074,p152;
  1867. double a0m7,a1m5,a2m6,m073,m074,m152;
  1868. if (la != m) return 3;
  1869. i0 = 0;
  1870. i1 = i0 + iink;
  1871. i2 = i1 + iink;
  1872. i3 = i2 + iink;
  1873. i4 = i3 + iink;
  1874. i5 = i4 + iink;
  1875. i6 = i5 + iink;
  1876. i7 = i6 + iink;
  1877. j0 = 0;
  1878. j1 = j0 + jink;
  1879. j2 = j1 + jink;
  1880. j3 = j2 + jink;
  1881. j4 = j3 + jink;
  1882. j5 = j4 + jink;
  1883. j6 = j5 + jink;
  1884. j7 = j6 + jink;
  1885. LOOP
  1886. a0p7 = a[i0+i] + a[i7+i];
  1887. a0m7 = a[i0+i] - a[i7+i];
  1888. a1p5 = a[i1+i] + a[i5+i];
  1889. a1m5 = a[i1+i] - a[i5+i];
  1890. a2p6 = a[i2+i] + a[i6+i];
  1891. a2m6 = a[i2+i] - a[i6+i];
  1892. p073 = a0p7 + a[i3+i];
  1893. m073 = a0p7 - a[i3+i];
  1894. p074 = 2.0 * (a0m7 + a[i4+i]);
  1895. m074 = 2.0 * (a0m7 - a[i4+i]);
  1896. p152 = M_SQRT2 * (a1m5 + a2p6);
  1897. m152 = M_SQRT2 * (a1m5 - a2p6);
  1898. c[j0+j] = 2.0 * (p073 + a1p5);
  1899. c[j4+j] = 2.0 * (p073 - a1p5);
  1900. c[j2+j] = 2.0 * (m073 - a2m6);
  1901. c[j6+j] = 2.0 * (m073 + a2m6);
  1902. c[j1+j] = m074 + m152;
  1903. c[j5+j] = m074 - m152;
  1904. c[j3+j] = p074 - p152;
  1905. c[j7+j] = p074 + p152;
  1906. ENDL
  1907. }
  1908. }
  1909. return 0;
  1910. }
  1911. int qpassc(double *a, double *b, double *c, double *d,
  1912. int inc3, int inc4,
  1913. int lot , int n , int ifac, int la )
  1914. {
  1915. /*
  1916. qpassc - performs one pass through data as part;
  1917. of multiple real fft (fourier analysis) routine;
  1918. a is first real input vector;
  1919. b is equivalent to a + ifac * la
  1920. c is first real output vector;
  1921. d is equivalent to c + la
  1922. inc3 is the increment between input vectors a;
  1923. inc4 is the increment between output vectors c;
  1924. lot is the number of vectors;
  1925. n is the length of the vectors;
  1926. ifac is the current factor of n;
  1927. la is the product of previous factors;
  1928. qpassc returns an error indicator:;
  1929. 0 - pass completed without error;
  1930. 2 - ifac not catered for;
  1931. 3 - ifac only catered for if la=n/ifac;
  1932. */
  1933. int i0,i1,i2,i3,i4,i5,i6,i7;
  1934. int j0,j1,j2,j3,j4,j5,j6,j7;
  1935. int ia,ib,ic;
  1936. int ja,jb,jc;
  1937. int i,j,k;
  1938. int ibase,jbase;
  1939. int iink,jink;
  1940. int ijk;
  1941. int jump;
  1942. int kstop;
  1943. int l;
  1944. int m;
  1945. double a0,a1,a2,a3;
  1946. double b0,b1,b2,b3;
  1947. double c1,c2,c3,c4,c5;
  1948. double s1,s2,s3,s4,s5;
  1949. double w,x,y,z;
  1950. double angle,kpidn,pin;
  1951. m = n / ifac;
  1952. iink = la;
  1953. jink = la;
  1954. jump = (ifac-1) * iink;
  1955. kstop = (n-ifac) / (2*ifac);
  1956. pin = 2.0 * M_PI / n;
  1957. ibase = 0;
  1958. jbase = 0;
  1959. switch (ifac) {
  1960. case 2: {
  1961. i0 = j0 = 0;
  1962. i1 = i0 + iink;
  1963. j1 = j0 + (m+m-la);
  1964. if (la != m) {
  1965. LOOP
  1966. c[j0+j] = a[i0+i] + a[i1+i];
  1967. c[j1+j] = a[i0+i] - a[i1+i];
  1968. ENDL
  1969. j0 += jink;
  1970. jink += jink;
  1971. j1 -= jink;
  1972. ibase += jump;
  1973. jump += jump + iink;
  1974. if (j0 != j1) {
  1975. FORK
  1976. angle = k * pin;
  1977. c1 = cos(angle);
  1978. s1 = sin(angle);
  1979. jbase = 0;
  1980. LOOP
  1981. c[j0+j] = a[i0+i] + c1 * a[i1+i] + s1 * b[i1+i];
  1982. c[j1+j] = a[i0+i] - c1 * a[i1+i] - s1 * b[i1+i];
  1983. d[j0+j] = c1 * b[i1+i] - s1 * a[i1+i] + b[i0+i];
  1984. d[j1+j] = c1 * b[i1+i] - s1 * a[i1+i] - b[i0+i];
  1985. ENDL
  1986. j0 += jink;
  1987. j1 -= jink;
  1988. ibase += jump;
  1989. } /* End FORK */
  1990. if (j0 > j1) return 0;
  1991. } /* End (i0 != i1) */
  1992. jbase = 0;
  1993. LOOP
  1994. c[j0+j] = a[i0+i];
  1995. d[j1+j] = -a[i1+i];
  1996. ENDL
  1997. }
  1998. else /* (la != m) */ {
  1999. z = 1.0 / n;
  2000. LOOP
  2001. c[j0+j] = z * (a[i0+i] + a[i1+i]);
  2002. c[j1+j] = z * (a[i0+i] - a[i1+i]);
  2003. ENDL
  2004. }
  2005. return 0;
  2006. }
  2007. case 3: {
  2008. ia = 0;
  2009. ib = ia + iink;
  2010. ic = ib + iink;
  2011. ja = 0;
  2012. jb = ja + (m+m-la);
  2013. jc = jb;
  2014. if (la != m) /* else 390 */ {
  2015. LOOP
  2016. c[ja+j] = a[ia+i] + a[ib+i] + a[ic+i];
  2017. c[jb+j] = a[ia+i] - 0.5 * (a[ib+i] + a[ic+i]);
  2018. d[jb+j] = S60 * (a[ic+i] - a[ib+i]);
  2019. ENDL
  2020. ja += jink;
  2021. jink += jink;
  2022. jb += jink;
  2023. jc -= jink;
  2024. ibase += jump;
  2025. jump += jump + iink;
  2026. if (ja != jc) /* else 360 */ {
  2027. FORK
  2028. angle = k * pin;
  2029. c1 = cos(angle);
  2030. s1 = sin(angle);
  2031. angle += angle;
  2032. c2 = cos(angle);
  2033. s2 = sin(angle);
  2034. jbase = 0;
  2035. LOOP
  2036. a1 = c1 * a[ib+i] + s1 * b[ib+i] + c2 * a[ic+i] + s2 * b[ic+i];
  2037. b1 = c1 * b[ib+i] - s1 * a[ib+i] + c2 * b[ic+i] - s2 * a[ic+i];
  2038. a2 = a[ia+i] - 0.5 * a1;
  2039. b2 = b[ia+i] - 0.5 * b1;
  2040. a3 = S60 * (c1 * a[ib+i] + s1 * b[ib+i] - c2 * a[ic+i] - s2 * b[ic+i]);
  2041. b3 = S60 * (c1 * b[ib+i] - s1 * a[ib+i] - c2 * b[ic+i] + s2 * a[ic+i]);
  2042. c[ja+j] = a[ia+i] + a1;
  2043. d[ja+j] = b[ia+i] + b1;
  2044. c[jb+j] = a2 + b3;
  2045. d[jb+j] = b2 - a3;
  2046. c[jc+j] = a2 - b3;
  2047. d[jc+j] =-b2 - a3;
  2048. ENDL
  2049. ja += jink;
  2050. jb += jink;
  2051. jc -= jink;
  2052. ibase += jump;
  2053. } /* End FORK */
  2054. if (ja > jc) return 0;
  2055. } /* End (ia != ic) */
  2056. jbase = 0;
  2057. LOOP
  2058. /* soweit */
  2059. c[ja+j] = a[ia+i] + 0.5 * (a[ib+i] - a[ic+i]);
  2060. d[ja+j] =-S60 * (a[ib+i] + a[ic+i]);
  2061. c[jb+j] = a[ia+i] - a[ib+i] + a[ic+i];
  2062. ENDL
  2063. }
  2064. else /* (la != m) */ {
  2065. z = 1.0 / n;
  2066. y = S60 / n;
  2067. LOOP
  2068. c[ja+j] = z * (a[ia+i] + a[ib+i] + a[ic+i]);
  2069. c[jb+j] = z * (a[ia+i] - 0.5 * (a[ib+i] + a[ic+i]));
  2070. d[jb+j] = y * (a[ic+i] - a[ib+i]);
  2071. ENDL
  2072. }
  2073. return 0;
  2074. }
  2075. case 4: {
  2076. double a0p2,a1p3;
  2077. i0 = 0;
  2078. i1 = i0 + iink;
  2079. i2 = i1 + iink;
  2080. i3 = i2 + iink;
  2081. j0 = 0;
  2082. j1 = j0 + (m+m-la);
  2083. j2 = j1 + (m+m );
  2084. j3 = j1;
  2085. if (la != m) /*else go to 490 */ {
  2086. LOOP
  2087. a0p2 = a[i0+i] + a[i2+i];
  2088. a1p3 = a[i1+i] + a[i3+i];
  2089. c[j0+j] = a0p2 + a1p3;
  2090. c[j2+j] = a0p2 - a1p3;
  2091. c[j1+j] = a[i0+i] - a[i2+i];
  2092. d[j1+j] = a[i3+i] - a[i1+i];
  2093. ENDL
  2094. j0 += jink;
  2095. jink += jink;
  2096. j1 += jink;
  2097. j2 -= jink;
  2098. j3 -= jink;
  2099. ibase += jump;
  2100. jump += jump + iink;
  2101. if (j1 != j2) /* else go to 460; */ {
  2102. FORK
  2103. angle = kpidn = k * pin;
  2104. c1 = cos(angle);
  2105. s1 = sin(angle);
  2106. angle += kpidn;
  2107. c2 = cos(angle);
  2108. s2 = sin(angle);
  2109. angle += kpidn;
  2110. c3 = cos(angle);
  2111. s3 = sin(angle);
  2112. jbase=0;
  2113. LOOP
  2114. a0 = a[i0+i] + c2 * a[i2+i] + s2 * b[i2+i];
  2115. a2 = a[i0+i] - c2 * a[i2+i] - s2 * b[i2+i];
  2116. b0 = b[i0+i] + c2 * b[i2+i] - s2 * a[i2+i];
  2117. b2 = b[i0+i] - c2 * b[i2+i] + s2 * a[i2+i];
  2118. a1 = c1*a[i1+i] + s1*b[i1+i] + c3*a[i3+i] + s3*b[i3+i];
  2119. a3 = c1*a[i1+i] + s1*b[i1+i] - c3*a[i3+i] - s3*b[i3+i];
  2120. b1 = c1*b[i1+i] - s1*a[i1+i] + c3*b[i3+i] - s3*a[i3+i];
  2121. b3 = c1*b[i1+i] - s1*a[i1+i] - c3*b[i3+i] + s3*a[i3+i];
  2122. c[j0+j] = a0 + a1;
  2123. c[j2+j] = a0 - a1;
  2124. d[j0+j] = b0 + b1;
  2125. d[j2+j] = b1 - b0;
  2126. c[j1+j] = a2 + b3;
  2127. c[j3+j] = a2 - b3;
  2128. d[j1+j] = b2 - a3;
  2129. d[j3+j] =-b2 - a3;
  2130. ENDL
  2131. j0 += jink;
  2132. j1 += jink;
  2133. j2 -= jink;
  2134. j3 -= jink;
  2135. ibase += jump;
  2136. } /* End FORK */
  2137. if (j1 > j2) return 0;
  2138. } /* End (i1 != i2) */
  2139. jbase=0;
  2140. LOOP
  2141. c[j0+j] = a[i0+i] + SQ2 * (a[i1+i] - a[i3+i]);
  2142. c[j1+j] = a[i0+i] - SQ2 * (a[i1+i] - a[i3+i]);
  2143. d[j0+j] =-a[i2+i] - SQ2 * (a[i1+i] + a[i3+i]);
  2144. d[j1+j] = a[i2+i] - SQ2 * (a[i1+i] + a[i3+i]);
  2145. ENDL
  2146. }
  2147. else /* (la != m) */ {
  2148. z = 1.0 / n;
  2149. LOOP
  2150. a0p2 = a[i0+i] + a[i2+i];
  2151. a1p3 = a[i1+i] + a[i3+i];
  2152. c[j0+j] = z * (a0p2 + a1p3);
  2153. c[j2+j] = z * (a0p2 - a1p3);
  2154. c[j1+j] = z * (a[i0+i] - a[i2+i]);
  2155. d[j1+j] = z * (a[i3+i] - a[i1+i]);
  2156. ENDL
  2157. }
  2158. return 0;
  2159. }
  2160. case 5: {
  2161. double a1p4,a2p3,b1p4,b2p3,a025,b025,asps,bsps,a0pq,b0pq;
  2162. double a1m4,a2m3,b1m4,b2m3,aqrt,bqrt,asms,bsms,a0mq,b0mq;
  2163. i0 = 0;
  2164. i1 = i0 + iink;
  2165. i2 = i1 + iink;
  2166. i3 = i2 + iink;
  2167. i4 = i3 + iink;
  2168. j0 = 0;
  2169. j1 = j0 + (m+m-la);
  2170. j2 = j1 + (m+m);
  2171. j3 = j2;
  2172. j4 = j1;
  2173. if (la != m) /* else go to 590; */ {
  2174. LOOP
  2175. a1p4 = a[i1+i] + a[i4+i];
  2176. a1m4 = a[i1+i] - a[i4+i];
  2177. a2p3 = a[i2+i] + a[i3+i];
  2178. a2m3 = a[i2+i] - a[i3+i];
  2179. a025 = a[i0+i] - 0.25 * (a1p4 + a2p3);
  2180. aqrt = QT5 * (a1p4 - a2p3);
  2181. c[j0+j] = a[i0+i] + a1p4 + a2p3;
  2182. c[j1+j] = a025 + aqrt;
  2183. c[j2+j] = a025 - aqrt;
  2184. d[j1+j] = -S72 * a1m4 - S36 * a2m3;
  2185. d[j2+j] = -S36 * a1m4 + S72 * a2m3;
  2186. ENDL
  2187. j0 += jink;
  2188. jink += jink;
  2189. j1 += jink;
  2190. j2 += jink;
  2191. j3 -= jink;
  2192. j4 -= jink;
  2193. ibase += jump;
  2194. jump += jump + iink;
  2195. if (j1 != j3) {
  2196. FORK
  2197. angle = kpidn = k * pin;
  2198. c1 = cos(angle);
  2199. s1 = sin(angle);
  2200. angle += kpidn;
  2201. c2 = cos(angle);
  2202. s2 = sin(angle);
  2203. angle += kpidn;
  2204. c3 = cos(angle);
  2205. s3 = sin(angle);
  2206. angle += kpidn;
  2207. c4 = cos(angle);
  2208. s4 = sin(angle);
  2209. jbase=0;
  2210. LOOP
  2211. a1p4 = c1*a[i1+i] + s1*b[i1+i] + c4*a[i4+i] + s4*b[i4+i];
  2212. a1m4 = c1*a[i1+i] + s1*b[i1+i] - c4*a[i4+i] - s4*b[i4+i];
  2213. a2p3 = c2*a[i2+i] + s2*b[i2+i] + c3*a[i3+i] + s3*b[i3+i];
  2214. a2m3 = c2*a[i2+i] + s2*b[i2+i] - c3*a[i3+i] - s3*b[i3+i];
  2215. b1p4 = c1*b[i1+i] - s1*a[i1+i] + c4*b[i4+i] - s4*a[i4+i];
  2216. b1m4 = c1*b[i1+i] - s1*a[i1+i] - c4*b[i4+i] + s4*a[i4+i];
  2217. b2p3 = c2*b[i2+i] - s2*a[i2+i] + c3*b[i3+i] - s3*a[i3+i];
  2218. b2m3 = c2*b[i2+i] - s2*a[i2+i] - c3*b[i3+i] + s3*a[i3+i];
  2219. a025 = a[i0+i] - 0.25 * (a1p4 + a2p3);
  2220. aqrt = QT5 * (a1p4 - a2p3);
  2221. b025 = b[i0+i] - 0.25 * (b1p4 + b2p3);
  2222. bqrt = QT5 * (b1p4 - b2p3);
  2223. a0pq = a025 + aqrt;
  2224. a0mq = a025 - aqrt;
  2225. b0pq = b025 + bqrt;
  2226. b0mq = b025 - bqrt;
  2227. asps = S72 * a1m4 + S36 * a2m3;
  2228. asms = S36 * a1m4 - S72 * a2m3;
  2229. bsps = S72 * b1m4 + S36 * b2m3;
  2230. bsms = S36 * b1m4 - S72 * b2m3;
  2231. c[j0+j] = a[i0+i] + a1p4 + a2p3;
  2232. c[j1+j] = a0pq + bsps;
  2233. c[j2+j] = a0mq + bsms;
  2234. c[j3+j] = a0mq - bsms;
  2235. c[j4+j] = a0pq - bsps;
  2236. d[j0+j] = b[i0+i] + b1p4 + b2p3;
  2237. d[j1+j] = b0pq - asps;
  2238. d[j2+j] = b0mq - asms;
  2239. d[j3+j] =-b0mq - asms;
  2240. d[j4+j] =-b0pq - asps;
  2241. ENDL
  2242. j0 += jink;
  2243. j1 += jink;
  2244. j2 += jink;
  2245. j3 -= jink;
  2246. j4 -= jink;
  2247. ibase += jump;
  2248. } /* End FORK */
  2249. if (j1 > j3) return 0;
  2250. } /* End (jb != jd) */
  2251. jbase=0;
  2252. LOOP
  2253. a1p4 = a[i1+i] + a[i4+i];
  2254. a1m4 = a[i1+i] - a[i4+i];
  2255. a2p3 = a[i2+i] + a[i3+i];
  2256. a2m3 = a[i2+i] - a[i3+i];
  2257. a025 = a[i0+i] + 0.25 * (a1m4 - a2m3);
  2258. aqrt = QT5 * (a1m4 + a2m3);
  2259. c[j0+j] = a025 + aqrt;
  2260. c[j1+j] = a025 - aqrt;
  2261. c[j2+j] = a[i0+i] - a1m4 + a2m3;
  2262. d[j0+j] = -S36 * a1p4 - S72 * a2p3;
  2263. d[j1+j] = -S72 * a1p4 + S36 * a2p3;
  2264. ENDL
  2265. } else {
  2266. z = 1.0 / n;
  2267. y = QT5 / n;
  2268. x = S36 / n;
  2269. w = S72 / n;
  2270. LOOP
  2271. a1p4 = a[i1+i] + a[i4+i];
  2272. a1m4 = a[i1+i] - a[i4+i];
  2273. a2p3 = a[i2+i] + a[i3+i];
  2274. a2m3 = a[i2+i] - a[i3+i];
  2275. a025 = z * (a[i0+i] - 0.25 * (a1p4 + a2p3));
  2276. aqrt = y * (a1p4 - a2p3);
  2277. c[j0+j] = z * (a[i0+i] + a1p4 + a2p3);
  2278. c[j1+j] = a025 + aqrt;
  2279. c[j2+j] = a025 - aqrt;
  2280. d[j1+j] = -w * a1m4 - x * a2m3;
  2281. d[j2+j] = w * a2m3 - x * a1m4;
  2282. ENDL
  2283. }
  2284. return 0;
  2285. }
  2286. case 6: {
  2287. double ab1a,ab2a,ab3a,ab4a,ab5a;
  2288. double ab1b,ab2b,ab3b,ab4b,ab5b;
  2289. double a0p3,a1p4,a1p5,a2p4,a2p5;
  2290. double a0m3,a1m4,a1m5,a2m4,a2m5;
  2291. double b1p4,b2p5;
  2292. double b1m4,b2m5;
  2293. double ap05,bp05,ap60,bp60;
  2294. double am05,bm05,am60,bm60;
  2295. i0 = 0;
  2296. i1 = i0 + iink;
  2297. i2 = i1 + iink;
  2298. i3 = i2 + iink;
  2299. i4 = i3 + iink;
  2300. i5 = i4 + iink;
  2301. j0 = 0;
  2302. j1 = j0 + (m+m-la);
  2303. j2 = j1 + (m+m);
  2304. j3 = j2 + (m+m);
  2305. j4 = j2;
  2306. j5 = j1;
  2307. if (la != m) {
  2308. LOOP
  2309. a0p3 = a[i0+i] + a[i3+i];
  2310. a0m3 = a[i0+i] - a[i3+i];
  2311. a1p4 = a[i1+i] + a[i4+i];
  2312. a1m4 = a[i1+i] - a[i4+i];
  2313. a2p5 = a[i2+i] + a[i5+i];
  2314. a2m5 = a[i2+i] - a[i5+i];
  2315. c[j0+j] = a0p3 + a1p4 + a2p5;
  2316. c[j3+j] = a0m3 + a2m5 - a1m4;
  2317. c[j1+j] = a0m3 - 0.5 * (a2m5 - a1m4);
  2318. c[j2+j] = a0p3 - 0.5 * (a1p4 + a2p5);
  2319. d[j1+j] = S60 * (-a2m5 - a1m4);
  2320. d[j2+j] = S60 * ( a2p5 - a1p4);
  2321. ENDL
  2322. j0 += jink;
  2323. jink += jink;
  2324. j1 += jink;
  2325. j2 += jink;
  2326. j3 -= jink;
  2327. j4 -= jink;
  2328. j5 -= jink;
  2329. ibase += jump;
  2330. jump += jump+iink;
  2331. if (j2 != j3) {
  2332. FORK
  2333. angle = kpidn = k * pin;
  2334. c1 = cos(angle);
  2335. s1 = sin(angle);
  2336. angle += kpidn;
  2337. c2 = cos(angle);
  2338. s2 = sin(angle);
  2339. angle += kpidn;
  2340. c3 = cos(angle);
  2341. s3 = sin(angle);
  2342. angle += kpidn;
  2343. c4 = cos(angle);
  2344. s4 = sin(angle);
  2345. angle += kpidn;
  2346. c5 = cos(angle);
  2347. s5 = sin(angle);
  2348. jbase = 0;
  2349. LOOP
  2350. ab1a = c1 * a[i1+i] + s1 * b[i1+i];
  2351. ab1b = c1 * b[i1+i] - s1 * a[i1+i];
  2352. ab2a = c2 * a[i2+i] + s2 * b[i2+i];
  2353. ab2b = c2 * b[i2+i] - s2 * a[i2+i];
  2354. ab3a = c3 * a[i3+i] + s3 * b[i3+i];
  2355. ab3b = c3 * b[i3+i] - s3 * a[i3+i];
  2356. ab4a = c4 * a[i4+i] + s4 * b[i4+i];
  2357. ab4b = c4 * b[i4+i] - s4 * a[i4+i];
  2358. ab5a = c5 * a[i5+i] + s5 * b[i5+i];
  2359. ab5b = c5 * b[i5+i] - s5 * a[i5+i];
  2360. a1p4 = ab1a + ab4a;
  2361. a1m4 = ab1a - ab4a;
  2362. a2p5 = ab2a + ab5a;
  2363. a2m5 = ab2a - ab5a;
  2364. b1p4 = ab1b + ab4b;
  2365. b1m4 = ab1b - ab4b;
  2366. b2p5 = ab2b + ab5b;
  2367. b2m5 = ab2b - ab5b;
  2368. ap05 = a[i0+i] + ab3a - 0.5 * (a1p4 + a2p5);
  2369. bp05 = b[i0+i] + ab3b - 0.5 * (b1p4 + b2p5);
  2370. am05 = a[i0+i] - ab3a - 0.5 * (a2m5 - a1m4);
  2371. bm05 =-b[i0+i] + ab3b - 0.5 * (b1m4 - b2m5);
  2372. ap60 = S60 * ( a2p5 - a1p4);
  2373. bp60 = S60 * ( b2p5 - b1p4);
  2374. am60 = S60 * (-a2m5 - a1m4);
  2375. bm60 = S60 * (-b2m5 - b1m4);
  2376. c[j0+j] = a[i0+i] + ab3a + a1p4 + a2p5;
  2377. d[j0+j] = b[i0+i] + ab3b + b1p4 + b2p5;
  2378. c[j1+j] = am05 - bm60;
  2379. d[j1+j] = am60 - bm05;
  2380. c[j2+j] = ap05 - bp60;
  2381. d[j2+j] = ap60 + bp05;
  2382. c[j3+j] = a[i0+i] - ab3a - a1m4 + a2m5;
  2383. d[j3+j] =-b[i0+i] + ab3b + b1m4 - b2m5;
  2384. c[j4+j] = ap05 + bp60;
  2385. d[j4+j] = ap60 - bp05;
  2386. c[j5+j] = am05 + bm60;
  2387. d[j5+j] = am60 + bm05;
  2388. ENDL
  2389. j0 += jink;
  2390. j1 += jink;
  2391. j2 += jink;
  2392. j3 -= jink;
  2393. j4 -= jink;
  2394. j5 -= jink;
  2395. ibase += jump;
  2396. }
  2397. if (j2 > j3) return 0;
  2398. }
  2399. jbase = 0;
  2400. LOOP
  2401. a1p5 = a[i1+i] + a[i5+i];
  2402. a1m5 = a[i1+i] - a[i5+i];
  2403. a2p4 = a[i2+i] + a[i4+i];
  2404. a2m4 = a[i2+i] - a[i4+i];
  2405. c[j0+j] = a[i0+i] + 0.5 * a2m4 + S60 * a1m5;
  2406. d[j0+j] =-a[i3+i] - 0.5 * a1p5 - S60 * a2p4;
  2407. c[j1+j] = a[i0+i] - a2m4;
  2408. d[j1+j] = a[i3+i] - a1p5;
  2409. c[j2+j] = a[i0+i] + 0.5 * a2m4 - S60 * a1m5;
  2410. d[j2+j] =-a[i3+i] - 0.5 * a1p5 + S60 * a2p4;
  2411. ENDL
  2412. } else {
  2413. z = 1.0 / n;
  2414. y = S60 / n;
  2415. LOOP
  2416. a0p3 = a[i0+i] + a[i3+i];
  2417. a0m3 = a[i0+i] - a[i3+i];
  2418. a1p4 = a[i1+i] + a[i4+i];
  2419. a1m4 = a[i1+i] - a[i4+i];
  2420. a2p5 = a[i2+i] + a[i5+i];
  2421. a2m5 = a[i2+i] - a[i5+i];
  2422. c[j0+j] = z * (a0p3 + a1p4 + a2p5);
  2423. c[j3+j] = z * (a0m3 + a2m5 - a1m4);
  2424. c[j1+j] = z * (a0m3 - 0.5 * (a2m5 - a1m4));
  2425. c[j2+j] = z * (a0p3 - 0.5 * (a1p4 + a2p5));
  2426. d[j1+j] = y * (-a2m5 - a1m4);
  2427. d[j2+j] = y * ( a2p5 - a1p4);
  2428. ENDL
  2429. }
  2430. return 0;
  2431. }
  2432. case 8: {
  2433. double a0p4,a1p5,a2p6,a3p7;
  2434. double a0m4,a1m5,a2m6,a3m7;
  2435. if (la != m) return 3;
  2436. i0 = 0;
  2437. i1 = i0 + iink;
  2438. i2 = i1 + iink;
  2439. i3 = i2 + iink;
  2440. i4 = i3 + iink;
  2441. i5 = i4 + iink;
  2442. i6 = i5 + iink;
  2443. i7 = i6 + iink;
  2444. j0 = 0;
  2445. j1 = j0 + jink;
  2446. j2 = j1 + jink;
  2447. j3 = j2 + jink;
  2448. j4 = j3 + jink;
  2449. j5 = j4 + jink;
  2450. j6 = j5 + jink;
  2451. j7 = j6 + jink;
  2452. z = 1.0 / n;
  2453. y = SQ2 / n;
  2454. LOOP
  2455. a0p4 = a[i0+i] + a[i4+i];
  2456. a0m4 = a[i0+i] - a[i4+i];
  2457. a1p5 = a[i1+i] + a[i5+i];
  2458. a1m5 = a[i1+i] - a[i5+i];
  2459. a2p6 = a[i2+i] + a[i6+i];
  2460. a2m6 = a[i2+i] - a[i6+i];
  2461. a3p7 = a[i3+i] + a[i7+i];
  2462. a3m7 = a[i3+i] - a[i7+i];
  2463. c[j0+j] = z * (a0p4 + a1p5 + a2p6 + a3p7);
  2464. c[j7+j] = z * (a0p4 - a1p5 + a2p6 - a3p7);
  2465. c[j3+j] = z * (a0p4 - a2p6);
  2466. c[j4+j] = z * (a3p7 - a1p5);
  2467. c[j1+j] = z * a0m4 + y * (a1m5 - a3m7);
  2468. c[j5+j] = z * a0m4 - y * (a1m5 - a3m7);
  2469. c[j2+j] =-z * a2m6 - y * (a1m5 + a3m7);
  2470. c[j6+j] = z * a2m6 - y * (a1m5 + a3m7);
  2471. ENDL
  2472. }
  2473. }
  2474. return 0;
  2475. }
  2476. void fc2gp(double *fc, double *gp, int Lat, int Lon, int Lev, int Fou)
  2477. {
  2478. int Lot;
  2479. int fou;
  2480. int ia;
  2481. int ifac;
  2482. int j;
  2483. int jump;
  2484. int k;
  2485. int la;
  2486. int lat;
  2487. int lev;
  2488. int lon;
  2489. int nfax;
  2490. int rix;
  2491. int wix;
  2492. double *wpt;
  2493. /* fc2gp performs fourier to gridpoint transforms using */
  2494. /* multiple fast fourier transform of length Lon */
  2495. /* */
  2496. /* fc - real array of fourier coefficients fc[Lev][Fou][Lat] */
  2497. /* gp - real array of gridpoints gp[Lev][Lat][Lon] */
  2498. /* Lat - Number of latitudes */
  2499. /* Lon - Number of longitudes */
  2500. /* Lev - Number of levels */
  2501. /* Fou - Number of fourier coefficients on 1 latitude */
  2502. /* x(j) = sum(k=0,...,n-1)(c(k)*exp(2*i*j*k*pi/Lon)) */
  2503. /* where c(k) = a(k) + i*b(k) and c(n-k) = a(k)-i*b(k) */
  2504. jump = (Lon + 2) | 1;
  2505. Lot = Lev * Lat;
  2506. nfax = ifax[0];
  2507. for (lev = 0; lev < Lev; ++lev)
  2508. {
  2509. for (lat = 0; lat < Lat; ++lat)
  2510. {
  2511. wix = jump * (lat + lev * Lat);
  2512. rix = lat + lev * Lat * Fou;
  2513. for (fou = 0 ; fou < Fou && fou < jump ; ++fou)
  2514. wfc[wix + fou] = fc[rix + fou * Lat];
  2515. for (fou = Fou; fou < jump; ++fou)
  2516. wfc[wix + fou] = 0.0;
  2517. wfc[wix+1] = 0.5 * wfc[wix];
  2518. }
  2519. }
  2520. ia = 1;
  2521. la = 1;
  2522. for (k = 0; k < nfax; ++k) {
  2523. ifac = ifax[k+1];
  2524. if (k&1) rpassc(wgp,wgp+la,wfc+ia,wfc+ia+ifac*la,
  2525. jump,jump,Lot,Lon,ifac,la);
  2526. else rpassc(wfc+ia,wfc+ia+la,wgp,wgp+ifac*la,
  2527. jump,jump,Lot,Lon,ifac,la);
  2528. la *= ifac;
  2529. ia = 0;
  2530. }
  2531. if (nfax & 1) wpt = wgp;
  2532. else wpt = wfc;
  2533. for (j = 0; j < Lot ; ++j)
  2534. for (lon = 0; lon < Lon; ++lon)
  2535. gp[lon + j * Lon] = wpt[lon + j * jump];
  2536. }
  2537. void gp2fc(double *gp, double *fc, int Lat, int Lon, int Lev, int Fou)
  2538. {
  2539. int Lot;
  2540. int fou;
  2541. int ia;
  2542. int ifac;
  2543. int jump;
  2544. int k;
  2545. int la;
  2546. int lat;
  2547. int lev;
  2548. int lon;
  2549. int lot;
  2550. int nfax;
  2551. int rix;
  2552. int wix;
  2553. double *wpt;
  2554. /* gp2fc performs gridpoint to fourier transforms using */
  2555. /* multiple fast fourier transform of length Lon */
  2556. /* */
  2557. /* fc - real array of fourier coefficients fc[Lev][Fou][Lat] */
  2558. /* gp - real array of gridpoints gp[Lev][Lat][Lon] */
  2559. /* Lat - Number of latitudes */
  2560. /* Lon - Number of longitudes */
  2561. /* Lev - Number of levels */
  2562. /* Fou - Number of fourier coefficients on 1 latitude */
  2563. /* a(k) = (1/n) * sum(j=0,...,n-1)(x(j) * cos(2*j*k*pi/n)) */
  2564. /* b(k) = -(1/n) * sum(j=0,...,n-1)(x(j) * sin(2*j*k*pi/n)) */
  2565. if (!gp) Abort("gp2fc called with NULL pointer for gp");
  2566. if (!fc) Abort("gp2fc called with NULL pointer for fc");
  2567. jump = (Lon + 2) | 1;
  2568. Lot = Lev * Lat;
  2569. nfax = ifax[0];
  2570. rix = 0;
  2571. wix = 0;
  2572. for (lot = 0; lot < Lot; ++lot) {
  2573. for (lon = 0; lon < Lon; ++lon) wgp[wix+lon] = gp[rix+lon];
  2574. wgp[wix+Lon ] = 0.0;
  2575. wgp[wix+Lon+1] = 0.0;
  2576. rix += Lon;
  2577. wix += jump;
  2578. }
  2579. ia = 0;
  2580. la = Lon;
  2581. for (k = 0; k < nfax; ++k) {
  2582. ifac = ifax[nfax-k];
  2583. la /= ifac;
  2584. if (k & 1) qpassc(wfc,wfc+ifac*la,wgp+ia,wgp+ia+la,
  2585. jump,jump,Lot,Lon,ifac,la);
  2586. else qpassc(wgp+ia,wgp+ia+ifac*la,wfc,wfc+la,
  2587. jump,jump,Lot,Lon,ifac,la);
  2588. ia = 1;
  2589. }
  2590. if (nfax & 1) wpt = wfc;
  2591. else wpt = wgp+1;
  2592. for (lev = 0; lev < Lev; ++lev) {
  2593. for (lat = 0; lat < Lat; ++lat) {
  2594. rix = jump * (lat + lev * Lat);
  2595. wix = lat + lev * Lat * Fou;
  2596. fc[wix ] = wpt[rix];
  2597. fc[wix+Lat] = 0.0;
  2598. for (fou = 2 ; fou < Fou ; ++fou)
  2599. fc[wix + fou * Lat] = wpt[rix + fou - 1];
  2600. }
  2601. }
  2602. }
  2603. inline void SwapIEEE(char W[4])
  2604. {
  2605. char B;
  2606. B = W[0]; W[0] = W[3]; W[3] = B;
  2607. B = W[1]; W[1] = W[2]; W[2] = B;
  2608. }
  2609. inline void SwapIEEE64(char W[8])
  2610. {
  2611. char B;
  2612. B = W[0]; W[0] = W[3]; W[3] = B;
  2613. B = W[1]; W[1] = W[2]; W[2] = B;
  2614. B = W[4]; W[4] = W[7]; W[7] = B;
  2615. B = W[5]; W[5] = W[6]; W[6] = B;
  2616. }
  2617. int check_fcw(int fcws, int fcwe)
  2618. {
  2619. if (fcwe != fcws)
  2620. {
  2621. printf("\n*************** ERROR reading input file **************\n");
  2622. printf("The FORTRAN control words (FCW) of a record don't match\n");
  2623. printf("FCW before record = %d\n",fcws);
  2624. printf("FCW after record = %d\n",fcwe);
  2625. printf("File position: %ld\n",ftell(fpi));
  2626. printf("Possible causes are:\n");
  2627. printf("1) Model crashed leaving an incomplete output file\n");
  2628. printf("2) Corrupt data file (cache or disk problems)\n");
  2629. return 1;
  2630. }
  2631. return 0;
  2632. }
  2633. /* =============================== */
  2634. /* Read IEEE 32 bit data from file */
  2635. /* =============================== */
  2636. inline int ReadINT(void)
  2637. {
  2638. int k;
  2639. fread(&k,sizeof(k),1,fpi);
  2640. if (Endian) SwapIEEE((char *)&k);
  2641. return k;
  2642. }
  2643. inline LONG ReadLONG(void)
  2644. {
  2645. LONG l;
  2646. fread(&l,sizeof(l),1,fpi);
  2647. if (Endian) SwapIEEE64((char *)&l);
  2648. return l;
  2649. }
  2650. inline int ReadFCW(void)
  2651. {
  2652. int k;
  2653. LONG l;
  2654. if (LongFCW)
  2655. {
  2656. fread(&l,sizeof(l),1,fpi);
  2657. if (Endian) SwapIEEE64((char *)&l);
  2658. k = (int)l;
  2659. }
  2660. else
  2661. {
  2662. fread(&k,sizeof(k),1,fpi);
  2663. if (Endian) SwapIEEE((char *)&k);
  2664. }
  2665. return k;
  2666. }
  2667. inline float ReadFLOAT(void)
  2668. {
  2669. int i;
  2670. float f;
  2671. i = fread(&f,sizeof(f),1,fpi);
  2672. if (i != 1) Abort("Unexpected EOF in ReadFLOAT");
  2673. if (Endian) SwapIEEE((char *)&f);
  2674. return f;
  2675. }
  2676. inline double ReadDOUBLE(void)
  2677. {
  2678. int i;
  2679. double f;
  2680. i = fread(&f,sizeof(f),1,fpi);
  2681. if (i != 1) Abort("Unexpected EOF in ReadDOUBLE");
  2682. if (Endian) SwapIEEE64((char *)&f);
  2683. return f;
  2684. }
  2685. inline int ReadINTRecord(void)
  2686. {
  2687. int k,b,e;
  2688. b = ReadFCW();
  2689. fread(&k,sizeof(k),1,fpi); /* IEEE 32-bit integer */
  2690. e = ReadFCW();
  2691. if (check_fcw(b,e)) Abort("record control word mismatch in ReadINTRecord");
  2692. if (Endian) SwapIEEE((char *)&k);
  2693. return k;
  2694. }
  2695. inline int Skip_FORTRAN_Record(void)
  2696. {
  2697. int fcws,fcwe;
  2698. fcws = ReadFCW();
  2699. if (feof(fpi)) return 0;
  2700. fseek(fpi,fcws,SEEK_CUR);
  2701. fcwe = ReadFCW();
  2702. if (check_fcw(fcws,fcwe))
  2703. Abort("record control word mismatch in Skip_FORTRAN_Record");
  2704. return fcws;
  2705. }
  2706. inline void Swap_FORTRAN_Record(char *c, int n)
  2707. {
  2708. char b;
  2709. int i;
  2710. for (i=0 ; i < n ; i+=4)
  2711. {
  2712. b = c[i ]; c[i ] = c[i+3]; c[i+3] = b;
  2713. b = c[i+1]; c[i+1] = c[i+2]; c[i+2] = b;
  2714. }
  2715. }
  2716. inline void Swap_FORTRAN_Double(char *c, int n)
  2717. {
  2718. char b;
  2719. int i;
  2720. for (i=0 ; i < n ; i+=8)
  2721. {
  2722. b = c[i ]; c[i ] = c[i+7]; c[i+7] = b;
  2723. b = c[i+1]; c[i+1] = c[i+6]; c[i+6] = b;
  2724. b = c[i+2]; c[i+2] = c[i+5]; c[i+5] = b;
  2725. b = c[i+3]; c[i+3] = c[i+4]; c[i+4] = b;
  2726. }
  2727. }
  2728. inline int Read_FORTRAN_Record(void)
  2729. {
  2730. int fcws,fcwe;
  2731. fcws = ReadFCW();
  2732. if (feof(fpi)) return 0;
  2733. fread(Record_char,1,fcws,fpi);
  2734. fcwe = ReadFCW();
  2735. if (check_fcw(fcws,fcwe)) Abort("record control word mismatch in Read_FORTRAN_Record");
  2736. if (Endian) Swap_FORTRAN_Record(Record_char,fcws);
  2737. return fcws;
  2738. }
  2739. inline int Read_FORTRAN_Double_Record(void)
  2740. {
  2741. int fcws,fcwe;
  2742. fcws = ReadFCW();
  2743. if (feof(fpi)) return 0;
  2744. fread(Record_char,1,fcws,fpi);
  2745. fcwe = ReadFCW();
  2746. if (check_fcw(fcws,fcwe)) Abort("record control word mismatch in Read_FORTRAN_Double_Record");
  2747. if (Endian) Swap_FORTRAN_Double(Record_char,fcws);
  2748. return fcws;
  2749. }
  2750. int ReadHeaderRecord(void)
  2751. {
  2752. int h,i,fcws,fcwe;
  2753. fcws = ReadFCW();
  2754. if (feof(fpi)) return 1;
  2755. if (fcws == 8) /* Skip PUMA header */
  2756. {
  2757. if (Debug)
  2758. {
  2759. printf("Skipping %d header words\n",HeaderWords);
  2760. for (i=0 ; i < HeaderWords ; ++i)
  2761. {
  2762. h = ReadINT();
  2763. printf("HW[%2d] = %8x %d\n",i,h,h);
  2764. }
  2765. }
  2766. else
  2767. for (i=0 ; i < HeaderWords ; ++i) ReadINT();
  2768. fcws = ReadFCW();
  2769. if (feof(fpi))
  2770. {
  2771. printf("\n#### Empty data file #####\n");
  2772. printf("Mark [Write Ouput] in MoSt\n");
  2773. printf("or set NOUTPUT=1 in file <puma_namelist>\n");
  2774. Abort("Empty data file");
  2775. }
  2776. }
  2777. if (fcws != HeadSize)
  2778. {
  2779. printf("FCW = %d (should be %d)\n",fcws,HeadSize);
  2780. Abort("Wrong FCW found in ReadHeaderRecord");
  2781. }
  2782. for (i=0 ; i < 8 ; ++i)
  2783. {
  2784. if (HeadSize == 32) HeadIn[i] = ReadINT();
  2785. else HeadIn[i] = ReadLONG();
  2786. }
  2787. fcwe = ReadFCW();
  2788. if (check_fcw(fcws,fcwe)) Abort("FCW mismatch in ReadHeaderRecord");
  2789. return 0;
  2790. }
  2791. void DecodePumaHeader(void)
  2792. {
  2793. PumaCode = HeadIn[0];
  2794. PumaLevel = HeadIn[1];
  2795. NewDate.tm_year = HeadIn[2] / 10000;
  2796. NewDate.tm_mon = HeadIn[2] / 100 % 100;
  2797. NewDate.tm_mday = HeadIn[2] % 100;
  2798. NewDate.tm_hour = HeadIn[3] / 100;
  2799. NewDate.tm_min = HeadIn[3] % 100;
  2800. if (DayDivisor > 1) NewMonth = (TermCount / DPM) % 12 + 1;
  2801. else NewMonth = NewDate.tm_mon;
  2802. if (HeadIn[4] * HeadIn[5] == DimSP) RepGrib = REP_SPECTRAL;
  2803. else RepGrib = REP_GAUSS;
  2804. if (PumaCode < 0 || PumaCode >= CODES)
  2805. {
  2806. printf("Illegal Code %d in header\n",PumaCode);
  2807. Abort("Code < 0 or Code > CODES found");
  2808. }
  2809. All[PumaCode].detected = TRUE;
  2810. }
  2811. // =============
  2812. // ReadPumaArray
  2813. // =============
  2814. void ReadPumaArray(double *Array)
  2815. {
  2816. int i,j,fcws;
  2817. double zfac;
  2818. double zmin;
  2819. if (RealSize == sizeof(float)) fcws = Read_FORTRAN_Record();
  2820. else fcws = Read_FORTRAN_Double_Record();
  2821. if (fcws == sizeof(float) * (Truncation + 2)) // Packed spectral data
  2822. {
  2823. for (i=0 ; i <= Truncation ; i++)
  2824. {
  2825. Array[2*i ] = Record_float[i];
  2826. Array[2*i+1] = 0.0; // Imaginary parts of zonal modes
  2827. }
  2828. zfac = 1.0 / Record_float[Truncation+1];
  2829. fcws = Read_FORTRAN_Record();
  2830. if (CoreBigEndian)
  2831. {
  2832. for (i=2*Truncation+2,j=0 ; i < DimSP ; ++i,++j)
  2833. {
  2834. Array[i] = (Record_short[j] - 32768) * zfac;
  2835. }
  2836. }
  2837. else
  2838. {
  2839. for (i=2*Truncation+2,j=0 ; i < DimSP ; i+=2,j+=2)
  2840. {
  2841. Array[i ] = (Record_short[j+1] - 32768) * zfac;
  2842. Array[i+1] = (Record_short[j ] - 32768) * zfac;
  2843. }
  2844. }
  2845. }
  2846. else if (fcws == sizeof(float) * DimSP) // Unpacked spectral float data
  2847. {
  2848. for (i=0 ; i < DimSP ; ++i) Array[i] = Record_float[i];
  2849. }
  2850. else if (fcws == sizeof(double) * DimSP) // Unpacked spectral double data
  2851. {
  2852. memcpy(Array,Record_double,fcws);
  2853. }
  2854. else if (fcws == sizeof(float) * DimGG) // Unpacked grid float data
  2855. {
  2856. for (i=0 ; i < DimGG ; ++i) Array[i] = Record_float[i];
  2857. }
  2858. else if (fcws == sizeof(double) * DimGG) // Unpacked grid double data
  2859. {
  2860. memcpy(Array,Record_double,fcws);
  2861. }
  2862. else if (fcws == 8) /* Packed grid data */
  2863. {
  2864. zmin = Record_float[0];
  2865. zfac = 1.0 / Record_float[1];
  2866. fcws = Read_FORTRAN_Record();
  2867. if (CoreBigEndian)
  2868. {
  2869. for (i=0 ; i < DimGG ; ++i)
  2870. {
  2871. Array[i] = Record_short[i] * zfac + zmin;
  2872. }
  2873. }
  2874. else
  2875. {
  2876. for (i=0 ; i < DimGG ; i+=2)
  2877. {
  2878. Array[i ] = Record_short[i+1] * zfac + zmin;
  2879. Array[i+1] = Record_short[i ] * zfac + zmin;
  2880. }
  2881. }
  2882. }
  2883. else Abort("fcws error in ReadPumaArray");
  2884. }
  2885. /* ============= */
  2886. /* SkipPumaArray */
  2887. /* ============= */
  2888. void SkipPumaArray(void)
  2889. {
  2890. int fcws;
  2891. fcws = Skip_FORTRAN_Record();
  2892. if (fcws == 8 || fcws == 4 * (Truncation + 2))
  2893. fcws = Skip_FORTRAN_Record();
  2894. }
  2895. /* ============================================= */
  2896. /* phcs - Compute values of Legendre polynomials */
  2897. /* and their meridional derivatives */
  2898. /* ============================================= */
  2899. void phcs(double *PNM, double *HNM, int Waves, double PMU,
  2900. double *ZTEMP1, double *ZTEMP2)
  2901. {
  2902. long TwoWaves;
  2903. long JK;
  2904. long JN;
  2905. long JM;
  2906. double JNmJK;
  2907. double ZCOS2;
  2908. double Lat;
  2909. double ZAN;
  2910. double ZSINPAR;
  2911. double ZCOSPAR;
  2912. double ZSQP;
  2913. double ZCOSFAK;
  2914. double ZSINFAK;
  2915. double ZQ;
  2916. double ZWM2;
  2917. double ZW;
  2918. double ZWQ;
  2919. double ZQ2M1;
  2920. double ZWM2Q2;
  2921. double Z2Q2;
  2922. double ZCNM;
  2923. double ZDNM;
  2924. double ZENM;
  2925. TwoWaves = Waves << 1;
  2926. ZCOS2 = sqrt(1.0 - PMU * PMU);
  2927. Lat = acos(PMU);
  2928. ZAN = 1.0;
  2929. ZTEMP1[0] = 0.5;
  2930. for (JN = 1; JN < TwoWaves; JN++) {
  2931. ZSQP = 1.0 / sqrt((double)(JN+JN*JN));
  2932. ZAN *= sqrt(1.0 - 1.0 / (4 * JN * JN));
  2933. ZCOSPAR = cos(Lat * JN);
  2934. ZSINPAR = sin(Lat * JN) * JN * ZSQP;
  2935. ZCOSFAK = 1.0;
  2936. for (JK = 2; JK < JN; JK += 2) {
  2937. JNmJK = JN - JK;
  2938. ZCOSFAK *= (JK-1) * (JN+JNmJK+2) / (JK * (JN+JNmJK+1));
  2939. ZSINFAK = ZCOSFAK * (JNmJK) * ZSQP;
  2940. ZCOSPAR += ZCOSFAK * cos(Lat * JNmJK);
  2941. ZSINPAR += ZSINFAK * sin(Lat * JNmJK);
  2942. }
  2943. /* Code for JK == JN */
  2944. if ((JN & 1) == 0) {
  2945. ZCOSFAK *= (double)((JN-1) * (JN+2)) / (double)(JN * (JN+1));
  2946. ZCOSPAR += ZCOSFAK * 0.5;
  2947. }
  2948. ZTEMP1[JN ] = ZAN * ZCOSPAR;
  2949. ZTEMP2[JN-1] = ZAN * ZSINPAR;
  2950. }
  2951. memcpy(PNM,ZTEMP1,Waves * sizeof(double));
  2952. PNM += Waves;
  2953. memcpy(PNM,ZTEMP2,Waves * sizeof(double));
  2954. PNM += Waves;
  2955. HNM[0] = 0.0;
  2956. for (JN = 1; JN < Waves; JN++) HNM[JN] =
  2957. JN * (PMU * ZTEMP1[JN] - sqrt((JN+JN+1.0) / (JN+JN-1.0)) * ZTEMP1[JN-1]);
  2958. HNM += Waves;
  2959. HNM[0] = PMU * ZTEMP2[0];
  2960. for (JN = 1; JN < Waves; JN++)
  2961. HNM[JN] = (JN+1) * PMU * ZTEMP2[JN]
  2962. - sqrt((double)((JN+JN+3) * ((JN+1) * (JN+1) - 1))
  2963. / (double)(JN+JN+1)) * ZTEMP2[JN-1];
  2964. HNM += Waves;
  2965. for (JM = 2; JM < Waves; JM++) {
  2966. PNM[0] = sqrt(1.0 + 1.0 / (JM+JM)) * ZCOS2 * ZTEMP2[0];
  2967. HNM[0] = JM * PMU * PNM[0];
  2968. for (JN = 1; JN < TwoWaves-JM; JN++) {
  2969. ZQ = JM + JM + JN - 1;
  2970. ZWM2 = ZQ+JN;
  2971. ZW = ZWM2+2;
  2972. ZWQ = ZW*ZQ;
  2973. ZQ2M1 = ZQ*ZQ-1.;
  2974. ZWM2Q2 = ZWM2*ZQ2M1;
  2975. Z2Q2 = ZQ2M1*2;
  2976. ZCNM = sqrt((ZWQ*(ZQ-2.))/(ZWM2Q2-Z2Q2));
  2977. ZDNM = sqrt((ZWQ*(JN+1.))/ZWM2Q2);
  2978. ZENM = sqrt(ZW * JN /((ZQ+1.0) * ZWM2));
  2979. PNM[JN] = ZCNM * ZTEMP1[JN] - PMU
  2980. * (ZDNM * ZTEMP1[JN+1] - ZENM * PNM[JN-1]);
  2981. HNM[JN] = (JM + JN) * PMU * PNM[JN]
  2982. - sqrt(ZW * JN * (ZQ+1) / ZWM2) * PNM[JN-1];
  2983. }
  2984. memcpy(ZTEMP1,ZTEMP2,TwoWaves * sizeof(double));
  2985. memcpy(ZTEMP2,PNM ,TwoWaves * sizeof(double));
  2986. PNM += Waves;
  2987. HNM += Waves;
  2988. }
  2989. }
  2990. void legini(void)
  2991. {
  2992. int jlat,jm,jn,jz;
  2993. int jsp,pdim,hdim;
  2994. double *hnm,*pnm,*ZTEMP1,*ZTEMP2,gmusq;
  2995. double znn1,zgmu;
  2996. char tb[COLS+2];
  2997. double poliv,pol2v,pliuv,plivv;
  2998. hdim = 2 * Waves * Waves;
  2999. if (PolyCreate) /* Generate filenames for polynomials */
  3000. {
  3001. sprintf(polin,"b6poli.T%d",Truncation);
  3002. sprintf(pol2n,"b6pol2.T%d",Truncation);
  3003. sprintf(pliun,"b6pliu.T%d",Truncation);
  3004. sprintf(plivn,"b6pliv.T%d",Truncation);
  3005. }
  3006. else if (PolyDisk) /* Generate filenames for polynomials */
  3007. {
  3008. sprintf(polin,"/comm/T1365/b6poli.t%d",Truncation);
  3009. sprintf(pol2n,"/comm/T1365/b6pol2.t%d",Truncation);
  3010. sprintf(pliun,"/comm/T1365/b6pliu.t%d",Truncation);
  3011. sprintf(plivn,"/comm/T1365/b6pliv.t%d",Truncation);
  3012. polif = fopen(polin,"r");
  3013. pol2f = fopen(pol2n,"r");
  3014. pliuf = fopen(pliun,"r");
  3015. plivf = fopen(plivn,"r");
  3016. if (polif && pol2f && pliuf && plivf)
  3017. sprintf(tb,"Legendre Polynomials read from disk");
  3018. else
  3019. {
  3020. sprintf(tb,"Legendre Polynomials calculated");
  3021. PolyDisk = 0;
  3022. }
  3023. CenterText(tb);
  3024. }
  3025. if (PolyDisk) pdim = Lats;
  3026. else pdim = Lats * DimSP_half;
  3027. poli = new double[pdim];
  3028. pol2 = new double[pdim];
  3029. pliu = new double[pdim];
  3030. pliv = new double[pdim];
  3031. pnm = new double[hdim];
  3032. hnm = new double[hdim];
  3033. ZTEMP1 = new double[Fouriers];
  3034. ZTEMP2 = new double[Fouriers];
  3035. // if gridtype for output is not selected, choose Gauss grid
  3036. // for matching resolution and regular grid else
  3037. if (GaussGrid < 0) GaussGrid = (Lats == Gats && Lons == Gons);
  3038. Gaulat = new GauLat(Gats,"Gaulat"); // Gaussian latitudes of input grid
  3039. Outlon = new RegLon(Lons,"Outlon"); // Regular longitudes of output grid
  3040. if (GaussGrid) Outlat = new GauLat(Lats,"Outlat");
  3041. else Outlat = new RegLat(Lats,"Outlat");
  3042. if (Debug)
  3043. {
  3044. Gaulat->PrintArray();
  3045. if (Lats != Gats || !GaussGrid) Outlat->PrintArray();
  3046. Outlon->PrintArray();
  3047. }
  3048. if (PolyCreate)
  3049. {
  3050. polif = fopen(polin,"w");
  3051. pol2f = fopen(pol2n,"w");
  3052. pliuf = fopen(pliun,"w");
  3053. plivf = fopen(plivn,"w");
  3054. for (jlat = 0 ; jlat < Lats ; ++jlat)
  3055. {
  3056. gmusq = 1.0 - Outlat->gmu[jlat] * Outlat->gmu[jlat];
  3057. zgmu = sqrt(gmusq);
  3058. phcs(pnm,hnm,Waves,Outlat->gmu[jlat],ZTEMP1,ZTEMP2);
  3059. for (jm = 0; jm < Waves; jm++)
  3060. {
  3061. for (jn = 0; jn < Waves - jm ; jn++)
  3062. {
  3063. jz = jm+jn;
  3064. znn1 = 0.0;
  3065. if (jz > 0) znn1 = 1.0 / (jz * (jz+1));
  3066. poliv = pnm[jm*Waves+jn] * 2.0;
  3067. fwrite(&poliv,sizeof(double),1,polif);
  3068. pol2v = hnm[jm*Waves+jn] / PlanetRadius;
  3069. fwrite(&pol2v,sizeof(double),1,pol2f);
  3070. pliuv = pnm[jm*Waves+jn] * 2.0 * PlanetRadius * znn1 * jm / zgmu;
  3071. fwrite(&pliuv,sizeof(double),1,pliuf);
  3072. plivv = hnm[jm*Waves+jn] * 2.0 * PlanetRadius * znn1 / zgmu;
  3073. fwrite(&plivv,sizeof(double),1,plivf);
  3074. }
  3075. }
  3076. }
  3077. }
  3078. else if (PolyDisk)
  3079. {
  3080. for (jlat = 0 ; jlat < Lats ; ++jlat)
  3081. {
  3082. gmusq = 1.0 - Outlat->gmu[jlat] * Outlat->gmu[jlat];
  3083. CosPhi[jlat] = sqrt(gmusq);
  3084. RevCosPhi[jlat] = 1.0 / CosPhi[jlat];
  3085. DerivationFactor[jlat] = RevCosPhi[jlat] / PlanetRadius;
  3086. }
  3087. }
  3088. else /* Normal computation of polynomials */
  3089. {
  3090. for (jlat = 0 ; jlat < Lats ; ++jlat)
  3091. {
  3092. gmusq = 1.0 - Outlat->gmu[jlat] * Outlat->gmu[jlat];
  3093. CosPhi[jlat] = sqrt(gmusq);
  3094. RevCosPhi[jlat] = 1.0 / CosPhi[jlat];
  3095. DerivationFactor[jlat] = RevCosPhi[jlat] / PlanetRadius;
  3096. phcs(pnm,hnm,Waves,Outlat->gmu[jlat],ZTEMP1,ZTEMP2);
  3097. jsp = jlat;
  3098. for (jm = 0; jm < Waves; jm++)
  3099. {
  3100. for (jn = 0; jn < Waves - jm ; jn++)
  3101. {
  3102. jz = jm+jn;
  3103. znn1 = 0.0;
  3104. if (jz > 0) znn1 = 1.0 / (jz * (jz+1));
  3105. poli[jsp] = pnm[jm*Waves+jn] * 2.0;
  3106. pol2[jsp] = hnm[jm*Waves+jn] / PlanetRadius;
  3107. pliu[jsp] = pnm[jm*Waves+jn] * 2.0 * PlanetRadius * znn1 * jm / sqrt(gmusq);
  3108. pliv[jsp] = hnm[jm*Waves+jn] * 2.0 * PlanetRadius * znn1 / sqrt(gmusq);
  3109. jsp += Lats;
  3110. }
  3111. }
  3112. }
  3113. }
  3114. delete [] pnm;
  3115. delete [] hnm;
  3116. delete [] ZTEMP1;
  3117. delete [] ZTEMP2;
  3118. }
  3119. void spvfc(double *sd, double *sz, double *fu, double *fv, int klev,int nlat,int nfc,int nt)
  3120. {
  3121. int lev,jmm,jfc,lat;
  3122. double sdr,sdi,szr,szi;
  3123. double *fur,*fui,*fvr,*fvi;
  3124. double *poa,*pob;
  3125. DoubleZero(fu,klev*nlat*nfc);
  3126. DoubleZero(fv,klev*nlat*nfc);
  3127. for (lev = 0; lev < klev; lev++)
  3128. {
  3129. if (PolyDisk)
  3130. {
  3131. rewind(pliuf);
  3132. rewind(plivf);
  3133. }
  3134. poa = pliu;
  3135. pob = pliv;
  3136. for (jmm = 0; jmm <= nt; jmm++)
  3137. {
  3138. for (jfc = jmm; jfc <= nt; jfc++)
  3139. {
  3140. sdr = *sd++;
  3141. sdi = *sd++;
  3142. szr = *sz++;
  3143. szi = *sz++;
  3144. fur = fu ;
  3145. fui = fu + nlat;
  3146. fvr = fv ;
  3147. fvi = fv + nlat;
  3148. if (PolyDisk)
  3149. {
  3150. fread(poa=pliu,sizeof(double),Lats,pliuf);
  3151. fread(pob=pliv,sizeof(double),Lats,plivf);
  3152. }
  3153. for (lat = 0; lat < nlat; lat++)
  3154. {
  3155. *fur += -*pob * szr + *poa * sdi;
  3156. *fui += -*pob * szi - *poa * sdr;
  3157. *fvr += *poa * szi + *pob * sdr;
  3158. *fvi += -*poa * szr + *pob * sdi;
  3159. fur++;
  3160. fui++;
  3161. fvr++;
  3162. fvi++;
  3163. poa++;
  3164. pob++;
  3165. }
  3166. }
  3167. fu += 2 * nlat;
  3168. fv += 2 * nlat;
  3169. }
  3170. }
  3171. }
  3172. // ========================================
  3173. // sp2fci - Inverse Legendre Transformation
  3174. // ========================================
  3175. void sp2fci(double *sa,double *fa,int klev)
  3176. {
  3177. int lev,m,n;
  3178. double sar,sai;
  3179. double *Far,*Fai,*pol;
  3180. DoubleZero(fa,klev*DimFC);
  3181. for (lev = 0; lev < klev; ++lev)
  3182. {
  3183. if (PolyDisk) rewind(polif);
  3184. pol = poli;
  3185. for (n = 0; n <= Truncation; ++n)
  3186. {
  3187. if (PolyDisk) fread(pol=poli,sizeof(double),Lats,polif);
  3188. sar = *sa;
  3189. sa += 2;
  3190. for (Far=fa; Far < fa+Lats;++Far,++pol)
  3191. {
  3192. *Far += *pol * sar;
  3193. }
  3194. }
  3195. fa += 2 * Lats;
  3196. for (m = 1; m <= Truncation; ++m)
  3197. {
  3198. for (n = m; n <= Truncation; ++n)
  3199. {
  3200. if (PolyDisk) fread(pol=poli,sizeof(double),Lats,polif);
  3201. sar = *sa++ ;
  3202. sai = *sa++ ;
  3203. for (Far=fa,Fai=fa+Lats; Far<fa+Lats; ++Far,++Fai,++pol)
  3204. {
  3205. *Far += *pol * sar;
  3206. *Fai += *pol * sai;
  3207. }
  3208. }
  3209. fa += 2 * Lats;
  3210. }
  3211. }
  3212. }
  3213. void sp2fcd(double *sa,double *fa,int klev,int nlat,int nfc,int nt)
  3214. {
  3215. int lev,jmm,jfc,lat;
  3216. double sar,sai;
  3217. double *Far,*fai,*pol;
  3218. double zpo;
  3219. DoubleZero(fa,klev*nlat*nfc);
  3220. for (lev = 0; lev < klev; lev++)
  3221. {
  3222. pol = pol2;
  3223. if (PolyDisk) rewind(pol2f);
  3224. for (jmm = 0; jmm <= nt; jmm++)
  3225. {
  3226. for (jfc = jmm; jfc <= nt; jfc++)
  3227. {
  3228. sar = *sa++ ;
  3229. sai = *sa++ ;
  3230. Far = fa ;
  3231. fai = fa + nlat ;
  3232. if (PolyDisk) fread(pol=pol2,sizeof(double),Lats,pol2f);
  3233. for (lat = 0; lat < nlat; lat++)
  3234. {
  3235. zpo = -2.0 * *pol * RevCosPhi[lat];
  3236. *Far += zpo * sar;
  3237. *fai += zpo * sai;
  3238. Far++;
  3239. fai++;
  3240. pol++;
  3241. }
  3242. }
  3243. fa += 2 * nlat;
  3244. }
  3245. }
  3246. }
  3247. void fc2sp(double *fa, double *sa, int klev, int nlat, int nt)
  3248. {
  3249. int lev,jmm,jfc,lat;
  3250. double sar,sai,*Far,*fai,*pol;
  3251. double zpo;
  3252. for (lev = 0; lev < klev; lev++)
  3253. {
  3254. pol = poli;
  3255. if (PolyDisk) rewind(polif);
  3256. for (jmm = 0; jmm <= nt; jmm++)
  3257. {
  3258. for (jfc = jmm; jfc <= nt; jfc++)
  3259. {
  3260. Far = fa ;
  3261. fai = fa + nlat ;
  3262. sar = 0.0 ;
  3263. sai = 0.0 ;
  3264. if (PolyDisk) fread(pol=poli,sizeof(double),Lats,polif);
  3265. for (lat = 0; lat < nlat; lat++)
  3266. {
  3267. zpo = *pol * 0.5 * Outlat->gwt[lat];
  3268. sar += zpo * *Far;
  3269. sai += zpo * *fai;
  3270. Far++;
  3271. fai++;
  3272. pol++;
  3273. }
  3274. *sa++ = sar;
  3275. *sa++ = sai;
  3276. }
  3277. fa += 2 * nlat;
  3278. }
  3279. }
  3280. }
  3281. void OMEGA(void)
  3282. {
  3283. int i,j;
  3284. double DeltaHybrid;
  3285. double Cterm;
  3286. double Pterm;
  3287. double *omega = &Omega->hgp[0];
  3288. double *diver = &Divergence->hgp[0];
  3289. double *halfp = &HalfPress->hgp[0];
  3290. double *fullp = &FullPress->hgp[0];
  3291. double *uwind = &u_wind->hgp[0];
  3292. double *vwind = &v_wind->hgp[0];
  3293. /* Compute half level part of vertical velocity */
  3294. for (i = 0; i < DimGP ; i++) omega[i] = 0.0;
  3295. for (j = 0; j < SigLevs; j++) {
  3296. DeltaHybrid = vct[SigLevs+j+2] - vct[SigLevs+j+1];
  3297. for (i = 0; i < DimGP; i++) {
  3298. omega[DimGP] = *omega
  3299. - *diver * (halfp[DimGP] - *halfp) - DeltaHybrid
  3300. * (*uwind * dpsdx->hgp[i]
  3301. + *vwind * dpsdy->hgp[i]);
  3302. omega++;
  3303. halfp++;
  3304. diver++;
  3305. uwind++;
  3306. vwind++;
  3307. }
  3308. }
  3309. /* interpolate to full levels */
  3310. omega = &Omega->hgp[0];
  3311. for (i = 0; i < Dim3GP; i++)
  3312. omega[i] = 0.5 * (omega[i] + omega[i+DimGP]);
  3313. /* compute full level part of vertical velocity */
  3314. omega = &Omega->hgp[0];
  3315. halfp = &HalfPress->hgp[0];
  3316. fullp = &FullPress->hgp[0];
  3317. uwind = &u_wind->hgp[0];
  3318. vwind = &v_wind->hgp[0];
  3319. for (j = 0; j < SigLevs; j++) {
  3320. DeltaHybrid = vct[SigLevs+j+2] - vct[SigLevs+j+1];
  3321. if (DeltaHybrid) {
  3322. Cterm = vct[j+1] * vct[SigLevs+j+1] - vct[j] * vct[SigLevs+j+2];
  3323. for (i = 0; i < DimGP; i++) {
  3324. if (Cterm != 0.0) Pterm = Cterm /
  3325. (halfp[DimGP] - *halfp) * log(halfp[DimGP] / *halfp);
  3326. else Pterm = 0.0;
  3327. *omega += *fullp *
  3328. (*uwind * dpsdx->hgp[i] + *vwind * dpsdy->hgp[i])
  3329. / (halfp[DimGP] - *halfp) * (DeltaHybrid + Pterm);
  3330. omega++;
  3331. halfp++;
  3332. fullp++;
  3333. uwind++;
  3334. vwind++;
  3335. }
  3336. }
  3337. else {
  3338. omega += DimGP;
  3339. halfp += DimGP;
  3340. fullp += DimGP;
  3341. uwind += DimGP;
  3342. vwind += DimGP;
  3343. }
  3344. }
  3345. }
  3346. void Omega_w(double w[], double om[], double T[], double P[])
  3347. {
  3348. int i;
  3349. for (i=0 ; i < Dim3GP ; ++i)
  3350. {
  3351. w[i] = -om[i] * RD * T[i] / (Grav * P[i]);
  3352. }
  3353. }
  3354. void Extrap(double *slp, double *aph, double *apf,
  3355. double *Geopotential, double *t, int nhor)
  3356. {
  3357. double zrg = 1.0 / Grav;
  3358. double alpha,tstar,tmsl,ZPRT,ZPRTAL;
  3359. int j;
  3360. for (j = 0; j < nhor; ++j) {
  3361. if (Geopotential[j] < 0.0001 && Geopotential[j] > -0.0001) slp[j] = aph[j];
  3362. else {
  3363. alpha = RD * RLAPSE * zrg;
  3364. tstar = (1.0 + alpha * (aph[j]/apf[j] - 1.0)) * t[j];
  3365. if (tstar < 255.0) tstar = 0.5 * (255.0 + tstar);
  3366. tmsl = tstar + RLAPSE * zrg * Geopotential[j];
  3367. if (tmsl > 290.5 && tstar > 290.5) {
  3368. tstar = 0.5 * (290.5 + tstar);
  3369. tmsl = tstar;
  3370. }
  3371. if (tmsl-tstar < 0.000001 && tstar-tmsl < 0.000001) alpha = 0.0;
  3372. else if (Geopotential[j] > 0.0001 || Geopotential[j] < -0.0001)
  3373. alpha = RD * (tmsl-tstar) / Geopotential[j];
  3374. ZPRT = Geopotential[j] / (RD * tstar);
  3375. ZPRTAL = ZPRT * alpha;
  3376. slp[j] = aph[j] * exp(ZPRT*(1.0-ZPRTAL*(0.5-ZPRTAL/3.0)));
  3377. }
  3378. }
  3379. }
  3380. double ExtraT(double PRES, double APH, double APF, double GEOS, double T)
  3381. {
  3382. double zrg = 1.0 / Grav;
  3383. double tstar,ztsz,Z1,ZTMSL,ZALPH,PEVAL,ZHTS,ZALP;
  3384. tstar = (1.0 + RLAPSE * RD * zrg * (APH/APF - 1.0)) * T;
  3385. ztsz = tstar;
  3386. Z1 = tstar + RLAPSE * zrg * GEOS;
  3387. if (tstar < 255.0) tstar = 0.5 * (255.0 + tstar);
  3388. ZTMSL = tstar + RLAPSE * zrg * GEOS;
  3389. if (ZTMSL > 290.5 && tstar > 290.5)
  3390. {
  3391. tstar = 0.5 * (290.5 + tstar);
  3392. ZTMSL = tstar;
  3393. }
  3394. if (ZTMSL > 290.5 && tstar <= 290.5) ZTMSL=290.5;
  3395. ZALPH=RD*RLAPSE*zrg;
  3396. if ( ZTMSL-tstar < 0.000001 && tstar-ZTMSL < 0.000001) ZALPH=0.0;
  3397. if ((ZTMSL-tstar > 0.000001 || tstar-ZTMSL > 0.000001) &&
  3398. (GEOS > 0.0001 || GEOS < -0.0001))
  3399. ZALPH=RD*(ZTMSL-tstar)/GEOS;
  3400. if (PRES <= APH) PEVAL = ((APH-PRES)*T+ (PRES-APF)*tstar)/ (APH-APF);
  3401. else
  3402. {
  3403. ZTMSL=Z1;
  3404. tstar=ztsz;
  3405. ZHTS=GEOS*zrg;
  3406. if (ZHTS > 2000. && Z1 > 298.)
  3407. {
  3408. ZTMSL=298.;
  3409. if (ZHTS < 2500.) ZTMSL=0.002*((2500.-ZHTS)*Z1+(ZHTS-2000.)*ZTMSL);
  3410. }
  3411. if ((ZTMSL-tstar) < 0.000001) ZALPH=0.;
  3412. else if (GEOS > 0.0001 || GEOS < -0.0001) ZALPH=RD*(ZTMSL-tstar)/GEOS;
  3413. else ZALPH=RD*RLAPSE*zrg;
  3414. ZALP=ZALPH*log(PRES/APH);
  3415. PEVAL=tstar*(1.0+ZALP*(1.0+ZALP*(0.5+0.16666666667*ZALP)));
  3416. }
  3417. return PEVAL;
  3418. }
  3419. double ExtraZ(double pres, double aph, double apf, double sg, double t)
  3420. {
  3421. double zrg = 1.0 / Grav;
  3422. double alpha,tstar,tmsl,ZALP,ZALPAL;
  3423. alpha = RD * RLAPSE * zrg;
  3424. tstar = (1.0 + alpha * (aph/apf - 1.0)) * t;
  3425. if (tstar < 255.0) tstar = 0.5 * (255.0 + tstar);
  3426. tmsl = tstar + RLAPSE * zrg * sg;
  3427. if (tmsl > 290.5 && tstar > 290.5)
  3428. {
  3429. tstar = 0.5 * (290.5 + tstar);
  3430. tmsl = tstar;
  3431. }
  3432. if (tmsl > 290.5 && tstar <= 290.5) tmsl = 290.5;
  3433. if (tmsl-tstar < 0.000001 && tstar-tmsl < 0.000001) alpha = 0.0;
  3434. else if (sg > 0.0001 || sg < -0.0001) alpha = RD * (tmsl-tstar) / sg;
  3435. ZALP = log(pres/aph);
  3436. ZALPAL = ZALP * alpha;
  3437. return (sg - RD * tstar * ZALP * (1.0 + ZALPAL * (0.5 + ZALPAL/6.0))) * zrg;
  3438. }
  3439. void Interpolate_T(int Code)
  3440. {
  3441. int lp, i;
  3442. int nl,nh;
  3443. double pres;
  3444. int *nx = vert_index;
  3445. double *gt = &All[Code].hgp[0];
  3446. double *pt = &All[Code].pgp[0];
  3447. double *pf = &FullPress->hgp[0];
  3448. double *ph = &HalfPress->hgp[0];
  3449. for (lp = 0; lp < OutLevs; lp++)
  3450. {
  3451. pres = level[lp];
  3452. for (i = 0; i < DimGP; i++)
  3453. {
  3454. nl = i + DimGP * *nx;
  3455. nh = nl + DimGP;
  3456. if (nl < 0) // Above top level
  3457. {
  3458. *pt = gt[i];
  3459. }
  3460. else if (nh >= Dim3GP) // Below bottom level
  3461. {
  3462. if (!mars && Code == TCODE) *pt = ExtraT(pres,ph[nh],pf[nl],Orography[i],gt[nl]);
  3463. else *pt = gt[nl];
  3464. }
  3465. else // Inside
  3466. {
  3467. *pt = gt[nl] + (pres-pf[nl]) * (gt[nh]-gt[nl]) / (pf[nh]-pf[nl]);
  3468. }
  3469. ++nx;
  3470. ++pt;
  3471. }
  3472. }
  3473. }
  3474. void Interpolate_Z(void)
  3475. {
  3476. int lp, i;
  3477. int nl,nh;
  3478. double pres;
  3479. int *nx = vert_index;
  3480. double *gz = &GeopotHeight->hgp[0];
  3481. double *pz = &GeopotHeight->pgp[0];
  3482. double *gt = &Temperature->hgp[0];
  3483. double *pf = &FullPress->hgp[0];
  3484. double *ph = &HalfPress->hgp[0];
  3485. for (lp = 0; lp < OutLevs; lp++)
  3486. {
  3487. pres = level[lp];
  3488. for (i = 0; i < DimGP; i++)
  3489. {
  3490. nl = i + DimGP * *nx;
  3491. if (pres > ph[nl+DimGP]) nl += DimGP;
  3492. nh = nl + DimGP;
  3493. if (nl < 0) // Above top level
  3494. {
  3495. *pz = gz[i];
  3496. }
  3497. else if (nl >= Dim3GP) // Below bottom level
  3498. {
  3499. if (mars) *pz = gz[nl-DimGP];
  3500. else *pz = ExtraZ(pres,ph[nl], pf[nl-DimGP],Orography[i],gt[nl-DimGP]);
  3501. }
  3502. else // Inside
  3503. {
  3504. *pz = gz[nl] + (pres-ph[nl]) * (gz[nh]-gz[nl]) / (ph[nh] - ph[nl]);
  3505. }
  3506. ++nx;
  3507. ++pz;
  3508. }
  3509. }
  3510. }
  3511. void CheckDependencies(void)
  3512. {
  3513. u_wind->needed = ( Divergence->needed && !Divergence->detected) ||
  3514. ( Vorticity->needed && !Vorticity->detected) ||
  3515. ( VeloPot->needed && !VeloPot->detected) ||
  3516. ( StreamF->needed && !StreamF->detected) ||
  3517. ( Omega->needed && !Omega->detected) ||
  3518. ( speed->needed && !speed->detected) ||
  3519. ( v_wind->needed && !v_wind->detected) ||
  3520. u_wind->selected;
  3521. v_wind->needed = ( Divergence->needed && !Divergence->detected) ||
  3522. ( Vorticity->needed && !Vorticity->detected) ||
  3523. ( VeloPot->needed && !VeloPot->detected) ||
  3524. ( StreamF->needed && !StreamF->detected) ||
  3525. ( Omega->needed && !Omega->detected) ||
  3526. ( speed->needed && !speed->detected) ||
  3527. ( u_wind->needed && !u_wind->detected) ||
  3528. v_wind->selected;
  3529. Divergence->needed = ( u_wind->needed && !u_wind->detected) ||
  3530. ( v_wind->needed && !v_wind->detected) ||
  3531. ( Omega->needed && !Omega->detected) ||
  3532. ( VeloPot->needed && !VeloPot->detected) ||
  3533. Divergence->selected;
  3534. Vorticity->needed = ( u_wind->needed && !u_wind->detected) ||
  3535. ( v_wind->needed && !v_wind->detected) ||
  3536. ( StreamF->needed && !StreamF->detected) ||
  3537. Vorticity->selected;
  3538. Humidity->needed = (GeopotHeight->needed && !GeopotHeight->detected) ||
  3539. ( Rhumidity->needed && !Rhumidity->detected) ||
  3540. Humidity->selected;
  3541. Ps->needed |= dpsdx->needed || dpsdy->needed ||
  3542. Rhumidity->needed || Omega->needed;
  3543. LnPs->needed |= Ps->needed;
  3544. Temperature->needed = (GeopotHeight->needed && !GeopotHeight->detected) ||
  3545. ( Rhumidity->needed && !Rhumidity->detected) ||
  3546. ( SLP->needed && !SLP->detected) ||
  3547. ( w_wind->needed && !w_wind->detected) ||
  3548. Temperature->selected;
  3549. All[176].needed = ( net_heat->needed && !net_heat->detected) ||
  3550. ( net_bot->needed && !net_bot->detected) ||
  3551. ( net_atm->needed && !net_atm->detected) ||
  3552. ( sw_atm->needed && !sw_atm->detected) ||
  3553. All[176].selected;
  3554. All[177].needed = ( net_heat->needed && !net_heat->detected) ||
  3555. ( net_bot->needed && !net_bot->detected) ||
  3556. ( net_atm->needed && !net_atm->detected) ||
  3557. ( lw_atm->needed && !lw_atm->detected) ||
  3558. All[177].selected;
  3559. All[178].needed = ( net_top->needed && !net_top->detected) ||
  3560. ( net_atm->needed && !net_atm->detected) ||
  3561. ( sw_atm->needed && !sw_atm->detected) ||
  3562. All[178].selected;
  3563. All[179].needed = ( net_top->needed && !net_top->detected) ||
  3564. ( net_atm->needed && !net_atm->detected) ||
  3565. ( lw_atm->needed && !lw_atm->detected) ||
  3566. All[179].selected;
  3567. }
  3568. void CheckContent(void)
  3569. {
  3570. int code;
  3571. for (code = 0; code < 256; code++)
  3572. {
  3573. if (code == GEOSCODE) continue;
  3574. if (code == SLPCODE) continue;
  3575. if (code == ZCODE) continue;
  3576. if (code == STRCODE) continue;
  3577. if (code == VELCODE) continue;
  3578. if (code == UCODE) continue;
  3579. if (code == VCODE) continue;
  3580. if (code == WCODE) continue;
  3581. if (code == RHCODE) continue;
  3582. if (code == PSCODE) continue;
  3583. if (code == WZCODE) continue;
  3584. if (code == SHCODE)
  3585. {
  3586. if (All[code].needed && !All[code].selected &&
  3587. All[code].hsp.size() == 0 &&
  3588. All[code].hgp.size() == 0 &&
  3589. HumInfo == 0)
  3590. {
  3591. printf("\n ********* I N F O **********\n");
  3592. printf( " * No humidity in data file *\n");
  3593. printf( " * Humidity set to zero ! *\n");
  3594. printf( " ****************************\n");
  3595. All[code].needed = FALSE;
  3596. HumInfo = 1;
  3597. }
  3598. }
  3599. else
  3600. {
  3601. if (All[code].needed &&
  3602. All[code].hsp.size() == 0 &&
  3603. All[code].hgp.size() == 0)
  3604. {
  3605. printf("\n ****** E R R O R ******\n");
  3606. printf(" * Code %3d not found *\n",code);
  3607. printf(" ***********************\n");
  3608. exit(1);
  3609. }
  3610. }
  3611. }
  3612. }
  3613. void Dependencies(void)
  3614. {
  3615. int code;
  3616. for (code = 0; code < CODES; code++)
  3617. All[code].needed = All[code].selected;
  3618. CheckDependencies();
  3619. if (OutRep >= PRE_GRID)
  3620. {
  3621. u_wind->needed |= Divergence->needed;
  3622. v_wind->needed |= Divergence->needed;
  3623. u_wind->needed |= Vorticity->needed;
  3624. v_wind->needed |= Vorticity->needed;
  3625. u_wind->needed |= VeloPot->needed;
  3626. v_wind->needed |= VeloPot->needed;
  3627. u_wind->needed |= StreamF->needed;
  3628. v_wind->needed |= StreamF->needed;
  3629. }
  3630. Omega->needed |= w_wind->needed;
  3631. dpsdx->needed |= Omega->needed;
  3632. dpsdy->needed |= Omega->needed;
  3633. if (VerType == 'p')
  3634. {
  3635. LnPs->needed = TRUE;
  3636. Divergence->needed |= Omega->needed;
  3637. u_wind->needed |= Omega->needed;
  3638. v_wind->needed |= Omega->needed;
  3639. u_wind->needed |= speed->needed;
  3640. v_wind->needed |= speed->needed;
  3641. Temperature->needed |= Omega->needed || SLP->needed;
  3642. Humidity->needed |= GeopotHeight->needed || Rhumidity->needed;
  3643. Temperature->needed |= GeopotHeight->needed || Rhumidity->needed ||
  3644. ThetaF->needed;
  3645. }
  3646. Divergence->needed |= u_wind->needed || v_wind->needed;
  3647. Vorticity->needed |= u_wind->needed || v_wind->needed;
  3648. Divergence->needed |= VeloPot->needed;
  3649. Vorticity->needed |= StreamF->needed;
  3650. LnPs->needed |= HalfPress->needed || dpsdx->needed ||
  3651. Ps->needed || Rhumidity->needed;
  3652. All[139].needed |= ThetaF->selected;
  3653. All[142].needed |= precip->selected || net_water->selected ||
  3654. fresh_water->selected || surf_runoff->selected;
  3655. All[143].needed |= precip->selected || net_water->selected ||
  3656. fresh_water->selected || surf_runoff->selected;
  3657. All[146].needed |= net_heat->selected; /* sensible heat */
  3658. All[147].needed |= net_heat->selected; /* latent heat */
  3659. All[160].needed |= net_water->selected; /* Runoff */
  3660. All[176].needed |= net_heat->selected ||
  3661. net_bot->selected ||
  3662. net_atm->selected || sw_atm->selected;
  3663. All[177].needed |= net_heat->selected ||
  3664. net_bot->selected ||
  3665. net_atm->selected || lw_atm->selected;
  3666. All[178].needed |= net_top->selected ||
  3667. net_atm->selected || sw_atm->selected;
  3668. All[179].needed |= net_top->selected ||
  3669. net_atm->selected || lw_atm->selected;
  3670. All[182].needed |= net_water->selected ||
  3671. fresh_water->selected || surf_runoff->selected;
  3672. All[218].needed |= net_heat->selected; /* snow melt */
  3673. All[221].needed |= surf_runoff->selected; /* snow depth change */
  3674. }
  3675. void Speed(double *speed, double *u, double *v)
  3676. {
  3677. int i;
  3678. for (i = 0; i < Dim3GP; i++)
  3679. speed[i] = sqrt(u[i] * u[i] + v[i] * v[i]);
  3680. }
  3681. // ======================================================
  3682. // Compute derivation d(LnPs)/d(sin phi) in fourier space
  3683. // ======================================================
  3684. void Deriva(double field[], double derilam[])
  3685. {
  3686. int l,n;
  3687. int i;
  3688. i = 0;
  3689. for (n = 0; n < Waves ; n++)
  3690. {
  3691. for (l = 0; l < Lats; l++,i++) // cosine coefficients
  3692. derilam[i] = -n * field[i+Lats] * DerivationFactor[l];
  3693. for (l = 0; l < Lats; l++,i++) // sine coefficients
  3694. derilam[i] = n * field[i-Lats] * DerivationFactor[l];
  3695. }
  3696. }
  3697. void scaluv(double *fu, double Factor[], int nlat, int nlot)
  3698. {
  3699. for (int lot = 0; lot < nlot; lot++)
  3700. for (int lat = 0; lat < nlat; lat++)
  3701. {
  3702. *fu++ *= Factor[lat];
  3703. }
  3704. }
  3705. void uv2dv(double *fu, double *fv, double *sd, double *sv,
  3706. double *pol2, double *poli, int klev, int nlat, int nt)
  3707. {
  3708. int lev,jmm,jfc,lat;
  3709. double dir,dii,vor,voi;
  3710. double *ufr,*ufi,*vfr,*vfi;
  3711. double *po2,*pod;
  3712. double zo2, zod;
  3713. double gmuq;
  3714. for (lev = 0; lev < klev; lev++)
  3715. {
  3716. if (PolyDisk)
  3717. {
  3718. rewind(pol2f);
  3719. rewind(polif);
  3720. }
  3721. po2 = pol2;
  3722. pod = poli;
  3723. for (jmm = 0; jmm <= nt; jmm++)
  3724. {
  3725. for (jfc = jmm; jfc <= nt; jfc++)
  3726. {
  3727. ufr = fu ;
  3728. ufi = fu + nlat ;
  3729. vfr = fv ;
  3730. vfi = fv + nlat ;
  3731. dir = 0.0 ;
  3732. dii = 0.0 ;
  3733. vor = 0.0 ;
  3734. voi = 0.0 ;
  3735. if (PolyDisk)
  3736. {
  3737. fread(po2=pol2,sizeof(double),Lats,pol2f);
  3738. fread(pod=poli,sizeof(double),Lats,polif);
  3739. }
  3740. for (lat = 0; lat < nlat; lat++)
  3741. {
  3742. gmuq = 1.0 - Outlat->gmu[lat] * Outlat->gmu[lat];
  3743. zod = *pod * 0.5 * jmm * Outlat->gwt[lat] / (PlanetRadius * gmuq);
  3744. zo2 = *po2 * Outlat->gwt[lat] / gmuq;
  3745. dir += *vfr * zo2 - *ufi * zod;
  3746. dii += *vfi * zo2 + *ufr * zod;
  3747. vor -= *ufr * zo2 + *vfi * zod;
  3748. voi -= *ufi * zo2 - *vfr * zod;
  3749. ufr++;
  3750. ufi++;
  3751. vfr++;
  3752. vfi++;
  3753. po2++;
  3754. pod++;
  3755. }
  3756. *sd++ = dir;
  3757. *sd++ = dii;
  3758. *sv++ = vor;
  3759. *sv++ = voi;
  3760. }
  3761. fu += 2 * nlat;
  3762. fv += 2 * nlat;
  3763. }
  3764. }
  3765. }
  3766. void genind(int *Interpolation_Index, double lv[],
  3767. double *Full_Level_Pressure, int DimGP, int OutLevs)
  3768. {
  3769. int h,k,l;
  3770. int *nx;
  3771. double Pressure,*pf;
  3772. nx = Interpolation_Index;
  3773. for (h=0 ; h < DimGP * OutLevs ; ++h) nx[h] = -1;
  3774. for (k = 0; k<OutLevs; k++)
  3775. {
  3776. Pressure = lv[k];
  3777. pf = Full_Level_Pressure;
  3778. for (l = 0; l<SigLevs; l++)
  3779. for (h = 0; h<DimGP ; h++)
  3780. {
  3781. if (Pressure > *pf) nx[h] = l;
  3782. pf++;
  3783. }
  3784. nx += DimGP;
  3785. }
  3786. }
  3787. void theta(double *PThetaF, double *PThetaH, double *PH, double *PS,
  3788. double *TF, double *TS, int DimGP, int Dim3GP)
  3789. {
  3790. int h,l;
  3791. double Kappa = RD / RCPD;
  3792. double *ThetaH = PThetaH;
  3793. double *ThetaF = PThetaF;
  3794. for (h = 0; h < DimGP; h++) ThetaH[h] = 0.0;
  3795. ThetaH += DimGP;
  3796. for (l = 0; l < SigLevs - 1; l++)
  3797. {
  3798. for (h = 0; h < DimGP; h++)
  3799. {
  3800. ThetaH[h] = 0.5 * (TF[h] + TF[h+DimGP]) * pow((PS[h]/PH[h]),Kappa);
  3801. }
  3802. PH += DimGP;
  3803. TF += DimGP;
  3804. ThetaH += DimGP;
  3805. }
  3806. memcpy(ThetaH,TS,DimGP * sizeof(double));
  3807. ThetaH = PThetaH;
  3808. for (h = 0; h < Dim3GP; h++)
  3809. {
  3810. ThetaF[h] = 0.5 * (ThetaH[h] + ThetaH[h+DimGP]);
  3811. }
  3812. }
  3813. void presh(double *pf, double *php, double *vct, double *ps)
  3814. {
  3815. int h,l;
  3816. double zp,ze;
  3817. double *ph = php;
  3818. for (l = 0; l<SigLevs; l++)
  3819. {
  3820. zp = vct[l];
  3821. ze = vct[l+SigLevs+1];
  3822. for (h = 0; h<DimGP; h++) ph[h] = zp + ze * ps[h];
  3823. ph += DimGP;
  3824. }
  3825. memcpy(ph,ps,DimGP * sizeof(double));
  3826. ph = php;
  3827. for (h = 0; h<Dim3GP; h++) pf[h] = 0.5 * (ph[h] + ph[h+DimGP]);
  3828. }
  3829. /*****************************/
  3830. /* Compute relative humidity */
  3831. /*****************************/
  3832. double relhum(double q, double t, double p)
  3833. {
  3834. double rh;
  3835. double gascon;
  3836. double rv;
  3837. double TMELT;
  3838. double ra1;
  3839. double ra2;
  3840. double ra4;
  3841. double rdbrv;
  3842. double zqsat;
  3843. rv = 461.51;
  3844. TMELT = 273.16;
  3845. gascon = 287.0 ;
  3846. ra1 = 610.78;
  3847. ra2 = 17.2693882;
  3848. ra4 = 35.86;
  3849. rdbrv = gascon / rv;
  3850. zqsat = rdbrv * ra1 * exp(ra2 * (t-TMELT) / (t-ra4)) / p;
  3851. zqsat *= 1.0 / (1.0 - (1.0 / rdbrv - 1.0) * zqsat);
  3852. rh = q * 100.0 / zqsat;
  3853. if (rh < 0.0) rh = 0.0;
  3854. if (rh > 100.0) rh = 100.0;
  3855. return rh;
  3856. }
  3857. /*****************************/
  3858. /* Compute relative humidity */
  3859. /*****************************/
  3860. void sh2rh(double *sphum, double *rhum, double *t, int lev)
  3861. {
  3862. int jhor,jlev;
  3863. double *pp; // pressure
  3864. pp = &FullPress->hgp[0];
  3865. for (jlev = 0; jlev < lev; jlev++)
  3866. for (jhor = 0; jhor < DimGP; jhor++)
  3867. *rhum++ = relhum(*sphum++,*t++,*pp++);
  3868. }
  3869. void dv2ps(double *div, double *pot, int lev)
  3870. {
  3871. for (int l = 0; l < lev ; l++)
  3872. for (int m = 0; m <= Truncation; m++)
  3873. for (int n = m; n <= Truncation; n++)
  3874. {
  3875. if (n)
  3876. {
  3877. *pot++ = *div++ * SQUARE_RADIUS / (n * n + n);
  3878. *pot++ = *div++ * SQUARE_RADIUS / (n * n + n);
  3879. }
  3880. else
  3881. {
  3882. *pot++ = 0.0;
  3883. *pot++ = 0.0;
  3884. div += 2;
  3885. }
  3886. }
  3887. }
  3888. void MakeGeopotHeight(double *geop, double* gt, double *gq, double *ph, int nhor, int nlev)
  3889. {
  3890. int i;
  3891. double VTMP = (RV / RD) - 1.0;
  3892. double zrg = 1.0 / Grav;
  3893. if (gq) /* Humidity is present */ {
  3894. for (i = nhor * nlev - 1; i >= nhor; i--)
  3895. geop[i] = geop[i+nhor] + RD * gt[i] * (1.0 + VTMP * gq[i])
  3896. * log(ph[i+nhor] / ph[i]);
  3897. for (i = 0; i < nhor; i++)
  3898. geop[i] = geop[i+nhor] + RD * gt[i] * (1.0 + VTMP * gq[i])
  3899. * 2.0 * log(2.0);
  3900. }
  3901. else /* No humidity */ {
  3902. for (i = nhor * nlev - 1; i >= nhor; i--)
  3903. geop[i] = geop[i+nhor] + RD * gt[i] * log(ph[i+nhor] / ph[i]);
  3904. for (i = 0; i < nhor; i++)
  3905. geop[i] = geop[i+nhor] + RD * gt[i] * 2.0 * log(2.0);
  3906. }
  3907. for (i = 0; i < nhor * (nlev+1); i++) geop[i] *= zrg;
  3908. }
  3909. void gp2fc_uv(void)
  3910. {
  3911. u_wind->SetPFour();
  3912. v_wind->SetPFour();
  3913. gp2fc(&u_wind->pgp[0],&u_wind->pfc[0],Lats,Lons,OutLevs,Fouriers);
  3914. gp2fc(&v_wind->pgp[0],&v_wind->pfc[0],Lats,Lons,OutLevs,Fouriers);
  3915. }
  3916. void fc2sp_uv(void)
  3917. {
  3918. scaluv(&u_wind->pfc[0],CosPhi,Lats,Fouriers*OutLevs);
  3919. scaluv(&v_wind->pfc[0],CosPhi,Lats,Fouriers*OutLevs);
  3920. u_wind->SetPSpec();
  3921. v_wind->SetPSpec();
  3922. Divergence->SetPSpec();
  3923. Vorticity->SetPSpec();
  3924. fc2sp(&u_wind->pfc[0],&u_wind->psp[0],OutLevs,Lats,Truncation);
  3925. fc2sp(&v_wind->pfc[0],&v_wind->psp[0],OutLevs,Lats,Truncation);
  3926. uv2dv(&u_wind->pfc[0],&v_wind->pfc[0],
  3927. &Divergence->psp[0],&Vorticity->psp[0],pol2,poli,OutLevs,Lats,Truncation);
  3928. if (VeloPot->needed)
  3929. {
  3930. VeloPot->plev = OutLevs;
  3931. VeloPot->SetPSpec();
  3932. dv2ps(&Divergence->psp[0],&VeloPot->psp[0],OutLevs);
  3933. }
  3934. if (StreamF->needed)
  3935. {
  3936. StreamF->plev = OutLevs;
  3937. StreamF->SetPSpec();
  3938. dv2ps(&Vorticity->psp[0],&StreamF->psp[0],OutLevs);
  3939. }
  3940. }
  3941. void sp2fc_uv(void)
  3942. {
  3943. for (int si = 0 ; si < 4 ; ++si)
  3944. {
  3945. int code = SpecialCodes[si];
  3946. if (All[code].selected && All[code].psp.size())
  3947. {
  3948. All[code].SetPFour();
  3949. sp2fci(&All[code].psp[0],&All[code].pfc[0],OutLevs);
  3950. }
  3951. }
  3952. if (u_wind->selected && u_wind->pfc.size())
  3953. scaluv(&u_wind->pfc[0],RevCosPhi,Lats,Fouriers*OutLevs);
  3954. if (v_wind->selected && v_wind->pfc.size())
  3955. scaluv(&v_wind->pfc[0],RevCosPhi,Lats,Fouriers*OutLevs);
  3956. }
  3957. void fc2gp_uv(void)
  3958. {
  3959. for (int si = 0 ; si < 4 ; ++si)
  3960. {
  3961. int code = SpecialCodes[si];
  3962. if (All[code].selected && All[code].pfc.size())
  3963. {
  3964. All[code].SetPGrid();
  3965. fc2gp(&All[code].pfc[0],&All[code].pgp[0],Lats,Lons,OutLevs,Fouriers);
  3966. }
  3967. }
  3968. }
  3969. void PumaProcess(void)
  3970. {
  3971. int code;
  3972. MeanCount++; // Count term inside month
  3973. TermCount++; // Count term
  3974. #ifdef NETCDF_OUTPUT
  3975. if (TermCount == 1 && NetCDF) NetVarDefine(); // Define NetCDF variables
  3976. #endif
  3977. if (MeanCount == 1) CheckContent(); // Everything OK ?
  3978. if (TermCount > 60) Debug = 0; // Limit debug output
  3979. // Reset level offset for all variables
  3980. for (code = 0; code < CODES; code++) All[code].loff = 0;
  3981. // Derive velocity potential and streamfunction from divergence and vorticity
  3982. if (VeloPot->needed && !VeloPot->detected && VerType == 's')
  3983. {
  3984. VeloPot->SetHSpec(SigLevs,OutLevs,FALSE);
  3985. dv2ps(&Divergence->hsp[0],&VeloPot->hsp[0],SigLevs);
  3986. }
  3987. if (StreamF->needed && !StreamF->detected && VerType == 's')
  3988. {
  3989. StreamF->SetHSpec(SigLevs,OutLevs,FALSE);
  3990. dv2ps(&Vorticity->hsp[0],&StreamF->hsp[0],SigLevs);
  3991. }
  3992. // -------------------------
  3993. // Output of spectral fields
  3994. // -------------------------
  3995. if (OutRep == HYB_SPEC)
  3996. {
  3997. HybSpec->Write_hspec();
  3998. return;
  3999. }
  4000. // =====================================================
  4001. // Transformation from spectral domain to fourier domain
  4002. // =====================================================
  4003. // Derive wind components u*cos(phi) and v*cos(phi)
  4004. if ((u_wind->needed || v_wind->needed) &&
  4005. (!u_wind->detected || !v_wind->detected))
  4006. {
  4007. u_wind->SetHFour(SigLevs,OutLevs,FALSE);
  4008. v_wind->SetHFour(SigLevs,OutLevs,FALSE);
  4009. spvfc(&Divergence->hsp[0],&Vorticity->hsp[0],
  4010. &u_wind->hfc[0] ,&v_wind->hfc[0] ,
  4011. Divergence->hlev ,Lats,Fouriers,Truncation);
  4012. }
  4013. // If divergence and vorticity were needed for u and v computation
  4014. // only, they are now released
  4015. Vorticity->needed = Vorticity->selected;
  4016. Divergence->needed = Divergence->selected || Omega->needed;
  4017. // Perform inverse Legendre transformation for all needed variables
  4018. for (code = 0 ; code < CODES; code++)
  4019. if (All[code].needed && All[code].hsp.size())
  4020. {
  4021. All[code].SetHFour(All[code].hlev,All[code].plev,All[code].twod);
  4022. sp2fci(&All[code].hsp[0],&All[code].hfc[0],All[code].hlev);
  4023. }
  4024. // Compute d(Lnps)/dx and d(Lnps)/dy if needed
  4025. if (dpsdx->needed || dpsdy->needed)
  4026. {
  4027. dpsdx->SetHFour(1,1,TRUE);
  4028. dpsdy->SetHFour(1,1,TRUE);
  4029. Deriva(&LnPs->hfc[0],&dpsdx->hfc[0]);
  4030. sp2fcd(&LnPs->hsp[0],&dpsdy->hfc[0],1,Lats,Fouriers,Truncation);
  4031. }
  4032. /* ------------------------ */
  4033. /* Output of fourier fields */
  4034. /* ------------------------ */
  4035. if (OutRep == HYB_FOUR)
  4036. {
  4037. HybFour->Write_hfour();
  4038. return;
  4039. }
  4040. /* --------------------- */
  4041. /* Output of zonal means */
  4042. /* --------------------- */
  4043. if (OutRep == HYB_ZONM)
  4044. {
  4045. HybSect->Write_hfour();
  4046. return;
  4047. }
  4048. /* ============================ */
  4049. /* Transformation to gridpoints */
  4050. /* ============================ */
  4051. if (SaveMemory) HybSpec->Clear_hspec();
  4052. for (code = 0; code < CODES; code++)
  4053. if (All[code].needed && All[code].hfc.size())
  4054. {
  4055. All[code].SetHGrid(All[code].hlev,All[code].plev,All[code].twod);
  4056. fc2gp(&All[code].hfc[0],&All[code].hgp[0],Lats,Lons,All[code].hlev,Fouriers);
  4057. }
  4058. if (SaveMemory) HybSpec->Clear_hfour();
  4059. if (Humidity->hgp.size()) // Remove spurious negative humidity
  4060. {
  4061. for (int i=0 ; i < Dim3GP ; ++i)
  4062. if (Humidity->hgp[i] < 0.0) Humidity->hgp[i] = 0.0;
  4063. }
  4064. if (LnPs->hgp.size())
  4065. {
  4066. Ps->SetHGrid(1,1,TRUE);
  4067. Ps->hgp = exp(LnPs->hgp);
  4068. }
  4069. LnPs->needed = LnPs->selected;
  4070. if (Orography.size() != DimGP)
  4071. {
  4072. Orography.resize(DimGP);
  4073. if (Geopotential->hgp.size()) Orography = Geopotential->hgp;
  4074. else
  4075. {
  4076. if (Geopotential->selected || VerType == 'p')
  4077. {
  4078. CenterText("Orography not found - using zero orography");
  4079. Orography = 0.0;
  4080. }
  4081. }
  4082. }
  4083. Geopotential->needed = Geopotential->selected;
  4084. if (Geopotential->needed && !Geopotential->hgp.size())
  4085. {
  4086. Geopotential->SetHGrid(1,1,TRUE);
  4087. Geopotential->hgp = Orography;
  4088. }
  4089. // This section is implemented for pressure level fields only
  4090. if (VerType == 'p' || Omega->needed)
  4091. {
  4092. FullPress->SetHGrid(SigLevs ,OutLevs,FALSE);
  4093. HalfPress->SetHGrid(SigLevs+1,OutLevs,FALSE);
  4094. presh(&FullPress->hgp[0],&HalfPress->hgp[0],vct,&Ps->hgp[0]);
  4095. if (ThetaF->needed)
  4096. {
  4097. ThetaF->SetHGrid(SigLevs,OutLevs,FALSE);
  4098. ThetaH->SetHGrid(SigLevs,OutLevs,FALSE);
  4099. theta(&ThetaF->hgp[0], &ThetaH->hgp[0], &HalfPress->hgp[0], &Ps->hgp[0],
  4100. &Temperature->hgp[0], &Ts->hgp[0], DimGP, Dim3GP);
  4101. }
  4102. if (GeopotHeight->needed)
  4103. {
  4104. GeopotHeight->SetHGrid(SigLevs+1,OutLevs,FALSE);
  4105. memcpy(&GeopotHeight->hgp[Dim3GP],&Orography[0],DimGP * sizeof(double));
  4106. MakeGeopotHeight(&GeopotHeight->hgp[0],&Temperature->hgp[0],
  4107. &Humidity->hgp[0],&HalfPress->hgp[0],DimGP,SigLevs);
  4108. Humidity->needed = Humidity->selected;
  4109. }
  4110. if (dpsdx->needed) dpsdx->hgp *= Ps->hgp;
  4111. if (dpsdy->needed) dpsdy->hgp *= Ps->hgp;
  4112. if (Omega->needed)
  4113. {
  4114. Omega->SetHGrid(SigLevs+1,OutLevs,FALSE);
  4115. OMEGA();
  4116. dpsdx->needed = dpsdx->selected;
  4117. dpsdy->needed = dpsdy->selected;
  4118. }
  4119. if (w_wind->needed)
  4120. {
  4121. w_wind->SetHGrid(SigLevs,OutLevs,FALSE);
  4122. Omega_w(&w_wind->hgp[0],&Omega->hgp[0],&Temperature->hgp[0],&FullPress->hgp[0]);
  4123. }
  4124. if (Rhumidity->needed)
  4125. {
  4126. Rhumidity->SetHGrid(SigLevs,OutLevs,FALSE);
  4127. sh2rh(&Humidity->hgp[0],&Rhumidity->hgp[0],
  4128. &Temperature->hgp[0],SigLevs);
  4129. Temperature->needed = Temperature->selected;
  4130. Humidity->needed = Humidity->selected;
  4131. }
  4132. if (SLP->needed)
  4133. {
  4134. SLP->SetHGrid(1,1,TRUE);
  4135. Extrap(&SLP->hgp[0],&HalfPress->hgp[0] + Dim3GP,
  4136. &FullPress->hgp[0] + Dim3GP - DimGP , &Orography[0],
  4137. &Temperature->hgp[0] + Dim3GP - DimGP , DimGP);
  4138. Temperature->needed = Temperature->selected || GeopotHeight->selected;
  4139. }
  4140. } // endif (VerType == 'p')
  4141. if (speed->needed)
  4142. {
  4143. speed->SetHGrid(SigLevs,OutLevs,FALSE);
  4144. Speed(&speed->hgp[0],&u_wind->hgp[0],&v_wind->hgp[0]);
  4145. }
  4146. if (precip->needed)
  4147. {
  4148. precip->SetHGrid(1,1,TRUE);
  4149. precip->hgp = All[142].hgp + All[143].hgp;
  4150. }
  4151. if (net_top->needed)
  4152. {
  4153. net_top->SetHGrid(1,1,TRUE);
  4154. net_top->hgp = All[178].hgp + All[179].hgp;
  4155. }
  4156. if (net_bot->needed)
  4157. {
  4158. net_bot->SetHGrid(1,1,TRUE);
  4159. net_bot->hgp = All[176].hgp + All[177].hgp;
  4160. }
  4161. if (net_heat->needed)
  4162. {
  4163. net_heat->SetHGrid(1,1,TRUE);
  4164. net_heat->hgp = All[218].hgp * L_times_rhoH2O
  4165. + All[176].hgp + All[177].hgp + All[146].hgp + All[147].hgp;
  4166. }
  4167. if (net_water->needed)
  4168. {
  4169. net_water->SetHGrid(1,1,TRUE);
  4170. net_water->hgp = All[182].hgp - All[160].hgp + All[142].hgp + All[143].hgp;
  4171. }
  4172. if (sw_atm->needed)
  4173. {
  4174. sw_atm->SetHGrid(1,1,TRUE);
  4175. sw_atm->hgp = All[178].hgp - All[176].hgp;
  4176. }
  4177. if (lw_atm->needed)
  4178. {
  4179. lw_atm->SetHGrid(1,1,TRUE);
  4180. lw_atm->hgp = All[179].hgp - All[177].hgp;
  4181. }
  4182. if (net_atm->needed)
  4183. {
  4184. net_atm->SetHGrid(1,1,TRUE);
  4185. net_atm->hgp = All[178].hgp + All[179].hgp - All[176].hgp - All[177].hgp;
  4186. }
  4187. if (surf_runoff->needed)
  4188. {
  4189. surf_runoff->SetHGrid(1,1,TRUE);
  4190. surf_runoff->hgp = All[182].hgp - All[221].hgp + All[142].hgp + All[143].hgp;
  4191. }
  4192. if (fresh_water->needed)
  4193. {
  4194. fresh_water->SetHGrid(1,1,TRUE);
  4195. fresh_water->hgp = All[142].hgp + All[143].hgp + All[182].hgp;
  4196. }
  4197. // =============================
  4198. // Monthly means on hybrid grids
  4199. // =============================
  4200. if (Mean && OutRep == HYB_GRID)
  4201. for (code = 0; code < CODES; code++)
  4202. if (All[code].selected && All[code].hgp.size())
  4203. {
  4204. if (MeanCount == 1)
  4205. {
  4206. All[code].mgp.resize(All[code].hgp.size());
  4207. All[code].mgp = All[code].hgp;
  4208. All[code].hgp.resize(0);
  4209. }
  4210. else All[code].mgp += All[code].hgp;
  4211. if (EndOfMonth)
  4212. {
  4213. double rmc = 1.0 / MeanCount;
  4214. All[code].hgp = All[code].mgp * rmc;
  4215. All[code].mgp.resize(0);
  4216. }
  4217. }
  4218. // ----------------------------
  4219. // Output of hybrid level grids
  4220. // ----------------------------
  4221. if (OutRep == HYB_GRID)
  4222. {
  4223. if (!Mean || EndOfMonth) HybGrid->Write_hgrid();
  4224. if (SaveMemory) HybGrid->Clear_hgrid();
  4225. return;
  4226. }
  4227. // ======================================
  4228. // Vertical interpolation / extrapolation
  4229. // ======================================
  4230. if (vert_index == NULL) vert_index = new int[OutLevs*DimGP];
  4231. genind(vert_index,level,&FullPress->hgp[0],DimGP,OutLevs);
  4232. for (code = 0; code < CODES; code++)
  4233. if (All[code].needed && All[code].hgp.size())
  4234. {
  4235. All[code].SetPGrid();
  4236. if (!All[code].twod)
  4237. {
  4238. if (code == ZCODE) Interpolate_Z();
  4239. else Interpolate_T(code);
  4240. }
  4241. }
  4242. Temperature->needed = Temperature->selected;
  4243. if (SaveMemory) HybGrid->Clear_hgrid();
  4244. // ===========================
  4245. // Computation of Montly Means
  4246. // ===========================
  4247. if (Mean)
  4248. for (code = 0; code < CODES; code++)
  4249. if (All[code].needed && All[code].pgp.size())
  4250. {
  4251. if (MeanCount == 1)
  4252. {
  4253. All[code].mgp.resize(All[code].pgp.size());
  4254. All[code].mgp = All[code].pgp;
  4255. All[code].pgp.resize(0);
  4256. }
  4257. else All[code].mgp += All[code].pgp;
  4258. if (EndOfMonth)
  4259. {
  4260. double rmc = 1.0 / MeanCount;
  4261. All[code].pgp = All[code].mgp * rmc;
  4262. All[code].mgp.resize(0);
  4263. }
  4264. }
  4265. if (Mean && !EndOfMonth)
  4266. {
  4267. if (SaveMemory) HybGrid->Clear_pgrid();
  4268. return;
  4269. }
  4270. // ------------------------------
  4271. // Output of pressure level grids
  4272. // ------------------------------
  4273. if (OutRep == PRE_GRID)
  4274. {
  4275. if (SpecialUV)
  4276. {
  4277. gp2fc_uv();
  4278. fc2sp_uv();
  4279. sp2fc_uv();
  4280. fc2gp_uv();
  4281. }
  4282. HybGrid->Write_pgrid();
  4283. if (SaveMemory) HybGrid->Clear_pgrid();
  4284. return;
  4285. }
  4286. // ===============================
  4287. // Transformation to fourier space
  4288. // ===============================
  4289. for (code = 0; code < CODES; code++)
  4290. if (All[code].needed && All[code].pgp.size())
  4291. {
  4292. if (!All[code].pfc.size()) All[code].SetPFour();
  4293. gp2fc(&All[code].pgp[0],&All[code].pfc[0],
  4294. Lats,Lons,All[code].plev,Fouriers);
  4295. }
  4296. if (SaveMemory) HybGrid->Clear_pgrid();
  4297. // ---------------------------------------
  4298. // Output of fourier fields or zonal means
  4299. // ---------------------------------------
  4300. if (OutRep == PRE_FOUR || OutRep == PRE_ZONM)
  4301. {
  4302. if (SpecialUV)
  4303. {
  4304. fc2sp_uv();
  4305. sp2fc_uv();
  4306. }
  4307. if (OutRep == PRE_FOUR) HybFour->Write_pfour();
  4308. else HybSect->Write_pfour();
  4309. if (SaveMemory) HybFour->Clear_pfour();
  4310. return;
  4311. }
  4312. // ================================
  4313. // Transformation to spectral space
  4314. // ================================
  4315. if (!SpecialUV && u_wind->pfc.size() && v_wind->pfc.size())
  4316. {
  4317. scaluv(&u_wind->pfc[0],CosPhi,Lats,Fouriers*OutLevs);
  4318. scaluv(&v_wind->pfc[0],CosPhi,Lats,Fouriers*OutLevs);
  4319. }
  4320. for (code = 0; code < CODES; code++)
  4321. if (All[code].needed && All[code].pfc.size() && !All[code].psp.size())
  4322. {
  4323. All[code].SetPSpec();
  4324. fc2sp(&All[code].pfc[0],&All[code].psp[0],All[code].plev,Lats,Truncation);
  4325. }
  4326. if (SpecialUV) fc2sp_uv();
  4327. if (SaveMemory) HybFour->Clear_pfour();
  4328. // -------------------------
  4329. // Output of spectral fields
  4330. // -------------------------
  4331. if (OutRep == PRE_SPEC)
  4332. {
  4333. HybSpec->Write_pspec();
  4334. if (SaveMemory) HybSpec->Clear_pspec();
  4335. return;
  4336. }
  4337. }
  4338. void PostProcess(void)
  4339. {
  4340. int l;
  4341. char tb[COLS+2];
  4342. if (EndOfMonth)
  4343. {
  4344. sprintf(tb,"Processed Month %2d Year %4d", OldMonth,OldDate.tm_year);
  4345. l = strlen(tb);
  4346. if (MeanCount > 1)
  4347. {
  4348. if (Mean) sprintf(tb+l," (Mean of %3d Terms)",MeanCount);
  4349. else sprintf(tb+l," Terms %3d",MeanCount);
  4350. }
  4351. LeftText(tb);
  4352. EndOfMonth = FALSE;
  4353. MeanCount = 0;
  4354. MonthCount++ ;
  4355. }
  4356. }
  4357. /* ================= */
  4358. /* switch input file */
  4359. /* ================= */
  4360. void SwitchFile(void)
  4361. {
  4362. int l,YY,MM;
  4363. fclose(fpi);
  4364. l = strlen(ifile);
  4365. if (l > 4 && ifile[l-4] == '.' && atoi(ifile+l-3) != 0) // .YYY
  4366. {
  4367. YY = atoi(ifile+l-3) + 1;
  4368. sprintf(ifile+l-3,"%03d",YY);
  4369. }
  4370. else if (l > 5 && ifile[l-5] == '_' && atoi(ifile+l-4) != 0) // _YYYY
  4371. {
  4372. YY = atoi(ifile+l-4) + 1;
  4373. sprintf(ifile+l-4,"%04d",YY);
  4374. }
  4375. else if (l > 7 && ifile[l-7] == '_' && atoi(ifile+l-6) != 0) // _YYYYMM
  4376. {
  4377. MM = atoi(ifile+l-2);
  4378. YY = atoi(ifile+l-6);
  4379. if (MM == 12) YY += 88;
  4380. if (YY > 1) sprintf(ifile+l-6,"%06d",++YY);
  4381. }
  4382. else if (l > 5 && atoi(ifile+l-5) != 0) // "YYYMM" at end
  4383. {
  4384. MM = atoi(ifile+l-2);
  4385. YY = atoi(ifile+l-5);
  4386. if (MM == 12) YY += 88;
  4387. if (YY > 1) sprintf(ifile+l-5,"%05d",++YY);
  4388. }
  4389. else if (l > 4 && atoi(ifile+l-4) != 0) // "YYMM" at end
  4390. {
  4391. MM = atoi(ifile+l-2);
  4392. YY = atoi(ifile+l-4);
  4393. if (MM == 12) YY += 88;
  4394. if (YY > 1) sprintf(ifile+l-4,"%04d",++YY);
  4395. }
  4396. Multi--;
  4397. printf("Continuation File: %s\n",ifile);
  4398. fpi = fopen(ifile,"rb");
  4399. }
  4400. /* ====================================== */
  4401. /* Interpolate gauss grid to regular grid */
  4402. /* ====================================== */
  4403. void Regauss(double *r, double *g, double *Ghi)
  4404. {
  4405. int j,jlon,jlat;
  4406. double np,sp,fn,fs,fe,fw;
  4407. double rphi,rlam,gdx,rdx;
  4408. double *Gam;
  4409. Gam = new double[Gons];
  4410. gdx = 360.0 / Gons;
  4411. rdx = 360.0 / Lons;
  4412. np = sp = 0.0;
  4413. for (jlon = 0 ; jlon < Gons ; ++jlon)
  4414. {
  4415. np += g[jlon];
  4416. sp += g[jlon + DimGG - Gons];
  4417. }
  4418. np /= Gons;
  4419. sp /= Gons;
  4420. for (jlat = 0 ; jlat < Lats ; ++jlat)
  4421. {
  4422. rphi = Outlat->Phi[jlat];
  4423. if (rphi > Ghi[0]) // far north
  4424. {
  4425. fn = (rphi - Ghi[0]) / (90.0 - Ghi[0]);
  4426. fs = 1.0 - fn;
  4427. for (jlon = 0 ; jlon < Gons ; ++jlon)
  4428. Gam[jlon] = fn * np + fs * g[jlon];
  4429. }
  4430. else if (rphi < Ghi[Gats-1]) // far south
  4431. {
  4432. fs = (Ghi[Gats-1] - rphi) / (Ghi[Gats-1] + 90.0);
  4433. fn = 1.0 - fs;
  4434. for (jlon = 0 ; jlon < Gons ; ++jlon)
  4435. Gam[jlon] = fn * g[jlon + DimGG - Gons] + fs * sp;
  4436. }
  4437. else // inside
  4438. {
  4439. j = 0; // search neighboured gauss latitudes
  4440. while (j < Gats-1 && rphi < Ghi[j]) ++j;
  4441. fn = (rphi - Ghi[j]) / (Ghi[j-1] - Ghi[j]);
  4442. fs = 1.0 - fn;
  4443. for (jlon = 0 ; jlon < Gons ; ++jlon)
  4444. Gam[jlon] = fn * g[jlon+(j-1)*Gons] + fs * g[jlon+j*Gons];
  4445. }
  4446. for (jlon = 0 ; jlon < Lons ; ++jlon)
  4447. {
  4448. rlam = jlon * rdx;
  4449. j = (int)floor(rlam / gdx);
  4450. fe = (rlam - j * gdx) / gdx;
  4451. fw = 1.0 - fe;
  4452. if (j >= Gons-1) r[jlon + jlat * Lons] = fw * Gam[j] + fe * Gam[0];
  4453. else r[jlon + jlat * Lons] = fw * Gam[j] + fe * Gam[j+1];
  4454. }
  4455. }
  4456. delete Gam;
  4457. }
  4458. /*******************/
  4459. /* SetOutputHeader */
  4460. /*******************/
  4461. void SetOutputHeader(void)
  4462. {
  4463. int MM,DD,HH;
  4464. if (DPM > 99) // Workaround for months with more than 99 days
  4465. {
  4466. MM = (TermCount / DPM) % 12 + 1;
  4467. HeadOu[2] = OldDate.tm_year * 10000 + MM * 100;
  4468. HeadOu[3] = 0;
  4469. if (!Mean) // Add day & hour info
  4470. {
  4471. HeadOu[2] += (TermCount % DPM) / DayDivisor + 1;
  4472. HeadOu[3] = 100 * (24 / DayDivisor) * ((TermCount % DPM) % DayDivisor);
  4473. }
  4474. }
  4475. else
  4476. {
  4477. HeadOu[2] = OldDate.tm_year * 10000 + OldDate.tm_mon * 100;
  4478. HeadOu[3] = 0;
  4479. if (!Mean)
  4480. {
  4481. HeadOu[2] += OldDate.tm_mday;
  4482. HeadOu[3] = OldDate.tm_hour * 100 + OldDate.tm_min;
  4483. }
  4484. }
  4485. }
  4486. /*****************/
  4487. /* Puma Control */
  4488. /*****************/
  4489. void PumaControl(void)
  4490. {
  4491. int i;
  4492. int LevelOffset;
  4493. int Eof;
  4494. char tb[COLS+2];
  4495. struct tm D1;
  4496. struct tm D2;
  4497. while (1)
  4498. {
  4499. Eof = ReadHeaderRecord();
  4500. if (Eof && Multi)
  4501. {
  4502. SwitchFile();
  4503. if (fpi) Eof = ReadHeaderRecord();
  4504. }
  4505. if (DataStep < 0.01) // Compute time interval
  4506. {
  4507. if (HeadIn[2] != HeadSt[2] || HeadIn[3] != HeadSt[3])
  4508. {
  4509. HeadToDate(HeadSt,&D1);
  4510. HeadToDate(HeadIn,&D2);
  4511. DeltaDy = D2.tm_mday - D1.tm_mday;
  4512. DeltaHr = D2.tm_hour - D1.tm_hour;
  4513. DeltaMn = D2.tm_min - D1.tm_min ;
  4514. if (DeltaDy < 0) DeltaDy = 1; // month changed after 1.st term
  4515. DataStep = DeltaDy + DeltaHr / 24.0 + DeltaMn / 1440.0;
  4516. }
  4517. }
  4518. if ((HeadIn[2] / 100 % 100) > LastMonth && DayDivisor == 0) // Ignore rest of file
  4519. {
  4520. Eof = 1;
  4521. if (Multi)
  4522. {
  4523. SwitchFile();
  4524. if (fpi) Eof = ReadHeaderRecord();
  4525. }
  4526. }
  4527. if (Eof) // Process last read term and finish
  4528. {
  4529. EndOfMonth = TRUE;
  4530. SetOutputHeader();
  4531. PumaProcess();
  4532. PostProcess();
  4533. Dependencies();
  4534. return;
  4535. }
  4536. DecodePumaHeader();
  4537. if (NewMonth < FirstMonth) /* Skip months before FirstMonth */
  4538. {
  4539. SkipPumaArray();
  4540. if (Debug)
  4541. {
  4542. if (RepGrib == REP_SPECTRAL) sprintf(tb,"T%04d",Truncation);
  4543. else sprintf(tb,"N%04d",Lons);
  4544. sprintf(tb+5," SKIPPED Code %3d Level%6d %2.2d.%2.2d.%2.2d %2.2d:%2.2d",
  4545. PumaCode,PumaLevel,NewDate.tm_mday,NewDate.tm_mon,NewDate.tm_year,
  4546. NewDate.tm_hour,NewDate.tm_min);
  4547. LeftText(tb);
  4548. }
  4549. continue;
  4550. }
  4551. if (Debug)
  4552. {
  4553. if (RepGrib == REP_SPECTRAL) sprintf(tb,"T%04d",Truncation);
  4554. else sprintf(tb,"N%04d",Lons);
  4555. sprintf(tb+5," Code %3d Level%6d %2.2d.%2.2d.%2.2d %2.2d:%2.2d",
  4556. PumaCode,PumaLevel,NewDate.tm_mday,NewDate.tm_mon,NewDate.tm_year,
  4557. NewDate.tm_hour,NewDate.tm_min);
  4558. LeftText(tb);
  4559. }
  4560. if (OldMonth > 0)
  4561. {
  4562. EndOfMonth = NewMonth != OldMonth;
  4563. EndOfTerm = memcmp(&NewDate,&OldDate,sizeof(struct tm));
  4564. if (EndOfTerm && MeanCount == DPM-1) EndOfMonth = 1;
  4565. if (EndOfTerm)
  4566. {
  4567. SetOutputHeader();
  4568. PumaProcess();
  4569. PostProcess();
  4570. Dependencies();
  4571. }
  4572. }
  4573. OldDate = NewDate;
  4574. OldMonth = NewMonth;
  4575. if (All[PumaCode].needed)
  4576. {
  4577. if (RepGrib == REP_SPECTRAL) // Spectral array
  4578. {
  4579. if (PumaLevel) All[PumaCode].SetHSpec(SigLevs,OutLevs,FALSE);
  4580. else All[PumaCode].SetHSpec( 1, 1,TRUE );
  4581. if (VerType != 's' || mom[PumaLevel])
  4582. {
  4583. ReadPumaArray(&All[PumaCode].hsp[0]+All[PumaCode].loff);
  4584. All[PumaCode].loff += DimSP;
  4585. }
  4586. else SkipPumaArray();
  4587. }
  4588. else // Gridpoint array
  4589. {
  4590. if (PumaLevel) All[PumaCode].SetHGrid(SigLevs,OutLevs,FALSE);
  4591. else All[PumaCode].SetHGrid( 1, 1,TRUE );
  4592. if (VerType != 's' || mom[PumaLevel])
  4593. {
  4594. if (DimGP == DimGG)
  4595. ReadPumaArray(&All[PumaCode].hgp[0]+All[PumaCode].loff);
  4596. else
  4597. {
  4598. double *ArrayBuffer;
  4599. ArrayBuffer = new double[DimGG];
  4600. ReadPumaArray(ArrayBuffer);
  4601. Regauss(&All[PumaCode].hgp[0]+All[PumaCode].loff,ArrayBuffer,Gaulat->Phi);
  4602. delete ArrayBuffer;
  4603. }
  4604. All[PumaCode].loff += DimGP;
  4605. }
  4606. else SkipPumaArray();
  4607. }
  4608. }
  4609. else SkipPumaArray();
  4610. }
  4611. }
  4612. char *amatch(char *msr, const char *sub)
  4613. {
  4614. int i,nm,ns;
  4615. nm = strlen(msr);
  4616. ns = strlen(sub);
  4617. for (i = 0; i < nm-ns; i++)
  4618. if (strncmp(msr+i,sub,ns) == 0) return (msr+i+ns);
  4619. return NULL;
  4620. }
  4621. int scanpar(const char *name, int def)
  4622. {
  4623. char *cp;
  4624. int value;
  4625. char tb[COLS+2];
  4626. cp = amatch(namelist,name);
  4627. if (cp == NULL)
  4628. {
  4629. value = def;
  4630. sprintf(tb,"%10.10s = %8d (default)",name,value);
  4631. }
  4632. else
  4633. {
  4634. value = atoi(cp);
  4635. sprintf(tb,"%10.10s = %8d ",name,value);
  4636. }
  4637. LeftText(tb);
  4638. return value;
  4639. }
  4640. double scanreal(const char *name, double def)
  4641. {
  4642. char *cp;
  4643. double value;
  4644. char tb[COLS+2];
  4645. cp = amatch(namelist,name);
  4646. if (cp == NULL)
  4647. {
  4648. value = def;
  4649. sprintf(tb,"%10.10s = %8.3f (default)",name,value);
  4650. }
  4651. else
  4652. {
  4653. value = strtod(cp,NULL);
  4654. sprintf(tb,"%10.10s = %8.3f ",name,value);
  4655. }
  4656. LeftText(tb);
  4657. return value;
  4658. }
  4659. char scantex(const char *name, const char choice[])
  4660. {
  4661. char *cp;
  4662. char value;
  4663. int i;
  4664. char tb[COLS+2];
  4665. value = choice[0];
  4666. cp = amatch(namelist,name);
  4667. if (cp)
  4668. {
  4669. while (isspace(*cp)) ++cp;
  4670. for (i=1 ; i < strlen(choice) ; ++i)
  4671. {
  4672. if (*cp == choice[i]) value = *cp;
  4673. }
  4674. }
  4675. sprintf(tb,"%10.10s = %c ",name,value);
  4676. LeftText(tb);
  4677. return value;
  4678. }
  4679. void scantime(void)
  4680. {
  4681. char *cp,*icp;
  4682. int time,i;
  4683. char tb[512];
  4684. nrqh = 0;
  4685. cp = amatch(namelist,"timesel");
  4686. if (cp == NULL)
  4687. {
  4688. hours[nrqh++] = -1;
  4689. sprintf(tb,"%10.10s = all ","timesel");
  4690. LeftText(tb);
  4691. return;
  4692. }
  4693. time = strtol(cp,&icp,10);
  4694. while ((char *)icp != (char *)cp && nrqh < MAX_HOURS) {
  4695. hours[nrqh++] = time;
  4696. cp = icp;
  4697. time = strtol(cp,&icp,10);
  4698. }
  4699. sprintf(tb,"%10.10s = ","timesel");
  4700. for (time = 0 ; time < nrqh ; ++time)
  4701. {
  4702. i = strlen(tb);
  4703. sprintf(tb+i," %02d",hours[time]);
  4704. }
  4705. LeftText(tb);
  4706. }
  4707. void PrintCodes(void)
  4708. {
  4709. int code;
  4710. char tb[COLS+2];
  4711. DashLine();
  4712. CenterText("Code Id Name Units ");
  4713. DashLine();
  4714. for (code=0 ; code < MAXCODES ; ++code) if (strncmp(All[code].Na,"Code",4))
  4715. {
  4716. sprintf(tb,"%4d %-8.8s %-32.32s %-16.16s",code,All[code].Id,All[code].Na,All[code].Un);
  4717. CenterText(tb);
  4718. }
  4719. }
  4720. int CodeOrName(char *a, char **b)
  4721. {
  4722. int l,code;
  4723. while (*a == ' ') ++a;
  4724. if (*a == '+' || *a == '-' || (*a >= '0' && *a <='9'))
  4725. return strtol(a,b,10);
  4726. for (code = 0 ; code < CODES ; ++code)
  4727. {
  4728. l = strlen(All[code].Id);
  4729. if (!strncmp(All[code].Id,a,l) && *(a+l) == ' ')
  4730. {
  4731. *b = a+l;
  4732. return code;
  4733. }
  4734. }
  4735. return 0;
  4736. }
  4737. void scancode(void)
  4738. {
  4739. char *cp,*icp;
  4740. int code;
  4741. char tb[COLS+2];
  4742. cp = amatch(namelist,"code");
  4743. if (cp == NULL) Abort(" *** No code selected for output ***");
  4744. code = CodeOrName(cp,&icp);
  4745. DashLine();
  4746. while (code > 0 && code < CODES)
  4747. {
  4748. sprintf(tb,"Code %5d = %-6.6s %-24.24s",code,All[code].Id,All[code].Na);
  4749. LeftText(tb);
  4750. All[code].selected = 1;
  4751. cp = icp;
  4752. code = CodeOrName(cp,&icp);
  4753. }
  4754. }
  4755. void scanmol(void)
  4756. {
  4757. char *cp,*icp;
  4758. int lev;
  4759. nrml = 0;
  4760. cp = amatch(namelist,"modlev");
  4761. if (cp == NULL) return;
  4762. lev = strtol(cp,&icp,10);
  4763. while (lev > 0 && nrml < MAX_LEVELS)
  4764. {
  4765. mol[nrml++] = lev;
  4766. mom[lev] = 1;
  4767. cp = icp;
  4768. lev = strtol(cp,&icp,10);
  4769. }
  4770. }
  4771. void scanhPa(void)
  4772. {
  4773. char *cp,*icp;
  4774. double lev;
  4775. nrpl = 0;
  4776. cp = amatch(namelist,"hpa");
  4777. if (!cp) return;
  4778. lev = strtod(cp,&icp);
  4779. while (lev > 0 && nrpl < MAX_LEVELS)
  4780. {
  4781. hPa[nrpl++] = lev;
  4782. cp = icp;
  4783. lev = strtod(cp,&icp);
  4784. }
  4785. }
  4786. void scanattributes(void)
  4787. {
  4788. char *cp;
  4789. int i;
  4790. nattr = 0;
  4791. cp = amatch(namelist,"attributes");
  4792. if (!cp) return;
  4793. while (nattr < ATTR_MAX)
  4794. {
  4795. i = 0;
  4796. while (*cp == ':' || isspace(*cp)) ++cp;
  4797. while ((isalnum(*cp) || *cp == '_') && i < 80) AttrNam[nattr][i++] = *cp++;
  4798. while (isspace(*cp)) ++cp;
  4799. if (*cp != '=') break;
  4800. else ++cp;
  4801. while (isspace(*cp)) ++cp;
  4802. if (*cp != '"') break;
  4803. else ++cp;
  4804. i = 0;
  4805. while (*cp != '"' && i < 80) AttrVal[nattr][i++] = *cp++;
  4806. ++cp;
  4807. while (isspace(*cp)) ++cp;
  4808. if (*cp != ';') break;
  4809. ++cp;
  4810. ++nattr;
  4811. }
  4812. }
  4813. void InitAll(void)
  4814. {
  4815. char Id[MAX_ID_LEN];
  4816. char Na[MAX_NA_LEN];
  4817. for (int code = 0 ; code < MAXCODES ; ++code)
  4818. {
  4819. sprintf(Id,"var%3.3d",code);
  4820. sprintf(Na,"Code[%d]",code);
  4821. All[code].Init(Id,Na,"1",0);
  4822. All[code].code = code;
  4823. }
  4824. All[110].Init("mld" ,"mixed_layer_depth" ,"m" ,1); // Not standard
  4825. All[129].Init("sg" ,"surface_geopotential" ,"m2 s-2" ,1);
  4826. All[130].Init("ta" ,"air_temperature" ,"K" ,0);
  4827. All[131].Init("ua" ,"eastward_wind" ,"m s-1" ,0);
  4828. All[132].Init("va" ,"northward_wind" ,"m s-1" ,0);
  4829. All[133].Init("hus" ,"specific_humidity" ,"1" ,0);
  4830. All[134].Init("ps" ,"surface_air_pressure" ,"hPa" ,1);
  4831. All[135].Init("wap" ,"vertical_air_velocity" ,"Pa s-1" ,0); // shortened
  4832. All[137].Init("wa" ,"upward_wind" ,"m s-1" ,0); // Not standard
  4833. All[138].Init("zeta" ,"atm_relative_vorticity" ,"s-1" ,0);
  4834. All[139].Init("ts" ,"surface_temperature" ,"K" ,1);
  4835. All[140].Init("mrso" ,"lwe_of_soil_moisture_content" ,"m" ,1); // shortened
  4836. All[141].Init("snd" ,"surface_snow_thickness" ,"m" ,1);
  4837. All[142].Init("prl" ,"lwe_of_large_scale_precipitation","m s-1" ,1); // rate !!
  4838. All[143].Init("prc" ,"convective_precipitation_rate" ,"m s-1" ,1);
  4839. All[144].Init("prsn" ,"lwe_of_snowfall_amount" ,"m s-1" ,1); // rate !!
  4840. All[145].Init("bld" ,"dissipation_in_atmosphere_bl" ,"W m-2" ,1); // shortened
  4841. All[146].Init("hfss" ,"surface_sensible_heat_flux" ,"W m-2" ,1); // shortened
  4842. All[147].Init("hfls" ,"surface_latent_heat_flux" ,"W m-2" ,1); // shortened
  4843. All[148].Init("stf" ,"streamfunction" ,"m2 s-2" ,0); // Not standard
  4844. All[149].Init("psi" ,"velocity_potential" ,"m2 s-2" ,0); // Not standard
  4845. All[151].Init("psl" ,"air_pressure_at_sea_level" ,"hPa" ,1);
  4846. All[152].Init("pl" ,"log_surface_pressure" ,"1" ,1);
  4847. All[155].Init("d" ,"divergence_of_wind" ,"s-1" ,0);
  4848. All[156].Init("zg" ,"geopotential_height" ,"m" ,0);
  4849. All[157].Init("hur" ,"relative_humidity" ,"1" ,0);
  4850. All[158].Init("tps" ,"tendency_of_surface_air_pressure","Pa s-1" ,1);
  4851. All[159].Init("u3" ,"ustar" ,"m3 s-3" ,1); // Not standard
  4852. All[160].Init("mrro" ,"surface_runoff" ,"m s-1" ,1); // Not standard
  4853. All[161].Init("clw" ,"liquid_water_content" ,"1" ,0); // Not standard
  4854. All[162].Init("cl" ,"cloud_area_fraction_in_layer" ,"1" ,0); // Not standard
  4855. All[163].Init("tcc" ,"total_cloud_cover" ,"1" ,1); // Not standard
  4856. All[164].Init("clt" ,"cloud_area_fraction" ,"1" ,1);
  4857. All[165].Init("uas" ,"eastward_wind_10m" ,"m s-1" ,1); // shortened
  4858. All[166].Init("vas" ,"northward_wind_10m" ,"m s-1" ,1); // shortened
  4859. All[167].Init("tas" ,"air_temperature_2m" ,"K" ,1); // shortened
  4860. All[168].Init("td2m" ,"dew_point_temperature_2m" ,"K" ,1); // shortened
  4861. All[169].Init("tsa" ,"surface_temperature_accumulated" ,"K" ,1); // Not standard
  4862. All[170].Init("tsod" ,"deep_soil_temperature" ,"K" ,1);
  4863. All[171].Init("dsw" ,"deep_soil_wetness" ,"1" ,1);
  4864. All[172].Init("lsm" ,"land_binary_mask" ,"1" ,1);
  4865. All[173].Init("z0" ,"surface_roughness_length" ,"m" ,1);
  4866. All[174].Init("alb" ,"surface_albedo" ,"1" ,1); // Not standard
  4867. All[175].Init("as" ,"surface_albedo" ,"1" ,1); // Not standard
  4868. All[176].Init("rss" ,"surface_net_shortwave_flux" ,"W m-2" ,1); // shortened
  4869. All[177].Init("rls" ,"surface_net_longwave_flux" ,"W m-2" ,1); // shortened
  4870. All[178].Init("rst" ,"toa_net_shortwave_flux" ,"W m-2" ,1); // shortened
  4871. All[179].Init("rlut" ,"toa_net_longwave_flux" ,"W m-2" ,1); // shortened
  4872. All[180].Init("tauu" ,"surface_eastward_stress" ,"Pa" ,1); // shortened
  4873. All[181].Init("tauv" ,"surface_northward_stress" ,"Pa" ,1); // shortened
  4874. All[182].Init("evap" ,"lwe_of_water_evaporation" ,"m s-1" ,1); // rate !!
  4875. All[183].Init("tso" ,"climate_deep_soil_temperature" ,"K" ,1); // Not standard
  4876. All[184].Init("wsoi" ,"climate_deep_soil_wetness" ,"1" ,1);
  4877. All[199].Init("vegc" ,"vegetation_cover" ,"1" ,1); // Not standard
  4878. All[203].Init("rsut" ,"toa_outgoing_shortwave_flux" ,"W m-2" ,1); // Not standard
  4879. All[204].Init("ssru" ,"surface_solar_radiation_upward" ,"W m-2" ,1); // Not standard
  4880. All[205].Init("stru" ,"surface_thermal_radiation_upward","W m-2" ,1); // Not standard
  4881. All[207].Init("tso2" ,"soil_temperature_level_2" ,"K" ,1); // Not standard
  4882. All[208].Init("tso3" ,"soil_temperature_level_3" ,"K" ,1); // Not standard
  4883. All[209].Init("tso4" ,"soil_temperature_level_4" ,"K" ,1); // Not standard
  4884. All[210].Init("sic" ,"sea_ice_cover" ,"1" ,1); // Not standard
  4885. All[211].Init("sit" ,"sea_ice_thickness" ,"m" ,1); // Not standard
  4886. All[212].Init("vegf" ,"forest_cover" ,"1" ,1); // Not standard
  4887. All[218].Init("snm" ,"snow_melt" ,"m s-1" ,1); // Not standard
  4888. All[221].Init("sndc" ,"snow_depth_change" ,"m s-1" ,1); // Not standard
  4889. All[230].Init("prw" ,"atmosphere_water_vapor_content" ,"kg m-2" ,1); // Not standard
  4890. All[232].Init("glac" ,"glacier_cover" ,"1" ,1); // Not standard
  4891. All[238].Init("tsn" ,"snow_temperature" ,"K" ,1);
  4892. All[259].Init("spd" ,"wind_speed" ,"m s-1" ,0); // Not standard
  4893. All[260].Init("pr" ,"total_precipitation" ,"m s-1" ,1); // Not standard
  4894. All[261].Init("ntr" ,"net_top_radiation" ,"W m-2" ,1); // Not standard
  4895. All[262].Init("nbr" ,"net_bottom_radiation" ,"W m-2" ,1); // Not standard
  4896. All[263].Init("hfns" ,"surface_downward_heat_flux" ,"W m-2" ,1); // shortened
  4897. All[264].Init("wfn" ,"net_water_flux" ,"m s-1" ,1); // Not standard
  4898. All[273].Init("dpdx" ,"d(ps)/dx" ,"Pa m-1" ,1); // Not standard
  4899. All[274].Init("dpdy" ,"d(ps)/dy" ,"Pa m-1" ,1); // Not standard
  4900. All[277].Init("hlpr" ,"half_level_pressure" ,"Pa" ,0); // Not standard
  4901. All[278].Init("flpr" ,"full_level_pressure" ,"Pa" ,0); // Not standard
  4902. }
  4903. void Usage(void)
  4904. {
  4905. char Line[132];
  4906. fpi = fopen("/usr/local/doc/burn7.txt","r");
  4907. if (fpi)
  4908. do
  4909. {
  4910. fgets(Line,130,fpi);
  4911. printf("%s",Line);
  4912. }
  4913. while (!feof(fpi) && Line[0] != '#');
  4914. if (fpi) fclose(fpi);
  4915. printf("\nburn7 [options] InputFile OutputFile <namelist >printout\n");
  4916. printf(" option -h : help (this output)\n");
  4917. printf(" option -c : print available codes and names\n");
  4918. printf(" option -d : debug mode (verbose output)\n");
  4919. printf(" option -m : Mean=1 output (override namelist option)\n");
  4920. printf(" option -n : NetCDF output (override namelist option)\n");
  4921. printf(" option -s : Save memory (increases CPU time)\n");
  4922. printf(" InputFile : PUMA or PlaSim data file\n");
  4923. #ifdef NETCDF_OUTPUT
  4924. printf(" <OutputFile> : SERVICE, or NetCDF format file\n");
  4925. #else
  4926. printf(" <OutputFile> : SERVICE format file\n");
  4927. #endif
  4928. printf(" namelist is read from <stdin>\n");
  4929. printf(" printout is written to <stdout>\n\n");
  4930. exit(1);
  4931. }
  4932. void parini(void)
  4933. {
  4934. char c;
  4935. unsigned int i;
  4936. int jind;
  4937. int lc;
  4938. char tb[COLS+2];
  4939. i = 1;
  4940. namelist[0] = ' ';
  4941. lc = 1;
  4942. c = getchar();
  4943. while (!feof(stdin) && i < MAX_NL)
  4944. {
  4945. if (c == ':' ) lc = 0; // No conversion to lower case
  4946. if (c == '\n') lc = 1;
  4947. if (c == '#') // Skip comment
  4948. {
  4949. while (!feof(stdin) && c != '\n') c = getchar();
  4950. }
  4951. if (lc)
  4952. {
  4953. if ((c >= '0' && c <= '9') ||
  4954. c == '-' || c == '.') namelist[i++] = c;
  4955. else if (c >= 'a' && c <= 'z') namelist[i++] = c;
  4956. else if (c >= 'A' && c <= 'Z') namelist[i++] = tolower(c);
  4957. else c = ' ';
  4958. if (c == ' ' && namelist[i-1] != ' ') namelist[i++] = c;
  4959. }
  4960. else namelist[i++] = c;
  4961. c = getchar();
  4962. }
  4963. namelist[i++] = ' ';
  4964. namelist[i] = 0;
  4965. if (Debug)
  4966. {
  4967. sprintf(tb,"Length of namelist: %d bytes",(int)strlen(namelist));
  4968. LeftText(tb);
  4969. for (i = 0; i<strlen(namelist); i+=40)
  4970. {
  4971. sprintf(tb,"namelist[%02d]=%-40.40s",i,namelist+i);
  4972. LeftText(tb);
  4973. }
  4974. StarLine();
  4975. }
  4976. Lats = scanpar("lats",Lats);
  4977. Lons = scanpar("lons",Lons);
  4978. DPM = scanpar("dpm",0);
  4979. if (DPM > 99 && DPM < 2400) /* Days Per Month */
  4980. {
  4981. DayDivisor = DPM / 100 + 1;
  4982. while (24 % DayDivisor && DayDivisor < 24) ++DayDivisor;
  4983. sprintf(tb,"%10.10s = %8d ","daydivisor",DayDivisor);
  4984. LeftText(tb);
  4985. }
  4986. DPY = scanpar("dpy",0);
  4987. if (DPY > 0) DaysPerYear = DPY;
  4988. Cyclical = scanpar("cyclical",Cyclical);
  4989. if (Cyclical) Cyclical = 1;
  4990. if (VerType == 0 || HorType == 0)
  4991. {
  4992. VerType = scantex("vtype" ,"ps"); // 1. char is default value (p)
  4993. HorType = scantex("htype" ,"gsfz"); // 1. char is default value (g)
  4994. }
  4995. Multi = scanpar("multi" ,0);
  4996. LevelFactor = scanreal("levelfactor",1.0);
  4997. if (NetCDF == 0) NetCDF = scanpar("netcdf",0);
  4998. HeadOu[6] = scanpar("head7",0);
  4999. mars = scanpar("mars" ,0);
  5000. FirstMonth = scanpar("first",1);
  5001. LastMonth = scanpar("last",12);
  5002. PlanetRadius = scanreal("radius",EARTH_RADIUS);
  5003. Grav = scanreal("gravity",EARTH_GRAV);
  5004. SigmaTop = scanreal("sigmatop",0.0);
  5005. vct[SigLevs] = SigmaTop;
  5006. if (FirstMonth < 1) FirstMonth = 1;
  5007. if (LastMonth > 12) LastMonth = 12;
  5008. if (LastMonth < FirstMonth) LastMonth = FirstMonth;
  5009. if (VerType == 's')
  5010. {
  5011. switch (HorType)
  5012. {
  5013. case 's': OutRep = HYB_SPEC; break;
  5014. case 'f': OutRep = HYB_FOUR; break;
  5015. case 'z': OutRep = HYB_ZONM; break;
  5016. case 'g': OutRep = HYB_GRID; break;
  5017. }
  5018. }
  5019. if (VerType == 'p')
  5020. {
  5021. switch (HorType)
  5022. {
  5023. case 's': OutRep = PRE_SPEC; break;
  5024. case 'f': OutRep = PRE_FOUR; break;
  5025. case 'z': OutRep = PRE_ZONM; break;
  5026. case 'g': OutRep = PRE_GRID; break;
  5027. }
  5028. }
  5029. if (Mean == 0) Mean = scanpar("mean" ,1);
  5030. if (Mean && OutRep < HYB_GRID)
  5031. {
  5032. sprintf(tb," mean = 1 ignored for spectral data on sigma levels");
  5033. LeftText(tb);
  5034. Mean = 0;
  5035. }
  5036. if (Multi) --Multi;
  5037. if (mars) {
  5038. Grav = MARS_GRAV;
  5039. PlanetRadius = MARS_RADIUS;
  5040. RD = MARS_RD;
  5041. }
  5042. scantime();
  5043. scancode();
  5044. DashLine();
  5045. if (VerType == 's') /* model levels */
  5046. {
  5047. scanmol();
  5048. mom[0] = 1; // surface arrays are selected always
  5049. if (nrml) /* Sigma levels explicitely given */
  5050. {
  5051. nrml = 0;
  5052. for (i=1 ; i <= SigLevs ; ++i)
  5053. {
  5054. if (mom[i])
  5055. {
  5056. level[nrml] = mol[nrml] = i;
  5057. nrml++;
  5058. }
  5059. }
  5060. SigLevs = OutLevs = nrml;
  5061. }
  5062. else /* No sigma levels specified -> select all */
  5063. {
  5064. OutLevs = nrml = SigLevs;
  5065. for (i=0 ; i < OutLevs ; ++i)
  5066. {
  5067. level[i] = mol[i] = mom[i+1] = i+1;
  5068. }
  5069. }
  5070. for (i=0 ; i < OutLevs ; ++i)
  5071. {
  5072. jind = mol[i] - 1;
  5073. LevelUnits[i] = mol[i];
  5074. SigmaF[i] = (int)(500000.0 * (vct[jind+1] - vct[jind])); // sigma * 1E6
  5075. sprintf(tb,"Level %4d = %10.6f",i+1,
  5076. 0.5 * (vct[SigLevs+mol[i]]+vct[SigLevs+mol[i]+1]));
  5077. LeftText(tb);
  5078. }
  5079. }
  5080. else /* pressure levels */
  5081. {
  5082. scanhPa();
  5083. if (nrpl)
  5084. {
  5085. OutLevs = nrpl;
  5086. for (i=0 ; i < OutLevs ; ++i)
  5087. {
  5088. level[i] = 100.0 * hPa[i];
  5089. if (hPa[i] < 0.0) Abort("pressure level < 0.0 is illegal");
  5090. // if (hPa[i] > 2000.0) Abort("pressure level > 2000 hPa is illegal");
  5091. }
  5092. }
  5093. else
  5094. {
  5095. OutLevs = nrpl = 10;
  5096. for (i=0 ; i < OutLevs ; ++i)
  5097. {
  5098. hPa[i] = (i+1) * 100.0;
  5099. level[i] = 100.0 * hPa[i];
  5100. }
  5101. }
  5102. for (i=0 ; i < OutLevs ; ++i)
  5103. {
  5104. LevelUnits[i] = (int)(LevelFactor * 100.0 * hPa[i] + 0.5);
  5105. sprintf(tb,"Level %4d = %14.4f hPa",i+1,hPa[i]);
  5106. LeftText(tb);
  5107. }
  5108. }
  5109. DashLine();
  5110. scanattributes();
  5111. for (i=0 ; i < nattr ; ++i)
  5112. {
  5113. sprintf(tb,"NetCDF attribute[%2d] :%s = \"%s\" ;",
  5114. i,AttrNam[i],AttrVal[i]);
  5115. LeftText(tb);
  5116. }
  5117. }
  5118. void dimcalc(void)
  5119. {
  5120. PolyDisk = Lats == 2048; // Currently T1365 only
  5121. Waves = Truncation + 1;
  5122. Fouriers = Waves * 2;
  5123. DimSP = (Truncation + 1) * (Truncation + 2);
  5124. DimFC = Lats * Fouriers;
  5125. DimGP = Lats * Lons;
  5126. DimGG = Gats * Gons;
  5127. Dim3GP = SigLevs * DimGP;
  5128. Dim3GG = SigLevs * DimGG;
  5129. Dim3FC = SigLevs * DimFC;
  5130. Dim3SP = SigLevs * DimSP;
  5131. DimSP_half = DimSP / 2;
  5132. DimAB = MAX(DimGG,DimGP) + MAX(Lons,Gons);
  5133. DashLine();
  5134. if (VerType == 's') LeftText("Vertical Type = Sigma [S]");
  5135. if (VerType == 'p') LeftText("Vertical Type = Pressure [P]");
  5136. if (HorType == 's') LeftText("Horizontal Type = Spherical Harmonics [S]");
  5137. if (HorType == 'f') LeftText("Horizontal Type = Fourier Coefficients [F]");
  5138. if (HorType == 'z') LeftText("Horizontal Type = Zonal Means [Z]");
  5139. if (HorType == 'g')
  5140. {
  5141. if (Lons == Gons && Lats == Gats)
  5142. {
  5143. LeftText("Horizontal Type = Gaussian Grid [G]");
  5144. GaussianOutput = 1;
  5145. }
  5146. else
  5147. {
  5148. LeftText("Horizontal Type = Grid (Lons x Lats) [G]");
  5149. GaussianOutput = 0;
  5150. }
  5151. }
  5152. DashLine();
  5153. Record_double = new double[DimAB];
  5154. Record_float = (float *)Record_double;
  5155. Record_int = (int *)Record_double;
  5156. Record_short = (unsigned short *)Record_double;
  5157. Record_char = (char *)Record_double;
  5158. CosPhi = new double[Lats];
  5159. RevCosPhi = new double[Lats];
  5160. DerivationFactor = new double[Lats];
  5161. }
  5162. /* ------------------------------------------------------ */
  5163. /* Check file OutRep and decode level number and truncation */
  5164. /* ------------------------------------------------------ */
  5165. void AnalyzeFile(void)
  5166. {
  5167. int i;
  5168. LONG fcb,fce; /* Fortran Record Control Words */
  5169. char Id[8];
  5170. char tb[COLS+2];
  5171. union EndianCheck
  5172. {
  5173. char b[sizeof(int)];
  5174. int i;
  5175. } ec;
  5176. ec.i = 8;
  5177. CoreBigEndian = ec.b[0] == 0;
  5178. fread(Id,1,8,fpi); // Read first 8 bytes
  5179. FileBigEndian = Id[0] == 0;
  5180. Endian = CoreBigEndian != FileBigEndian;
  5181. if (FileBigEndian)
  5182. {
  5183. if (Id[3] == 0) LongFCW = 1;
  5184. }
  5185. else
  5186. {
  5187. if (Id[4] == 0) LongFCW = 1;
  5188. }
  5189. rewind(fpi);
  5190. HeadSize = fcb = ReadFCW();
  5191. if (fcb != 8 && fcb != 32 && fcb != 64) Abort("Not a PUMA/PLASIM file");
  5192. CenterText("Found PUMA/Planet Simulator data set");
  5193. if (CoreBigEndian) CenterText("Running on BIG endian machine");
  5194. else CenterText("Running on little endian machine");
  5195. if (FileBigEndian) CenterText("File is in BIG endian format");
  5196. else CenterText("File is in little endian format");
  5197. if (Endian) CenterText("Endian swap activated");
  5198. if (LongFCW) CenterText("Record control words have 64 bits");
  5199. else CenterText("Record control words have 32 bits");
  5200. if (fcb == 8) CenterText("Header format: PUMA-II ");
  5201. if (fcb == 32) CenterText("Header format: Service 32 bit");
  5202. if (fcb == 64) CenterText("Header format: Service 64 bit");
  5203. BlankLine();
  5204. if (fcb == 8)
  5205. {
  5206. HeadSize = 32;
  5207. i = fread(Id,1,8,fpi);
  5208. if (strncmp(Id,"PUMA-II ",8)) Abort("PUMA-II header missing");
  5209. fce = ReadFCW();
  5210. if (check_fcw(fcb,fce)) Abort("Wrong FORTRAN control word after PUMA header");
  5211. Truncation = ReadINTRecord();
  5212. Gats = ReadINTRecord();
  5213. AllLevs = SigLevs = ReadINTRecord();
  5214. if (SigLevs < 1 || SigLevs > 1000) Abort("Illegal value for Level");
  5215. SingleLevel = (SigLevs == 1);
  5216. nvct = 2 * SigLevs + 2;
  5217. /* Check length of sigma vector and determine precision */
  5218. fcb = ReadFCW();
  5219. RealSize = fcb / SigLevs; // Should be float (4) or double (8)
  5220. if (RealSize != sizeof(float) && RealSize != sizeof(double))
  5221. Abort("FCW error on level record");
  5222. for (i = 0 ; i < SigLevs ; i++)
  5223. {
  5224. if (RealSize == sizeof(float)) vct[i+SigLevs+2] = ReadFLOAT();
  5225. else vct[i+SigLevs+2] = ReadDOUBLE();
  5226. }
  5227. fce = ReadFCW();
  5228. if (check_fcw(fcb,fce)) Abort("FCW mismatch on level record");
  5229. /* Header = "PUMA-II " Truncation Lats SigLevs sigmah */
  5230. /* 2-FCW FCW-1-FCW FCW-1-FCW FCW-1-FCW FCW-SigLevs-FCW */
  5231. HeaderWords = SigLevs * RealSize / 4 + 5 + 9 * (1 + LongFCW);
  5232. ReadHeaderRecord();
  5233. if (HeadIn[7] > 100) DaysPerYear = HeadIn[7];
  5234. }
  5235. else
  5236. {
  5237. rewind(fpi);
  5238. ReadHeaderRecord();
  5239. if (HeadIn[0] != 333) Abort("Initial code 333 was not found");
  5240. Gats = HeadIn[5];
  5241. AllLevs = SigLevs = HeadIn[6];
  5242. SingleLevel = (SigLevs == 1);
  5243. nvct = 2 * SigLevs + 2;
  5244. Truncation = HeadIn[7];
  5245. /* Check length of array and determine precision */
  5246. fcb = ReadFCW();
  5247. RealSize = fcb / (Gats * Gats * 2); // Should be float (4) or double (8)
  5248. fseek(fpi,-4*LongFCW,SEEK_CUR);
  5249. if (RealSize != sizeof(float) && RealSize != sizeof(double))
  5250. Abort("FCW error on first array");
  5251. for (i = 0 ; i < SigLevs ; i++)
  5252. {
  5253. if (RealSize == sizeof(float)) vct[i+SigLevs+2] = ReadFLOAT();
  5254. else vct[i+SigLevs+2] = ReadDOUBLE();
  5255. }
  5256. if (RealSize == sizeof(float)) DaysPerYear = ReadFLOAT();
  5257. else DaysPerYear = ReadDOUBLE();
  5258. }
  5259. HeadSt = HeadIn;
  5260. sprintf(tb,"Truncation = %6d",Truncation);
  5261. CenterText(tb);
  5262. sprintf(tb,"Latitudes = %6d",Gats);
  5263. CenterText(tb);
  5264. sprintf(tb,"Longitudes = %6d",Gats*2);
  5265. CenterText(tb);
  5266. sprintf(tb,"Sigma Levels = %6d",SigLevs);
  5267. CenterText(tb);
  5268. if (RealSize == 8)
  5269. sprintf(tb,"Double precision data: Bytes = %6d",RealSize);
  5270. else if (RealSize == 4)
  5271. sprintf(tb,"Single precision data: Bytes = %6d",RealSize);
  5272. else
  5273. sprintf(tb,"Size of real data = %6d",RealSize);
  5274. CenterText(tb);
  5275. BlankLine();
  5276. sprintf(tb,"Half Level [p] [sigma]");
  5277. CenterText(tb);
  5278. for (i = 0; i<nvct/2; i++)
  5279. {
  5280. sprintf(tb,"%10.1f %14.4f %14.4f",(float)i,vct[i],vct[i+nvct/2]);
  5281. CenterText(tb);
  5282. }
  5283. StarLine();
  5284. rewind(fpi);
  5285. }
  5286. const char *MoName[13] = {"Nix","Jan","Feb","Mar","Apr","May","Jun",
  5287. "Jul","Aug","Sep","Oct","Nov","Dec"};
  5288. void WriteGradsCtl()
  5289. {
  5290. int i,j,yy,mm,dd,code,varcodes;
  5291. FILE *fp;
  5292. double DelLon;
  5293. fp = fopen(gfile,"w");
  5294. if (HorType == 'z')
  5295. fprintf(fp,"DSET ^%s\n",rfile);
  5296. else
  5297. fprintf(fp,"DSET ^%s\n",ofile);
  5298. fprintf(fp,"UNDEF 9e09i\n");
  5299. if (HorType == 'z')
  5300. fprintf(fp,"XDEF 1 LINEAR 0 1\n");
  5301. else
  5302. {
  5303. DelLon = 360.0 / Gons;
  5304. fprintf(fp,"XDEF %5d LINEAR 0.0 %14.8f\n",Gons,DelLon);
  5305. }
  5306. fprintf(fp,"OPTIONS YREV\n");
  5307. fprintf(fp,"YDEF %5d LEVELS\n",Gats);
  5308. for (j=Gats-1 ; j >= 0 ; j-=8)
  5309. {
  5310. for (i=j ; i >= 0 && i> j-8 ; --i)
  5311. fprintf(fp,"%14.8f",Outlat->Phi[i]);
  5312. fprintf(fp,"\n");
  5313. }
  5314. if (HorType != 'z')
  5315. {
  5316. fprintf(fp,"OPTIONS SEQUENTIAL\n");
  5317. fprintf(fp,"XYHEADER %d\n",40 + 8 * LongFCW);
  5318. }
  5319. if (OutLevs < 2)
  5320. {
  5321. if (VerType == 'p') fprintf(fp,"ZDEF 1 LINEAR %14.8f 1\n",hPa[0]);
  5322. else fprintf(fp,"ZDEF 1 LINEAR %d 1\n",mol[0]);
  5323. }
  5324. else
  5325. {
  5326. fprintf(fp,"ZDEF %d LEVELS\n",OutLevs);
  5327. if (VerType == 'p')
  5328. {
  5329. for (j=0 ; j < OutLevs ; j+=8)
  5330. {
  5331. for (i=j ; i < OutLevs && i < j+8 ; ++i)
  5332. if (HorType == 'z' && hPa[0] < hPa[OutLevs-1])
  5333. fprintf(fp,"%14.8f",hPa[OutLevs-1-i]);
  5334. else
  5335. fprintf(fp,"%14.8f",hPa[i]);
  5336. fprintf(fp,"\n");
  5337. }
  5338. if (HorType == 'z' && hPa[0] < hPa[OutLevs-1])
  5339. fprintf(fp,"OPTIONS ZREV\n");
  5340. }
  5341. else
  5342. {
  5343. for (j=0 ; j < OutLevs ; j+=8)
  5344. {
  5345. for (i=j ; i < OutLevs && i < j+8 ; ++i)
  5346. if (HorType == 'z' && mol[0] < mol[OutLevs-1])
  5347. fprintf(fp,"%10d",mol[OutLevs-1-i]);
  5348. else
  5349. fprintf(fp,"%10d",mol[i]);
  5350. fprintf(fp,"\n");
  5351. }
  5352. if (HorType == 'z' && mol[0] < mol[OutLevs-1])
  5353. fprintf(fp,"OPTIONS ZREV\n");
  5354. }
  5355. }
  5356. yy = HeadSt[2] / 10000;
  5357. mm = HeadSt[2] / 100 % 100;
  5358. dd = HeadSt[2] % 100;
  5359. if (Mean)
  5360. fprintf(fp,"TDEF %d LINEAR 00:00z%d%s%d 1mo\n",
  5361. MonthCount,dd,MoName[mm],yy);
  5362. else if (DeltaMn > 0)
  5363. fprintf(fp,"TDEF %d LINEAR 00:00z%d%s%d %dmn\n",
  5364. TermCount,dd,MoName[mm],yy,DeltaMn);
  5365. else if (DeltaHr > 0)
  5366. fprintf(fp,"TDEF %d LINEAR 00:00z%d%s%d %dhr\n",
  5367. TermCount,dd,MoName[mm],yy,DeltaHr);
  5368. else
  5369. fprintf(fp,"TDEF %d LINEAR 00:00z%d%s%d %ddy\n",
  5370. TermCount,dd,MoName[mm],yy,DeltaDy);
  5371. varcodes = 0;
  5372. for (code = 0 ; code < CODES ; ++code)
  5373. if (All[code].selected) ++varcodes;
  5374. fprintf(fp,"VARS %d\n",varcodes);
  5375. for (code = 0 ; code < CODES ; ++code)
  5376. if (All[code].selected)
  5377. fprintf(fp,"%s %d 99 %s\n",
  5378. All[code].Id,All[code].plev,All[code].Na);
  5379. fprintf(fp,"ENDVARS\n");
  5380. fclose(fp);
  5381. }
  5382. int main(int argc, char *argv[])
  5383. {
  5384. int i,l;
  5385. int wdim;
  5386. char tb[COLS+2];
  5387. time_t StartTime;
  5388. StartTime = time(NULL);
  5389. /*********************/
  5390. /* print information */
  5391. /*********************/
  5392. StarLine();
  5393. CenterText(V0);
  5394. CenterText(V1);
  5395. DashLine();
  5396. CenterText(V2);
  5397. CenterText(V3);
  5398. CenterText(V4);
  5399. StarLine();
  5400. sprintf(tb,"Run started at %s",ctime(&StartTime));
  5401. strcpy(tb+strlen(tb)-1," local time");
  5402. CenterText(tb);
  5403. StarLine();
  5404. InitAll();
  5405. /***********************/
  5406. /* options & filenames */
  5407. /***********************/
  5408. for (i = 1 ; i < argc ; ++i) {
  5409. if (argv[i][0] == '-') {
  5410. if (argv[i][1] == 'c') {PrintCodes(); exit(1);}
  5411. else if (argv[i][1] == 'd') Debug = 1;
  5412. else if (argv[i][1] == 'v') Debug = 1;
  5413. else if (argv[i][1] == 'n') NetCDF = 1;
  5414. else if (argv[i][1] == 'g') Grads = 1;
  5415. else if (argv[i][1] == 'm') Mean = 1;
  5416. else if (argv[i][1] == 'p') PolyCreate = 1;
  5417. else if (argv[i][1] == 'i') GaussGrid = 1;
  5418. else if (argv[i][1] == 'r') GaussGrid = 0;
  5419. else if (argv[i][1] == 's') SaveMemory = 1;
  5420. else Usage();
  5421. }
  5422. else if (ifile[0] == '\0') strcpy(ifile,argv[i]);
  5423. else if (ofile[0] == '\0') strcpy(ofile,argv[i]);
  5424. else if (strcmp("Debug",argv[i]) == 0) Debug = 1;
  5425. else Usage();
  5426. }
  5427. if (NetCDF) Grads = 0;
  5428. if (ifile[0] == '\0' || ofile[0] == '\0') {
  5429. printf("*** Missing filename ***\n");
  5430. Usage();
  5431. }
  5432. /*******************/
  5433. /* open input file */
  5434. /*******************/
  5435. fpi = fopen(ifile,"rb");
  5436. if (fpi == 0) {
  5437. printf("could not open input file %s\n",ifile);
  5438. exit(1);
  5439. }
  5440. /******************/
  5441. /* pre-processing */
  5442. /******************/
  5443. AnalyzeFile();
  5444. Gons = Gats * 2;
  5445. Lats = Gats;
  5446. Lons = Gons;
  5447. /*******************/
  5448. /* initializations */
  5449. /*******************/
  5450. parini();
  5451. l = strlen(ofile);
  5452. if (NetCDF) // Add ".nc" extension for NetCDF filename if not specified
  5453. {
  5454. if (l < 4 || strcmp(ofile+l-3,".nc")) strcat(ofile,".nc");
  5455. }
  5456. else // Add ".srv" extension for Service format if not specified
  5457. {
  5458. if (l > 4 && !strcmp(ofile+l-4,".srv")) l -= 4;
  5459. ofile[l] = 0;
  5460. strcpy(gfile,ofile);
  5461. strcpy(rfile,ofile);
  5462. strcat(ofile,".srv");
  5463. strcat(gfile,".ctl");
  5464. strcat(rfile,".gra");
  5465. }
  5466. sprintf(tb," Input File: %s",ifile); LeftText(tb);
  5467. sprintf(tb,"Output File: %s",ofile); LeftText(tb);
  5468. if (Grads) {sprintf(tb,"Grads File: %s",gfile); LeftText(tb);}
  5469. if (Grads && HorType == 'z')
  5470. {sprintf(tb,"Grads Data: %s",rfile); LeftText(tb);}
  5471. if (Debug) LeftText("Debug on");
  5472. #ifndef NETCDF_OUTPUT
  5473. if (NetCDF) Abort("This executable was not compiled for NetCDF");
  5474. #endif
  5475. /********************/
  5476. /* open output file */
  5477. /********************/
  5478. if (!NetCDF)
  5479. {
  5480. gp = fopen(ofile,"wb");
  5481. if (gp == 0)
  5482. {
  5483. printf("could not open output file <%s>\n",ofile);
  5484. exit(1);
  5485. }
  5486. }
  5487. dimcalc();
  5488. HybSpec = new ServiceGrid(gp,DimSP,1);
  5489. HybFour = new ServiceGrid(gp,Lats,Fouriers);
  5490. HybGrid = new ServiceGrid(gp,Lons,Lats);
  5491. HybSect = new ServiceSect(gp,Lats,OutLevs);
  5492. /* FFT initialization */
  5493. if (OutLevs <= SigLevs) wdim = (Lons + 3) * Lats * SigLevs;
  5494. else wdim = (Lons + 3) * Lats * OutLevs ;
  5495. wfc = new double[wdim];
  5496. wgp = new double[wdim];
  5497. fft_set(Lons);
  5498. filename = strrchr(ifile,'/');
  5499. if (filename == 0) filename = ifile;
  5500. else filename++ ;
  5501. HeadOu[7] = atol(filename);
  5502. if (VerType == 'p' &&
  5503. (Divergence->selected || VeloPot->selected ||
  5504. Vorticity->selected || StreamF->selected))
  5505. SpecialUV = 1;
  5506. Dependencies();
  5507. // Check correct vertical coordinate
  5508. if (GeopotHeight->selected && VerType != 'p')
  5509. {
  5510. printf("\n ****************** E R R O R ************************\n");
  5511. printf(" * Geopotential height (156) requires pressure level *\n");
  5512. printf(" *****************************************************\n");
  5513. exit(1);
  5514. }
  5515. Geopotential->needed |= OutRep >= PRE_GRID
  5516. || SLP->needed || GeopotHeight->needed;
  5517. if (OutRep) legini();
  5518. if (PolyCreate) exit(0); /* Called for Legendre Polynomials only */
  5519. #ifdef NETCDF_OUTPUT
  5520. if (NetCDF) NetOpen(ofile);
  5521. #endif
  5522. PumaControl();
  5523. if (gp) fclose(gp);
  5524. #ifdef NETCDF_OUTPUT
  5525. if (NetCDF) NetClose();
  5526. #endif
  5527. if (Grads) WriteGradsCtl();
  5528. StarLine();
  5529. if (DaysPerYear < 1) DaysPerYear = 360;
  5530. if (DPM > 99) DaysPerYear = DPM * 12;
  5531. sprintf(tb,"Using %d day calendar",DaysPerYear);
  5532. CenterText(tb);
  5533. sprintf(tb,"Data interval = %6.2f hours",DataStep * 24.0);
  5534. CenterText(tb);
  5535. StarLine();
  5536. {
  5537. double ut,st;
  5538. struct rusage ru;
  5539. getrusage(RUSAGE_SELF,&ru);
  5540. ut = ru.ru_utime.tv_sec + 0.000001 * ru.ru_utime.tv_usec;
  5541. st = ru.ru_stime.tv_sec + 0.000001 * ru.ru_stime.tv_usec;
  5542. sprintf(tb,"User time: %10.3lf seconds",ut);
  5543. LeftText(tb);
  5544. sprintf(tb,"System time: %10.3lf seconds",st);
  5545. LeftText(tb);
  5546. sprintf(tb,"Total time: %10.3lf seconds",ut+st);
  5547. LeftText(tb);
  5548. if (ru.ru_maxrss > 0)
  5549. {
  5550. sprintf(tb,"Memory usage: %10.3lf MBytes",0.000001 * ru.ru_maxrss);
  5551. LeftText(tb);
  5552. }
  5553. if (ru.ru_minflt > 0)
  5554. {
  5555. sprintf(tb,"Page reclaims: %10ld page",ru.ru_minflt);
  5556. if (ru.ru_minflt != 1) strcat(tb,"s");
  5557. LeftText(tb);
  5558. }
  5559. if (ru.ru_majflt > 0)
  5560. {
  5561. sprintf(tb,"Page faults: %10ld page",ru.ru_majflt);
  5562. if (ru.ru_majflt != 1) strcat(tb,"s");
  5563. LeftText(tb);
  5564. }
  5565. if (ru.ru_nswap > 0)
  5566. {
  5567. sprintf(tb,"Swaps : %10ld",ru.ru_nswap);
  5568. LeftText(tb);
  5569. }
  5570. if (ru.ru_inblock > 0)
  5571. {
  5572. sprintf(tb,"Disk read: %10ld block",ru.ru_inblock);
  5573. if (ru.ru_inblock != 1) strcat(tb,"s");
  5574. LeftText(tb);
  5575. }
  5576. if (ru.ru_oublock > 0)
  5577. {
  5578. sprintf(tb,"Disk Write: %10ld block",ru.ru_oublock);
  5579. if (ru.ru_oublock != 1) strcat(tb,"s");
  5580. LeftText(tb);
  5581. }
  5582. StarLine();
  5583. }
  5584. return 0;
  5585. }