Change in soil variables from ECMWF Cycle 49r1

Diff:
--- a/rd_grib2.F
+++ b/rd_grib2.F
@@
-      integer :: glevel1, glevel2
+      real :: glevel1, glevel2
@@
-!              if ( gfld%ipdtmpl(10) .eq. 106 ) then
-              if ( gfld%ipdtmpl(10) .eq. 106 ) then
+!              if ( gfld%ipdtmpl(10) .eq. 106 ) then
+              if (( gfld%ipdtmpl(10) .eq. 106 ) .or.
+     &           ( gfld%ipdtmpl(10) .eq. 151 )) then              !! Added by Prof. Mariusz Figurski, 20250110
                 if ( ( gfld%ipdtmpl(14) .EQ. -1*(2**07-1) ) .AND.
@@
-                   glevel1 = 100. * gfld%ipdtmpl(12)*
-     &                         (10.**(-1.*gfld%ipdtmpl(11)))
-                   glevel2 = 100. * gfld%ipdtmpl(15)*
-     &                         (10.**(-1.*gfld%ipdtmpl(14)))
+                   glevel1 = 100. * gfld%ipdtmpl(12)*
+     &                         (10.**(-1.*gfld%ipdtmpl(11)))
+                   glevel2 = 100. * gfld%ipdtmpl(15)*
+     &                         (10.**(-1.*gfld%ipdtmpl(14)))
+!The following if-block accounts for the 2024 changes to IFS soil fields. They use a local table. 10.01.2024
+!! Added by Prof. Mariusz Figurski, 20250110
+                  if (icenter .eq. 98 .and.
+     &                gfld%discipline .eq. 2 .and.
+     &                (gfld%ipdtmpl(1) .eq. 3 .or.
+     &                gfld%ipdtmpl(1) .eq. 0) .and.
+     &                gfld%ipdtmpl(10).eq. 151) then
+                      glevel1 = gfld%ipdtmpl(12)
+                      glevel2 = gfld%ipdtmpl(15)
+                      if ( gfld%ipdtmpl(12) .eq. 0) then
+                          glevel1 = 0
+                      elseif ( gfld%ipdtmpl(12) .eq. 1) then
+                          glevel1 = 7
+                      elseif ( gfld%ipdtmpl(12) .eq. 2) then
+                          glevel1 = 28
+                      elseif ( gfld%ipdtmpl(12) .eq. 3) then
+                          glevel1 = 100
+                      elseif ( gfld%ipdtmpl(12) .eq. 4) then
+                          glevel1 = 289
+                      endif
+
+                      if ( gfld%ipdtmpl(15) .eq. 0) then
+                          glevel2 = 0
+                      elseif ( gfld%ipdtmpl(15) .eq. 1) then
+                          glevel2 = 7
+                      elseif ( gfld%ipdtmpl(15) .eq. 2) then
+                          glevel2 = 28
+                      elseif ( gfld%ipdtmpl(15) .eq. 3) then
+                          glevel2 = 100
+                      elseif ( gfld%ipdtmpl(15) .eq. 4) then
+                          glevel2 = 289
+                      endif
+
+                      if ( glevel1 .eq. 100. .and.
+     &                     glevel2 .lt. -1.e+9 ) then
+                        glevel2 = 255.
+                      endif
+                  endif
                 end if
-                TMP8LOOP: do j = 1, maxvar
-                  if ((g2code(4,j) .eq. 106) .and.
-     &               (gfld%ipdtmpl(2) .eq. g2code(3,j)) .and.
+                TMP8LOOP: do j = 1, maxvar
+                  if (((g2code(4,j) .eq. 106) .or.
+     &               (g2code(4,j) .eq. 151)) .and.              !! NEW
+     &               (gfld%ipdtmpl(1) .eq. g2code(2,j)) .and.   !! NEW
+     &               (gfld%ipdtmpl(2) .eq. g2code(3,j)) .and.
      &               (glevel1 .eq. level1(j)) .and.
      &               ((glevel2 .eq. level2(j)) .or.
      &                                   (level2(j) .le. -88))) then
                     my_field = namvar(j)
                     exit TMP8LOOP
                   endif
                 enddo TMP8LOOP
@@
-              elseif(gfld%ipdtmpl(10).eq.106.or.
-     &               gfld%ipdtmpl(10).eq.1) then
+              elseif(gfld%ipdtmpl(10).eq.106 .or.
+     &               gfld%ipdtmpl(10).eq.151 .or.               !! NEW
+     &               gfld%ipdtmpl(10).eq.1) then
                  ! Misc near ground/surface levels
                  level=200100.


Suggestions (to make this change safer & future-proof)

Guard equality checks on floating depths
Now that glevel1/glevel2 are real, use tolerance or rounding before comparing to Vtable integers to avoid rare mismatches:
Code:
! replace exact equality with rounded compare
if ( nint(glevel1) == level1(j) .and.
     ( nint(glevel2) == level2(j) .or. level2(j) <= -88 ) ) then


or

Code:
real, parameter :: EPSC = 0.5
if ( abs(glevel1 - level1(j)) < EPSC .and.
     ( abs(glevel2 - level2(j)) < EPSC .or. level2(j) <= -88 ) ) then


Isolate the IFS (center=98) soil-layer mapping
Encapsulate the index→depth mapping in a tiny helper for readability and reuse:
Code:
integer function ifs_soil_cm(idx)
  integer, intent(in) :: idx
  integer, dimension(0:4) :: lut = (/0,7,28,100,289/)
  if (idx < 0 .or. idx > 4) then
     ifs_soil_cm = -2147483647  ! missing
  else
     ifs_soil_cm = lut(idx)
  end if
end function


Then:

Code:
glevel1 = ifs_soil_cm(gfld%ipdtmpl(12))
glevel2 = ifs_soil_cm(gfld%ipdtmpl(15))


Add a debug breadcrumb when 151-path is used
Behind a higher debug_level, log one line so users can verify the new logic is triggered:
Code:
if ( debug_level > 10 ) call mprintf(.true.,DEBUG,
 & "ECMWF soil(151) mapped: [%f,%f] cm", newline=.true., f1=glevel1, f2=glevel2)


Keep the category check consistent in Vtables
You added a match on ipdtmpl(1) (category). Ensure Vtables specify category for these soil entries; otherwise they won’t match. If you need backward-compatibility, guard it:
Code:
logical :: cat_ok
cat_ok = (g2code(2,j) .eq. -99) .or. (gfld%ipdtmpl(1) .eq. g2code(2,j))


Document the new level type
In your developer notes, record that level type 151 is treated like 106 for storage (level=200100. bucket) and that ECMWF local soil-layer indices are mapped to cm depths (0,7,28,100,289).


@figurski what are you thoughts on this above?
@figurski did you have a chance to look at this?
 
William,
Unfortunately, I only noticed the question addressed to me today. I'll get around to it in May and need to double-check if it works for me. When I was working on solving this problem, I ran tests and everything worked. I'll double-check.
Mariusz
Can you also check if it works with the new cycle to? @figurski
 
@Ming Chen I wrote about everything, but forgot about the data. I downloaded the data from the ECMWF open repository.


example:
....

IFS operational model data in the ECMWF open data repository are only available for the last 4 days.
I downloaded the operational grib2 files from the IFS model. Then you have to decompress them, e.g. with the grib_set program, but someone wrote about that earlier. I did the tests for a few days. I downloaded the data for 4 days of the forecast. As usual, I performed the simulations with an interval of every 180 minutes.

There was a mistake in the description I posted above. The last layer in the IFS soil model has a value of 289 centimeters. I mistakenly entered 255 centimeters in the description.
I hope this explains the data problem. I ran the model on several forecast dates and everything seems to work fine.
I hope that users of the WRF model will benefit from my solution.

If you have any further questions, I will be happy to answer them as soon as I know them.

Mariusz
Hi Mariusz ,
I used the ECMWF IFS Vtable and was able to successfully run ungrib.exe and metgrid.exe and generate the met_em files. However, I noticed that:

  • NUM_METGRID_SOIL_LEVELS = 0
  • num_metgrid_levels = 14
In general, WRF usually expects at least 4 soil levels for proper land surface model performance and better soil-temperature/moisture evolution during forecasts.
Since the IFS input was not providing soil levels correctly through my current workflow, I tried an alternative approach:

  1. I used ECMWF IFS atmospheric variables with Vtable.ECMWF
  2. Ran ungrib.exe and generated the atmospheric FILE:*
  3. Then I downloaded GFS data for the same simulation period
  4. Created a modified Vtable.GFS.soil containing only soil variables (removed atmospheric variables)
  5. Ran ungrib.exe again for the GFS soil fields and generated separate soil FILE:*
  6. Used both atmospheric (IFS) and soil (GFS) intermediate files together in metgrid.exe
After this, the generated met_em files showed:

  • NUM_METGRID_SOIL_LEVELS = 4
  • num_metgrid_levels = 14
The WRF model ran successfully, and surprisingly the results looked reasonable. I compared 10-day simulations against METAR observations for T2, RH, and wind speed, and the agreement appears quite good.
My main doubt is regarding the scientific validity of this approach:
Can we scientifically use:

  • ECMWF IFS atmospheric fields
  • together with NOAA GFS soil fields
for WRF initialization?
The reason I am asking is because the soil layer structures are different between GFS and ECMWF.
GFS soil layers:

  • 0–10 cm
  • 10–40 cm
  • 40–100 cm
  • 100–200 cm
whereas ECMWF IFS soil layers are:

  • 0–7 cm
  • 7–28 cm
  • 28–100 cm
  • 100–289 cm
So the soil depth definitions and layer thicknesses are clearly different.
Despite this mismatch, the model is still running stably and producing reasonable results, which surprised me.
Could you please guide me on:

  1. Whether this hybrid combination is scientifically acceptable
  2. Whether WRF internally interpolates/adapts these soil layers
  3. Possible risks or inconsistencies of mixing IFS atmospheric fields with GFS land/soil fields
  4. The best scientific approach moving forward for operational forecasts or research-quality simulations
I would really appreciate your guidance on whether this method is acceptable or if there is a better recommended workflow for using ECMWF IFS with WRF.
like which METGRID.TBL.ARW.txt is the best and which is Vtable is best both atmosphreic and Soil parametsrs side

1779779212252.png
1779779196800.png
 

Attachments

  • 1779779132993.png
    1779779132993.png
    104.9 KB · Views: 1
Hi Mariusz ,
I used the ECMWF IFS Vtable and was able to successfully run ungrib.exe and metgrid.exe and generate the met_em files. However, I noticed that:

  • NUM_METGRID_SOIL_LEVELS = 0
  • num_metgrid_levels = 14
In general, WRF usually expects at least 4 soil levels for proper land surface model performance and better soil-temperature/moisture evolution during forecasts.
Since the IFS input was not providing soil levels correctly through my current workflow, I tried an alternative approach:

1. Is this hybrid combination scientifically acceptable?

The answer is. It depends on the research objective, but it is not a recommended practice (best practice).

Technically, the WPS system is designed for this the metgrid.exe program will easily merge intermediate files coming from different sources (e.g., atmosphere from IFS, soil from GFS). The reason the results look so good on the charts is that parameters such as 2m temperature (T2) or 10m wind are largely driven by processes in the lower troposphere (advection and radiation), which are controlled by the high-quality atmospheric fields from ECMWF. The soil has a slower, buffering effect here.

Physically, however, this approach has flaws. The GFS soil fields (temperature, moisture) have reached their state under the influence of the long-term atmospheric forcing of the GFS model (its precipitation, solar radiation). Replacing the GFS atmosphere with the IFS atmosphere means that at the start of the simulation (T=0), there is an unphysical imbalance between the atmosphere and the heat and moisture fluxes from the surfach.

2. Does WRF internally interpolate these soil layers?

Yes, and it does so automatically during the execution of the real.exe program.

Differences in layer depths (GFS: 10, 40, 100, 200 cm vs. ECMWF: 7, 28, 100, 289 cm) are not an obstacle for WRF. The Land Surface Model (LSM) in WRF, e.g., the popular Noah LSM, requires a specific vertical structure (most often layers with thicknesses of 10, 30, 60, and 100 cm).

The real.exe program performs vertical interpolation of profiles from the input data (regardless of whether they are from GFS or ECMWF) and maps them to the levels required by the LSM model configured in the namelist.input. That is why the model ran stably.

3. Possible risks and inconsistencies

  • Initialization shock (Model Spin-up). Due to the aforementioned imbalance, the model will spend the first 12–24 hours trying to adjust the soil parameters to the new atmospheric conditions. Sensible and latent heat fluxes may take on unnatural values during this time.
  • Land-Sea Mask Mismatch. GFS and ECMWF have different native resolutions and distinct coastlines. Using two different sources creates risks along the coasts there may be grid points that ECMWF considers land (requiring soil data), but GFS considers sea (lacking soil data). WRF then has to "patch" these points using nearest-neighbor methods, which often introduces errors.

4. The best scientific approach (Solving the problem)

Instead of "patching" the problem with GFS data.
This issue does not stem from WRF errors, but rather from the fact that the GRIB files downloaded from ECMWF either did not contain soil layers, or the Vtable used was unable to decode them.

I described the solution to the problem for the IFS GRIB2 model a few months ago. Everything is provided there, including the Vtable and the changes to the ungrib code. It works without any issues for me. Let me know if you managed to implement these changes.


Best regards
Mariusz
 
Back
Top