Introduction

ECMWF makes real-time forecast data from the IFS and AIFS models available to the public free of charge. More information about this dataset is available on the ECMWF website. This page provides example config for adding this import to your Delft-FEWS application. An up-to-date configuration example of the import is also available in the FEWS-Conform repository

This import uses importType NETCDF-CF_GRID_S3

This import is available Delft-FEWS versions 2024.02 and later.

The second time you run the import for the same T0, the import will be much faster, because FEWS caches the .gpx files in the temp folder. This makes the import easier to test/debug.

Make the IdMap

Start by manually downloading an example .grib2 file from the ECMWF data browser and opening it in a NetCDF viewer (e.g. Panoply). Identify the parameters you would like to import. How to map the parameters depends on whether a parameter has a z-level (*_height_above_ground) and whether a parameter is accumulated or not (i.e. variables whose name changes in the grib2 file for each timestep).:

Note: It seems like the units defined in the .grib2 files are not always correct.

Example IdMap for 2D parameters, 3D parameters using a z-level, and parameters whose names change at each timestep

<idMap xmlns="http://www.wldelft.nl/fews" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.wldelft.nl/fews http://fews.wldelft.nl/schemas/version1.0/idMap.xsd" version="1.1">
	
	<!--3D variables with a fixed grib2 parameter name and a z-level ("*_height_above_ground") should be linked to a location with that height.-->
	<map internalParameter="WSu.fcst" internalLocation="Ecmwf.10m" externalParameter="u-component_of_wind_height_above_ground" externalLocation="0"/>
	<map internalParameter="WSv.fcst" internalLocation="Ecmwf.10m" externalParameter="v-component_of_wind_height_above_ground" externalLocation="0"/>
	<map internalParameter="T.fcst" internalLocation="Ecmwf.2m" externalParameter="Temperature_height_above_ground" externalLocation="0"/>

	<!--2D variables with a fixed grib2 parameter name only need to be linked to the internal parameter-->
	<parameter internal="Pmsl.fcst" external="Pressure_msl"/>

	<!--2D variables with a varying grib2 parameter name only need to be linked to the internal parameter. Use the "Grib2_Parameter_name" as external.-->
    <parameter internal="Rs.fcst" external="Net short wave radiation flux"/>
</idMap>

Example IdMap for 3D parameters using isobaric levels

See next section for how locationSet Ecmwf.Ecmwf_levels is configured.

<idMap xmlns="http://www.wldelft.nl/fews" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.wldelft.nl/fews http://fews.wldelft.nl/schemas/version1.0/idMap.xsd" version="1.1">
    
	<!-- 3D variables with a fixed grib2 parameter name and an isobaric level ("*_isobaric") should be linked to a location with that height.-->
	<parameter internal="T.air.3D" external="Temperature_isobaric"/>
	<parameter internal="Wind.u.3D" external="u-component_of_wind_isobaric"/>
	<parameter internal="Wind.v.3D" external="v-component_of_wind_isobaric"/>
	<parameter internal="Humidity.rel.3D" external="Relative_humidity_isobaric"/>
	<parameter internal="Geopot.height.3D" external="Geopotential_height_isobaric"/>	
	
	<locationIdFunction internalLocationSet="Ecmwf.Ecmwf_levels" externalLocationFunction="@LAYER_INDEX@"/>
</idMap>

Define the locations

Next, define the locationId for the grid(s). You'll need to configure a separate locationId for each height above the ground (and one for variables that don't have a height specified). For *_height_above_ground variables, you'll need to identify the height coordinate defined for the variable, and then check the associated coordinate variable to identify the height. Configure this height in Locations.xml as shown below.

Example locationIds for 2D and 3D data (using z-levels)

<location id="Ecmwf" name="Grid for ECMWF">
		<x>0</x>
		<y>0</y>
	</location>
	<location id="Ecmwf.2m" name="Grid for ECMWF (2 m above ground)">
		<x>0</x>
		<y>0</y>
		<z>2</z>
	</location>
	<location id="Ecmwf.10m" name="Grid for ECMWF (10 m above ground)">
		<x>0</x>
		<y>0</y>
		<z>10</z>
	</location>

Example locationSet for 3D data (using isobaric levels)

	<locationSet id="Ecmwf.Ecmwf_levels">
		<csvFile>
			<file>ECMWF_layers.csv</file>
			<geoDatum>WGS 1984</geoDatum>
			<id>ECMWF.%LEVEL_MB%mb</id>
			<name>ECMWF (%LEVEL_MB% mb)</name>
			<parentLocationId>Ecmwf</parentLocationId>
			<x>0</x>
			<y>0</y>
			<z>%LEVEL_MB%</z>
			<attribute id="LAYER_INDEX">
				<description>Level ID (0-12), out of 13 layers available in ECMWF</description>
				<text>%LAYER_INDEX%</text>
			</attribute>
			<attribute id="LEVEL_MB">
				<description>Pressure associated with level (in mb)</description>
				<text>%LEVEL_MB%</text>
			</attribute>
		</csvFile>
	</locationSet>

