mirror of https://github.com/ecmwf/eccodes.git
345 lines
12 KiB
Modula-2
345 lines
12 KiB
Modula-2
constant ECMWF = 98 : hidden;
|
|
constant WMO = 0;
|
|
constant conceptsMasterDir="grib1" : hidden;
|
|
constant conceptsLocalDirECMF="grib1/localConcepts/ecmf" : hidden;
|
|
constant conceptsLocalDirAll="grib1/localConcepts/[centre:s]" : hidden;
|
|
|
|
constant tablesMasterDir="grib1" : hidden;
|
|
constant tablesLocalDir="grib1/local/[centre:s]" : hidden;
|
|
|
|
# ECC-806: Local concepts precedence order
|
|
if (preferLocalConcepts) {
|
|
constant conceptsDir1 = conceptsMasterDir : hidden;
|
|
constant conceptsDir2 = conceptsLocalDirAll : hidden;
|
|
} else {
|
|
constant conceptsDir1 = conceptsLocalDirAll : hidden;
|
|
constant conceptsDir2 = conceptsMasterDir : hidden;
|
|
}
|
|
|
|
transient productionStatusOfProcessedData=0;
|
|
position offsetSection1;
|
|
section_length[3] section1Length;
|
|
meta section1Pointer section_pointer(offsetSection1,section1Length,1);
|
|
constant wrongPadding=0;
|
|
|
|
# GRIB tables Version No.
|
|
# (currently 3 for international exchange)
|
|
unsigned[1] table2Version : edition_specific,dump;
|
|
alias gribTablesVersionNo=table2Version;
|
|
|
|
#assert(section1Length > 5);
|
|
|
|
# Identification of originating/generating centre
|
|
codetable[1] centre 'common/c-1.table' : dump,string_type;
|
|
alias identificationOfOriginatingGeneratingCentre=centre;
|
|
meta centreDescription codetable_title(centre);
|
|
|
|
alias parameter.centre=centre;
|
|
alias originatingCentre=centre;
|
|
alias ls.centre = centre;
|
|
|
|
# Generating process identification number
|
|
unsigned[1] generatingProcessIdentifier : dump;
|
|
alias generatingProcessIdentificationNumber=generatingProcessIdentifier;
|
|
alias process=generatingProcessIdentifier;
|
|
|
|
unsigned[1] gridDefinition = 255 : edition_specific;
|
|
flags[1] section1Flags 'grib1/1.table' = 128 : hidden; # = section 2 present
|
|
|
|
alias centreForTable2=centre;
|
|
|
|
codetable[1] indicatorOfParameter 'grib1/2.[centreForTable2:l].[table2Version:l].table' : edition_specific,no_copy,dump;
|
|
meta parameterName codetable_title(indicatorOfParameter);
|
|
meta parameterUnits codetable_units(indicatorOfParameter);
|
|
|
|
# Local comes before Master to give precedence to the local, centre-specific table
|
|
codetable[1] indicatorOfTypeOfLevel ('3.table',tablesLocalDir,tablesMasterDir) : edition_specific,no_copy,dump,string_type;
|
|
alias levelType=indicatorOfTypeOfLevel;
|
|
|
|
transient pressureUnits="hPa";
|
|
|
|
concept typeOfLevelECMF (unknown, "typeOfLevel.def",conceptsMasterDir,conceptsLocalDirECMF);
|
|
concept vertical.typeOfLevel (typeOfLevelECMF, "typeOfLevel.def",conceptsDir2,conceptsDir1);
|
|
|
|
when ( typeOfLevel is "isobaricInPa" ) { set pressureUnits="Pa"; }
|
|
else { set pressureUnits="hPa";}
|
|
|
|
alias ls.typeOfLevel=typeOfLevel;
|
|
|
|
if ( indicatorOfTypeOfLevel == 101 or
|
|
indicatorOfTypeOfLevel == 104 or
|
|
indicatorOfTypeOfLevel == 106 or
|
|
indicatorOfTypeOfLevel == 108 or
|
|
indicatorOfTypeOfLevel == 110 or
|
|
indicatorOfTypeOfLevel == 112 or
|
|
indicatorOfTypeOfLevel == 114 or
|
|
indicatorOfTypeOfLevel == 116 or
|
|
indicatorOfTypeOfLevel == 120 or
|
|
indicatorOfTypeOfLevel == 121 or
|
|
indicatorOfTypeOfLevel == 128 or
|
|
indicatorOfTypeOfLevel == 141 )
|
|
{
|
|
unsigned[1] topLevel : can_be_missing,dump;
|
|
unsigned[1] bottomLevel : can_be_missing,dump;
|
|
meta levels sprintf("%d-%d",topLevel,bottomLevel) : dump;
|
|
alias ls.levels=levels;
|
|
alias vertical.level = topLevel;
|
|
alias vertical.topLevel = topLevel;
|
|
alias vertical.bottomLevel = bottomLevel;
|
|
}
|
|
else
|
|
{
|
|
unsigned[2] level : can_be_missing,dump;
|
|
if (indicatorOfTypeOfLevel == 210) {
|
|
meta marsLevel scale(level,oneConstant,hundred) : read_only;
|
|
alias mars.levelist = marsLevel;
|
|
}
|
|
alias vertical.level=level;
|
|
alias vertical.topLevel = level;
|
|
alias vertical.bottomLevel = level;
|
|
alias ls.level=level;
|
|
alias lev=level;
|
|
}
|
|
|
|
if( indicatorOfTypeOfLevel == 109 ||
|
|
indicatorOfTypeOfLevel == 100 ||
|
|
indicatorOfTypeOfLevel == 110 ||
|
|
indicatorOfTypeOfLevel == 113 ||
|
|
indicatorOfTypeOfLevel == 117 ||
|
|
indicatorOfTypeOfLevel == 203)
|
|
{
|
|
alias mars.levelist = level;
|
|
}
|
|
|
|
unsigned[1] yearOfCentury : edition_specific;
|
|
unsigned[1] month;
|
|
unsigned[1] day;
|
|
unsigned[1] hour;
|
|
unsigned[1] minute;
|
|
transient second = 0;
|
|
|
|
codetable[1] unitOfTimeRange 'grib1/4.table' = 1 : edition_specific;
|
|
alias unitOfTime=unitOfTimeRange;
|
|
alias indicatorOfUnitOfTimeRange=unitOfTimeRange;
|
|
|
|
unsigned[1] P1 : edition_specific;
|
|
|
|
unsigned[1] P2 : edition_specific;
|
|
|
|
# Local comes before Master to give precedence to the local, centre-specific table
|
|
codetable[1] timeRangeIndicator ('5.table',tablesLocalDir,tablesMasterDir) = 1 : dump,edition_specific;
|
|
|
|
unsigned[2] numberIncludedInAverage;
|
|
|
|
unsigned[1] numberMissingFromAveragesOrAccumulations;
|
|
unsigned[1] centuryOfReferenceTimeOfData;
|
|
|
|
codetable[1] subCentre 'grib1/0.[centre].table' : dump;
|
|
|
|
if(table2Version >= 128) {
|
|
_if (centre != 98 && subCentre == 98) {
|
|
alias centreForTable2 = subCentre;
|
|
} else {
|
|
alias centreForTable2 = centre;
|
|
}
|
|
} else {
|
|
alias centreForTable2 = WMO;
|
|
}
|
|
|
|
#if ( subCentre == 98 ) {
|
|
# alias conceptsLocalDir=conceptsLocalDirECMF;
|
|
#} else {
|
|
# alias conceptsLocalDir=conceptsLocalDirAll;
|
|
#}
|
|
|
|
concept paramIdECMF (defaultParameter,"paramId.def",conceptsMasterDir,conceptsLocalDirECMF): no_copy;
|
|
concept paramId (paramIdECMF,"paramId.def",conceptsDir2,conceptsDir1): long_type,dump;
|
|
# transient pid = paramId : hidden;
|
|
|
|
concept cfNameECMF(defaultName,"cfName.def",conceptsMasterDir,conceptsLocalDirECMF) : no_copy,read_only;
|
|
concept cfName(cfNameECMF,"cfName.def",conceptsDir2,conceptsDir1) : dump,no_copy,read_only;
|
|
|
|
concept unitsECMF(defaultName,"units.def",conceptsMasterDir,conceptsLocalDirECMF) : no_copy,read_only;
|
|
concept units(unitsECMF,"units.def",conceptsDir2,conceptsDir1) : dump,no_copy,read_only;
|
|
|
|
concept nameECMF(defaultName,"name.def",conceptsMasterDir,conceptsLocalDirECMF) : no_copy,read_only;
|
|
concept name(nameECMF,"name.def",conceptsDir2,conceptsDir1) : dump,no_copy,read_only;
|
|
|
|
signed[2] decimalScaleFactor :dump;
|
|
transient setLocalDefinition= 0 : no_copy;
|
|
|
|
# Try different values of binaryScaleFactor and decimalScaleFactor to reduce packing error
|
|
transient optimizeScaleFactor = 0;
|
|
|
|
meta dataDate g1date(centuryOfReferenceTimeOfData,yearOfCentury,month,day) : dump;
|
|
meta year evaluate(dataDate / 10000);
|
|
|
|
meta dataTime time(hour,minute,second) : dump;
|
|
meta julianDay julian_day(dataDate,hour,minute,second) : edition_specific;
|
|
|
|
codetable[1] stepUnits 'stepUnits.table' = 1 : transient,dump,no_copy;
|
|
# The lowercase version is to unify it with the helper key in the MARS language
|
|
alias stepunits = stepUnits;
|
|
|
|
concept_nofail stepType (timeRangeIndicator, "stepType.def", conceptsDir2, conceptsDir1);
|
|
|
|
#alias stepTypeInternal=stepType;
|
|
#alias lengthOfTimeRange=numberIncludedInAverage;
|
|
#alias indicatorOfUnitForTimeRange=unitOfTimeRange;
|
|
#alias indicatorOfUnitForTimeIncrement=zero;
|
|
#alias timeIncrement=zero;
|
|
|
|
#if (timeRangeIndicator==113) {
|
|
# alias lengthOfTimeRange=numberIncludedInAverage;
|
|
# alias indicatorOfUnitForTimeRange=unitOfTimeRange;
|
|
# alias indicatorOfUnitForTimeIncrement=unitOfTimeRange;
|
|
# alias timeIncrement=P2;
|
|
# alias forecastTime=P1;
|
|
#}
|
|
|
|
#if (stepType is "accum") {
|
|
# transient accumulationRange=P2-P1;
|
|
# alias lengthOfTimeRange=accumulationRange;
|
|
# alias forecastTime=P1;
|
|
# alias indicatorOfUnitForTimeRange=unitOfTimeRange;
|
|
#}
|
|
|
|
#conversion 1->2
|
|
_if (stepType is "instant" ) {
|
|
alias productDefinitionTemplateNumber=zero;
|
|
} else {
|
|
alias productDefinitionTemplateNumber=eight;
|
|
}
|
|
|
|
meta stepRange g1step_range(P1,P2,timeRangeIndicator,unitOfTimeRange,stepUnits,stepType) : dump;
|
|
meta startStep long_vector(stepRange,0) : dump,no_copy;
|
|
meta endStep long_vector(stepRange,1) : dump,no_copy;
|
|
meta stepHumanReadable step_human_readable(stepUnits, stepRange): hidden,no_copy;
|
|
|
|
alias stepInHours = endStep;
|
|
alias ls.stepRange = stepRange;
|
|
alias ls.dataDate = dataDate;
|
|
|
|
alias mars.step = endStep;
|
|
alias mars.date = dataDate;
|
|
alias mars.levtype = indicatorOfTypeOfLevel;
|
|
alias mars.time = dataTime;
|
|
#alias mars.param = paramId;
|
|
meta marsParam mars_param(paramId,gribTablesVersionNo,indicatorOfParameter): read_only,dump;
|
|
alias mars.param = marsParam;
|
|
|
|
# GRIB-860: JRA55 rule for MARS.
|
|
# subCentre of 241 means Japanese Reanalysis Project
|
|
if (centre == 34 && subCentre == 241)
|
|
{
|
|
alias mars.param = paramId;
|
|
|
|
if (indicatorOfTypeOfLevel == 101) {
|
|
# See ECC-467
|
|
constant sfc_levtype = "sfc";
|
|
alias mars.levtype = sfc_levtype;
|
|
}
|
|
}
|
|
|
|
meta time.validityDate validity_date(dataDate,dataTime,step,stepUnits);
|
|
meta time.validityTime validity_time(dataDate,dataTime,step,stepUnits);
|
|
meta validityDateTime julian_date(validityDate, validityTime) : no_copy;
|
|
|
|
transient deleteLocalDefinition=0;
|
|
|
|
if(((section1Length > 40) or new() or setLocalDefinition> 0) and deleteLocalDefinition==0)
|
|
{
|
|
constant localUsePresent = 1 : edition_specific;
|
|
alias grib2LocalSectionPresent=present;
|
|
|
|
if( (centre == ECMWF) or
|
|
(centre != ECMWF and
|
|
subCentre == ECMWF))
|
|
{
|
|
pad reservedNeedNotBePresent(12);
|
|
codetable[1] localDefinitionNumber 'grib1/localDefinitionNumber.98.table' = 1 : dump;
|
|
template_nofail localDefinition "grib1/local.98.[localDefinitionNumber:l].def";
|
|
if (changed(localDefinitionNumber)) {
|
|
if(!new() && localDefinitionNumber!=4 ) {
|
|
section_padding localExtensionPadding : read_only;
|
|
}
|
|
}
|
|
|
|
template_nofail marsKeywords "mars/grib.[stream:s].[type:s].def";
|
|
}
|
|
else
|
|
{
|
|
if ( !new() || setLocalDefinition ) {
|
|
# Other centres
|
|
pad reservedNeedNotBePresent(12);
|
|
template_nofail localDefinition "grib1/local.[centre:l].def";
|
|
|
|
section_padding localExtensionPadding : read_only;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
constant localUsePresent = 0 : edition_specific;
|
|
}
|
|
|
|
section_padding section1Padding : read_only;
|
|
|
|
#if (!wrongPadding) {
|
|
# padtoeven evenpadding_sec1(offsetSection1,section1Length);
|
|
#}
|
|
|
|
concept shortNameECMF (defaultShortName,"shortName.def",conceptsMasterDir,conceptsLocalDirECMF) : no_copy;
|
|
concept ls.shortName (shortNameECMF,"shortName.def",conceptsDir2,conceptsDir1) : no_copy,dump;
|
|
|
|
#concept cfVarNameECMF(defaultName,"cfVarName.def",conceptsMasterDir,conceptsLocalDirECMF) : no_copy,read_only;
|
|
#concept cfVarName(cfVarNameECMF,"cfVarName.def",conceptsDir2,conceptsDir1) : dump,no_copy,read_only;
|
|
# See ECC-1886
|
|
meta defaultCfVarName cf_var_name(shortName) : hidden, read_only;
|
|
concept cfVarNameECMF(defaultCfVarName,"cfVarName.def",conceptsMasterDir,conceptsLocalDirECMF) : no_copy,read_only;
|
|
concept cfVarName(cfVarNameECMF,"cfVarName.def",conceptsDir2,conceptsDir1) : dump,no_copy,read_only;
|
|
|
|
meta ifsParam ifs_param(paramId,type);
|
|
|
|
alias parameter.paramId=paramId;
|
|
alias parameter.shortName=shortName;
|
|
alias parameter.units=units;
|
|
alias parameter.name=name;
|
|
|
|
alias parameter=paramId;
|
|
alias short_name=shortName;
|
|
|
|
alias time.stepRange=stepRange;
|
|
alias time.stepUnits=stepUnits;
|
|
alias time.dataDate=dataDate;
|
|
alias time.dataTime=dataTime;
|
|
alias time.startStep=startStep;
|
|
alias time.endStep=endStep;
|
|
alias time.stepType=stepType;
|
|
|
|
# ECC-457: GRIB1 to GRIB2 conversion
|
|
concept_nofail stepTypeForConversion (unknown, "stepTypeForConversion.def", conceptsDir2, conceptsDir1);
|
|
if (stepTypeForConversion is "accum" || stepTypeForConversion is "max" || stepTypeForConversion is "min" || stepTypeForConversion is "avg") {
|
|
if (productDefinitionTemplateNumber == 1) {
|
|
alias productDefinitionTemplateNumber=eleven;
|
|
}
|
|
else {
|
|
alias productDefinitionTemplateNumber=eight;
|
|
}
|
|
}
|
|
|
|
meta md5Section1 md5(offsetSection1,section1Length);
|
|
# md5(start,length,blacklisted1,blacklisted2,...);
|
|
meta md5Product md5(offsetSection1,section1Length,gridDefinition,section1Flags,decimalScaleFactor);
|
|
|
|
# ECC-1806
|
|
concept_nofail paramIdForConversion(zero, "paramIdForConversion.def", conceptsDir2, conceptsDir1) : long_type,read_only;
|
|
|
|
# ECC-1954
|
|
if (productDefinitionTemplateNumber == 0 && defined(perturbationNumber) && defined(numberOfForecastsInEnsemble) && numberOfForecastsInEnsemble > 0) {
|
|
alias productDefinitionTemplateNumber = one; # ensemble instant
|
|
}
|
|
if (productDefinitionTemplateNumber == 8 && defined(perturbationNumber) && defined(numberOfForecastsInEnsemble) && numberOfForecastsInEnsemble > 0) {
|
|
alias productDefinitionTemplateNumber = eleven; # ensemble interval
|
|
}
|