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