Where ECMWF_layers.csv looks like this (in this example we only import 5 of the 13 layers available in ECMWF):

LAYER_INDEX,LEVEL_MB
5,300
7,500
8,600
9,700
10,850

Define the grids

Next, define the grid you would like to import - see the example below. The ECMWF data are available for the entire globe, but with the NETCDF-CF_GRID_S3 you can directly import a smaller section of the grid for your area of interest.

<regular locationId="Ecmwf">
		<rows>136</rows>
		<columns>168</columns>
		<geoDatum>WGS 1984</geoDatum>
		<firstCellCenter>
			<x>112</x>
			<y>-10</y>
		</firstCellCenter>
		<xCellSize>0.25</xCellSize>
		<yCellSize>0.25</yCellSize>
	</regular>
	<regular locationId="Ecmwf.2m">
		<rows>136</rows>
		<columns>168</columns>
		<geoDatum>WGS 1984</geoDatum>
		<firstCellCenter>
			<x>112</x>
			<y>-10</y>
		</firstCellCenter>
		<xCellSize>0.25</xCellSize>
		<yCellSize>0.25</yCellSize>
	</regular>
	<regular locationId="Ecmwf.10m">
		<rows>136</rows>
		<columns>168</columns>
		<geoDatum>WGS 1984</geoDatum>
		<firstCellCenter>
			<x>112</x>
			<y>-10</y>
		</firstCellCenter>
		<xCellSize>0.25</xCellSize>
		<yCellSize>0.25</yCellSize>
	</regular>

Configure the import module

Now you can configure your import module. 

Variables without a z-level (i.e. without *_height_above_ground in the variable name)

<import>
		<general>
			<importType>NETCDF-CF_GRID_S3</importType>
			<serverUrl>https://ecmwf-forecasts.s3.eu-central-1.amazonaws.com/ecmwf-forecasts/%TIME_ZERO(yyyyMMdd)%/%TIME_ZERO(HH)%z/ifs/0p25/oper/</serverUrl>
			<connectionTimeOutMillis>1200000</connectionTimeOutMillis>
			<relativeViewPeriod unit="day" start="0" end="10"/>
			<idMapId>IdMapFromEcmwf</idMapId>
			<unitConversionsId>ImportUnitConversions</unitConversionsId>
			<importTimeZone>
				<timeZoneName>GMT</timeZoneName>
			</importTimeZone>
			<dataFeedId>Ecmwf.meteo</dataFeedId>
		</general>
		<properties>
			<bool key="anonymousS3Credentials" value="true"/>
		</properties>
		<timeSeriesSet>
			<moduleInstanceId>ImportEcmwfMeteo</moduleInstanceId>
			<valueType>grid</valueType>
			<parameterId>Pmsl.fcst</parameterId>
			<locationId>Ecmwf</locationId>
			<timeSeriesType>external forecasting</timeSeriesType>
			<timeStep unit="hour" multiplier="3"/>
			<readWriteMode>add originals</readWriteMode>
		</timeSeriesSet>
		<interpolateSerie parameterId="Pmsl.fcst" interpolate="true"/>
	</import>

3D variables with a z-level (i.e. with *_height_above_ground)

Importing these variables requires setting layerIndexAsQualifierId to true (and using the locationId with a z-level defined, see above).

