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 open data page and ECMWF open data user documentation. This wiki page provides example config for adding this import to your Delft-FEWS application. A 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 (basebuild 202402-50714143 or higher) and later.

Tips for testing:

  • Add the optional property <int key="s3MaxForecastHours" value="12"/> to the import module to shorten the length of forecast FEWS tries to import (and thus time required for testing). Remove this later to read the entire forecast length.
  • The second time you run the import for the same T0, the import will be much faster (as long as you don't restart FEWS), because FEWS caches the .gpx files in the temp folder.

Known issues/warnings

  1. The ECMWF open-data portal is currently (March 2026) limited to 500 simultaneous connections. This sometimes results in errors like "Too many requests". This appears to happen more often during specific times of day when many users are attempting to access the data.
  2. The first time importing a certain forecast (with a specific T0), you'll see several warnings like "WARN - Table ecmf/name line      scaledValueOfSecondWavelength = missing() ;"
    1. This is not a problem, you can ignore this warning.
  3. When importing accumulated parameters, the first timestep (00h) will always give a warning like "WARN - Exception while parsing NetCDF data from url cdms3://ecmwf-forecasts.s3.eu-central-1.amazonaws.com/ecmwf-forecasts?20250807/00z/ifs/0p25/oper/20250807000000-0h-oper-fc.grib2. This url will be skipped. Message was: Allocation size must be greater than zero".
    1. This is not a problem, you can ignore this warning.
  4. The units defined in the .grib2 files don't always seem to be correct (e.g. radiation flux says W/m2 in the .grib2, but it actually seems to be a 3-hour accumulated J/m2 value). 
  5. We have observed that certain parameters (e.g. Pressure_msl) take much longer than other parameters to import. This still needs to be investigated further.
  6. Some users get an error "Unable to execute HTTP request: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target Sun cert path builder unable to find valid certification path to requested target version" when running the import in Stand Alone.
    1. The solution for this is to create a truststore using the server URL using the "convert https server certificates to client.truststore" option in the F12 menu.

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 variables you would like to import. Note that some variables do not have an easy-to-identify variable name in the Grib2 file (with names like VAR#-#-###_FROM_). Use the parameter database (https://codes.ecmwf.int/grib/param-db/) to find parameters of interest (including the associated units). The Grib2_Parameter attribute in the Grib2 file corresponds to the discipline-parameterCategory-parameterNumber listed at the bottom of the parameter database page. For example: Parameter "Total precipitation" is described on this page: https://codes.ecmwf.int/grib/param-db/228. Scroll down, expand the ECMWF section, and combine the discipline (0), parameterCategory (1), and parameterNumber (193). The resulting Grib2_Parameter is 0-1-193. This code can also be found as an attribute in the Grib2 file. The variable with this attribute is called VAR0-1-193_FROM_98-0–1_surface_?_Hour_Accumulation.

How to map the variable depends on whether a variable has a z-level (*_height_above_ground) and whether a variable is accumulated or not (i.e. variables whose name changes in the grib2 file for each timestep).:

  • Variables without a z-levelcan be mapped directly, without defining locations. Use the main variable name listed in the grib2 file as external id.
  • Variables with a z-level (i.e. with *_height_above_ground) can be mapped to an internalLocation that has a z-level defined (see next paragraph) combined with externalLocation="0". Use the main variable name listed in the grib2 file as external id.
    • Alternatively, variables with a z-level, for which you only want to import one level, can also be imported onto a grid without a z-level. In this case, follow the instructions for variables without a z-level.
  • For variables whose name changes at each timestep, such as accumulated variables (*_Accumulation), use the "Grib2_Parameter_Name" from the grib2 file as external id. 
  • For variables whose name changes at each timestep, and which are missing the "Grib2_Parameter_Name" attribute (e.g. precipitation) or for which "Grib2_Parameter_Name" is not unique (e.g. Net long-wave radiation flux), the parameter to use in the idMap is a combination of several parts: (1) the "Grib2_Parameter," which is a code composed of: discipline-parameterCategory-parameterNumber, (2) the "Grib2_Level_Type" and (3) the "Grib2_Statistical_Process_Type". When there is no Grib2_Statistical_Process_Type (i.e. it says UnknownStatType-1), use a 4-digit code instead. The 5- or 4-digit code can be derived using information from the ECMWF parameter database (https://codes.ecmwf.int/grib/param-db/).
  • For isobaric parameters (*_isobaric), map the FEWS location to the layer index in the grib2 file. Isobaric idmapping should be done in a separate IdMap.

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 https://fewsdocs.deltares.nl/schemas/version1.0/idMap.xsd" version="1.1">
	
	<!--3D variables with a fixed grib2 variable 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 time-independent grib2 variable name-->
	<parameter internal="Pmsl.fcst" external="Pressure_msl"/>
	<parameter internal="Rain.rate.tot" external="Total_precipitation_rate_surface"/>

    <!--2D variables with a time-dependent grib2 variable name.-->
    <parameter internal="Rs.fcst" external="Downward short-wave radiation flux"/>

	<!--2D variables with a time-dependent grib2 variable name, (or) which are missing a unique Grib2_Parameter_Name attribute.-->
    <!--If the Grib2_Statistical_Process_Type is "UnknownStatisType--1" then use a 4-number code (remove the last number).-->
    <parameter internal="P.fcst" external="0-1-193-1-1"/>
	<parameter internal="Rs.fcst.net.surf" external="0-5-5-1-1"/>

</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 https://fewsdocs.deltares.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. 

  • The import settings depend on the type of parameter you're trying to import - five known examples are shown below.
  •  Properties:
    • Required: <bool key="anonymousS3Credentials" value="true"/>
    • Optional property to limit the length of the forecast to import (useful for initial testing!): <int key="s3MaxForecastHours" value="12"/>  (replace 12 with the length of forecast you want to import)
  • Timestep: Some of the ECMWF open data (e.g. IFS oper meteo data) uses a variable timestep - e.g. 3-hourly for the first 144 hours, followed by 6-hourly timesteps, but only for 2 of the 4 forecasts per day. To address, this, the example below includes setting the option interpolateSerie to true which automatically imports the data to 3-hourly timesteps upon import, avoiding the need for a processing module. This setting also works for accumulated data. If you import 6 days or less, then you don't need this setting.
  • Data streams: To import data every 6 hours, duplicate the <import> section in your import module file and replace "/oper/" with "/scda/" for meteo data. Similarly, for wave data, substitute /wave/ with /scwv/ to get the 06:00 and 18:00 forecasts. Alternatively, you can make single template with a property to populate the "oper" / "scda" part of the URL.
    • As of May 2026 the 00:00/12:00 and 06:00/18:00 forecasts use the same data stream in the serverUrl: "/oper/" for meteo data and "/wave/" for wave data. The forecasts still differ in length (144 hours for T0=06/18 and 360 hours for T0=00/12).

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>
		<timeSeriesSet>
			<moduleInstanceId>ImportEcmwfMeteo</moduleInstanceId>
			<valueType>grid</valueType>
			<parameterId>Rain.rate.tot</parameterId>
			<locationId>Ecmwf</locationId>
			<timeSeriesType>external forecasting</timeSeriesType>
			<timeStep unit="hour" multiplier="3"/>
			<readWriteMode>add originals</readWriteMode>
		</timeSeriesSet>
		<interpolateSerie parameterId="Pmsl.fcst" interpolate="true"/>
		<interpolateSerie parameterId="Rain.rate.tot" 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 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>

2D variables with a name that changes per timestep (e.g. accumulated parameters), but that are missing the Grib2_Parameter_Name attribute

This option requires setting the variable_identification_method property to grib2_parameter_code.

<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_code"/>
		</properties>
		<timeSeriesSet>
			<moduleInstanceId>ImportEcmwfMeteo</moduleInstanceId>
			<valueType>grid</valueType>
			<parameterId>P.fcst</parameterId>
			<locationId>Ecmwf</locationId>
			<timeSeriesType>external forecasting</timeSeriesType>
			<timeStep unit="hour" multiplier="3"/>
			<readWriteMode>add originals</readWriteMode>
		</timeSeriesSet>
		<timeSeriesSet>
			<moduleInstanceId>ImportEcmwfMeteo</moduleInstanceId>
			<valueType>grid</valueType>
			<parameterId>Rs.fcst.net.surf</parameterId>
			<locationId>Ecmwf</locationId>
			<timeSeriesType>external forecasting</timeSeriesType>
			<timeStep unit="hour" multiplier="3"/>
			<readWriteMode>add originals</readWriteMode>
		</timeSeriesSet>
        <externUnit parameterId="P.fcst" unit="m" cumulativeSum="true"/>
		<externUnit parameterId="Rs.fcst.net.surf" unit="Jm-2/3hr" cumulativeSum="true"/>
        <interpolateSerie parameterId="P.fcst" interpolate="true"/>
        <interpolateSerie parameterId="Rs.fcst.net.surf" 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>



  • No labels