/* This file is part of CDO. CDO is a collection of Operators to manipulate and analyse Climate model Data. Copyright (C) 2006 Brockmann Consult See COPYING file for copying and redistribution conditions. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ /* This module contains the following operators: Seaspctl seaspctl Seasonal percentiles */ #include #include "cdo.h" #include "cdo_int.h" #include "pstream.h" #include "percentiles_hist.h" #include "util.h" void *Seaspctl(void *argument) { int timestat_date = TIMESTAT_MEAN; int vdate1 = 0; int vdate2 = 0, vtime2 = 0; int vdate3 = 0, vtime3 = 0; int nrecs; int gridID, varID, levelID, recID; int tsID; int otsID; long nsets; int year, month, day, seas, seas0 = 0; int nmiss; int nlevels; int newseas, oldmon = 0, newmon; double missval; field_t **vars1 = NULL; field_t field; HISTOGRAM_SET *hset = NULL; int season_start; cdoInitialize(argument); cdoOperatorAdd("seaspctl", func_pctl, 0, NULL); operatorInputArg("percentile number"); double pn = parameter2double(operatorArgv()[0]); percentile_check_number(pn); season_start = get_season_start(); int streamID1 = streamOpenRead(cdoStreamName(0)); int streamID2 = streamOpenRead(cdoStreamName(1)); int streamID3 = streamOpenRead(cdoStreamName(2)); int vlistID1 = streamInqVlist(streamID1); int vlistID2 = streamInqVlist(streamID2); int vlistID3 = streamInqVlist(streamID3); int vlistID4 = vlistDuplicate(vlistID1); vlistCompare(vlistID1, vlistID2, CMP_ALL); vlistCompare(vlistID1, vlistID3, CMP_ALL); int taxisID1 = vlistInqTaxis(vlistID1); int taxisID2 = vlistInqTaxis(vlistID2); int taxisID3 = vlistInqTaxis(vlistID3); /* TODO - check that time axes 2 and 3 are equal */ int taxisID4 = taxisDuplicate(taxisID1); vlistDefTaxis(vlistID4, taxisID4); int streamID4 = streamOpenWrite(cdoStreamName(3), cdoFiletype()); streamDefVlist(streamID4, vlistID4); int nvars = vlistNvars(vlistID1); int nrecords = vlistNrecs(vlistID1); int *recVarID = (int*) Malloc(nrecords * sizeof(int)); int *recLevelID = (int*) Malloc(nrecords * sizeof(int)); dtlist_type *dtlist = dtlist_new(); dtlist_set_stat(dtlist, timestat_date); dtlist_set_calendar(dtlist, taxisInqCalendar(taxisID1)); int gridsize = vlistGridsizeMax(vlistID1); field.ptr = (double*) Malloc(gridsize*sizeof(double)); vars1 = (field_t **) Malloc(nvars * sizeof(field_t *)); hset = hsetCreate(nvars); for ( varID = 0; varID < nvars; varID++ ) { gridID = vlistInqVarGrid(vlistID1, varID); gridsize = gridInqSize(gridID); nlevels = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID)); missval = vlistInqVarMissval(vlistID1, varID); vars1[varID] = (field_t*) Malloc(nlevels * sizeof(field_t)); hsetCreateVarLevels(hset, varID, nlevels, gridID); for ( levelID = 0; levelID < nlevels; levelID++ ) { vars1[varID][levelID].grid = gridID; vars1[varID][levelID].nmiss = 0; vars1[varID][levelID].missval = missval; vars1[varID][levelID].ptr = (double*) Malloc(gridsize * sizeof(double)); } } tsID = 0; otsID = 0; while ( TRUE ) { nrecs = streamInqTimestep(streamID2, otsID); if ( nrecs != streamInqTimestep(streamID3, otsID) ) cdoAbort("Number of records at time step %d of %s and %s differ!", otsID+1, cdoStreamName(1)->args, cdoStreamName(2)->args); vdate2 = taxisInqVdate(taxisID2); vtime2 = taxisInqVtime(taxisID2); vdate3 = taxisInqVdate(taxisID3); vtime3 = taxisInqVtime(taxisID3); if ( vdate2 != vdate3 || vtime2 != vtime3 ) cdoAbort("Verification dates at time step %d of %s and %s differ!", otsID+1, cdoStreamName(1)->args, cdoStreamName(2)->args); for ( recID = 0; recID < nrecs; recID++ ) { streamInqRecord(streamID2, &varID, &levelID); streamReadRecord(streamID2, vars1[varID][levelID].ptr, &nmiss); vars1[varID][levelID].nmiss = nmiss; } for ( recID = 0; recID < nrecs; recID++ ) { streamInqRecord(streamID3, &varID, &levelID); streamReadRecord(streamID3, field.ptr, &nmiss); field.nmiss = nmiss; field.grid = vars1[varID][levelID].grid; field.missval = vars1[varID][levelID].missval; hsetDefVarLevelBounds(hset, varID, levelID, &vars1[varID][levelID], &field); } nsets = 0; newseas = FALSE; while ( nrecs && (nrecs = streamInqTimestep(streamID1, tsID)) ) { dtlist_taxisInqTimestep(dtlist, taxisID1, nsets); vdate1 = dtlist_get_vdate(dtlist, nsets); cdiDecodeDate(vdate1, &year, &month, &day); newmon = month; if ( season_start == START_DEC && newmon == 12 ) newmon = 0; seas = month_to_season(month); if ( nsets == 0 ) { seas0 = seas; oldmon = newmon; } if ( newmon < oldmon ) newseas = TRUE; if ( (seas != seas0) || newseas ) break; oldmon = newmon; for ( recID = 0; recID < nrecs; recID++ ) { streamInqRecord(streamID1, &varID, &levelID); if ( tsID == 0 ) { recVarID[recID] = varID; recLevelID[recID] = levelID; } streamReadRecord(streamID1, vars1[varID][levelID].ptr, &nmiss); vars1[varID][levelID].nmiss = nmiss; hsetAddVarLevelValues(hset, varID, levelID, &vars1[varID][levelID]); } nsets++; tsID++; } if ( nrecs == 0 && nsets == 0 ) break; for ( varID = 0; varID < nvars; varID++ ) { if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue; nlevels = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID)); for ( levelID = 0; levelID < nlevels; levelID++ ) hsetGetVarLevelPercentiles(&vars1[varID][levelID], hset, varID, levelID, pn); } dtlist_stat_taxisDefTimestep(dtlist, taxisID4, nsets); streamDefTimestep(streamID4, otsID); for ( recID = 0; recID < nrecords; recID++ ) { varID = recVarID[recID]; levelID = recLevelID[recID]; if ( otsID && vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue; streamDefRecord(streamID4, varID, levelID); streamWriteRecord(streamID4, vars1[varID][levelID].ptr, vars1[varID][levelID].nmiss); } if ( nrecs == 0 ) break; otsID++; } for ( varID = 0; varID < nvars; varID++ ) { nlevels = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID)); for ( levelID = 0; levelID < nlevels; levelID++ ) Free(vars1[varID][levelID].ptr); Free(vars1[varID]); } Free(vars1); hsetDestroy(hset); dtlist_delete(dtlist); if ( field.ptr ) Free(field.ptr); if ( recVarID ) Free(recVarID); if ( recLevelID ) Free(recLevelID); streamClose(streamID4); streamClose(streamID3); streamClose(streamID2); streamClose(streamID1); cdoFinish(); return 0; }