<import>
		<general>
			<importType>NETCDF-CF_GRID_S3</importType>
			<serverUrl>https://ecmwf-forecasts.s3.eu-central-1.amazonaws.com/ecmwf-forecasts/%TIME_ZERO(yyyyMMdd)%/%TIME_ZERO(HH)%z/ifs/0p25/oper/</serverUrl>
			<connectionTimeOutMillis>1200000</connectionTimeOutMillis>
			<relativeViewPeriod unit="day" start="0" end="10"/>
			<idMapId>IdMapFromEcmwf</idMapId>
			<unitConversionsId>ImportUnitConversions</unitConversionsId>
			<importTimeZone>
				<timeZoneName>GMT</timeZoneName>
			</importTimeZone>
			<dataFeedId>Ecmwf.meteo</dataFeedId>
		</general>
		<properties>
			<bool key="anonymousS3Credentials" value="true"/>
			<bool key="layerIndexAsQualifierId" value="true"/>
		</properties>
		<timeSeriesSet>
			<moduleInstanceId>ImportEcmwfMeteo</moduleInstanceId>
			<valueType>grid</valueType>
			<parameterId>T.fcst</parameterId>
			<locationId>Ecmwf.2m</locationId>
			<timeSeriesType>external forecasting</timeSeriesType>
			<timeStep unit="hour" multiplier="3"/>
			<readWriteMode>add originals</readWriteMode>
		</timeSeriesSet>
		<timeSeriesSet>
			<moduleInstanceId>ImportEcmwfMeteo</moduleInstanceId>
			<valueType>grid</valueType>
			<parameterId>WSu.fcst</parameterId>
			<locationId>Ecmwf.10m</locationId>
			<timeSeriesType>external forecasting</timeSeriesType>
			<timeStep unit="hour" multiplier="3"/>
			<readWriteMode>add originals</readWriteMode>
		</timeSeriesSet>
		<timeSeriesSet>
			<moduleInstanceId>ImportEcmwfMeteo</moduleInstanceId>
			<valueType>grid</valueType>
			<parameterId>WSv.fcst</parameterId>
			<locationId>Ecmwf.10m</locationId>
			<timeSeriesType>external forecasting</timeSeriesType>
			<timeStep unit="hour" multiplier="3"/>
			<readWriteMode>add originals</readWriteMode>
		</timeSeriesSet>
		<interpolateSerie parameterId="T.fcst" interpolate="true"/>
		<interpolateSerie parameterId="WSu.fcst" interpolate="true"/>
		<interpolateSerie parameterId="WSv.fcst" interpolate="true"/>
	</import>

2D variables with a grib2 parameter name that changes per timestep (e.g. accumulated parameters)

This option requires setting the variable_identification_method property to grib2_parameter_name.

<import>
		<general>
			<importType>NETCDF-CF_GRID_S3</importType>
			<serverUrl>https://ecmwf-forecasts.s3.eu-central-1.amazonaws.com/ecmwf-forecasts/%TIME_ZERO(yyyyMMdd)%/%TIME_ZERO(HH)%z/ifs/0p25/oper/</serverUrl>
			<connectionTimeOutMillis>1200000</connectionTimeOutMillis>
			<relativeViewPeriod unit="day" start="0" end="10"/>
			<idMapId>IdMapFromEcmwf</idMapId>
			<unitConversionsId>ImportUnitConversions</unitConversionsId>
			<importTimeZone>
				<timeZoneName>GMT</timeZoneName>
			</importTimeZone>
			<dataFeedId>Ecmwf.meteo</dataFeedId>
		</general>
		<properties>
			<bool key="anonymousS3Credentials" value="true"/>
			<string key="variable_identification_method" value="grib2_parameter_name"/>
		</properties>
		<timeSeriesSet>
			<moduleInstanceId>ImportEcmwfMeteo</moduleInstanceId>
			<valueType>grid</valueType>
			<parameterId>Rs.fcst</parameterId>
			<locationId>Ecmwf</locationId>
			<timeSeriesType>external forecasting</timeSeriesType>
			<timeStep unit="hour" multiplier="3"/>
			<readWriteMode>add originals</readWriteMode>
		</timeSeriesSet>
		<externUnit parameterId="Rs.fcst" unit="Jm-2/3hr" cumulativeSum="true"/>
        <interpolateSerie parameterId="Rs.fcst" interpolate="true"/>
	</import>

3D variables with an isobaric level (i.e. with *_isobaric)

This option requires setting the laterIndexAsLocationId property to true.

<import>
		<general>
			<importType>NETCDF-CF_GRID_S3</importType>
			<serverUrl>https://ecmwf-forecasts.s3.eu-central-1.amazonaws.com/ecmwf-forecasts/%TIME_ZERO(yyyyMMdd)%/%TIME_ZERO(HH)%z/ifs/0p25/oper/</serverUrl>
			<connectionTimeOutMillis>1200000</connectionTimeOutMillis>
			<relativeViewPeriod unit="day" start="0" end="10"/>
			<idMapId>IdMapFromEcmwf</idMapId>
			<unitConversionsId>ImportUnitConversions</unitConversionsId>
			<importTimeZone>
				<timeZoneName>GMT</timeZoneName>
			</importTimeZone>
			<dataFeedId>Ecmwf.meteo</dataFeedId>
		</general>
		<properties>
			<bool key="anonymousS3Credentials" value="true"/>
            <bool key="layerIndexAsLocationId" value="true"/>
        </properties>
		<timeSeriesSet>
			<moduleInstanceId>ImportEcmwfMeteo</moduleInstanceId>
			<valueType>grid</valueType>
			<parameterId>T.air.3D</parameterId>
			<locationId>Ecmwf.Ecmwf_levels</locationId>
			<timeSeriesType>external forecasting</timeSeriesType>
			<timeStep unit="hour" multiplier="3"/>
			<readWriteMode>add originals</readWriteMode>
		</timeSeriesSet>
        <interpolateSerie parameterId="T.air.3D" interpolate="true"/>
	</import>