NCAR / ccpp-framework

Common Community Physics Package (CCPP)
http://www.dtcenter.org/community-code/common-community-physics-package-ccpp/
Other
26 stars 64 forks source link

Unit conversion bug when variable is used by two different schemes (with different units) #594

Open peverwhee opened 1 day ago

peverwhee commented 1 day ago

Description

Scenario 1

If a variable is used in two different schemes and:

  1. The first scheme has the same units as the host variable.
  2. The second scheme has different units than the host variable.

It produces this error:

Invalid new variable, <variable>, incompatible  between <variable>,

Scenario 2

On the flip side, if:

  1. The first scheme has different units than the host variable.
  2. The second scheme has the same units as the host variable.

The framework will convert the variable to pass into the first scheme, but not convert it back for the second scheme (thus using the wrong units)

Steps to Reproduce

  1. Modify ps in cld_ice.meta in the advection test to have units of "hPa", run the tests and observe the error.
  2. Remove your modification to cld_ice.meta. Modify ps in cld_liq.meta in the advection test and inspect the generated code to see the wrong units passed into cld_liq

Output

Generated code for scenario number 2 (where the wrong units are used):

! Compute reverse (pre-scheme) transforms
ps_local(:) = 1.0E-2_kind_phys*ps(:)
! Call scheme
call cld_liq_run(ncol=ncol, timestep=timestep, tcld=tcld, temp=temp, qv=qv,              &
              ps=ps_local, cld_liq_array=cld_liq_array, errmsg=errmsg, errflg=errflg)
...
! Call scheme
call cld_ice_run(ncol=ncol, timestep=timestep, temp=temp, qv=qv, ps=ps_local,            &
              cld_ice_array=cld_ice_array, errmsg=errmsg, errflg=errflg)
climbfuji commented 1 day ago

is this also a problem with prebuild or just with capgen?

peverwhee commented 1 day ago

@climbfuji good question!

I ran a brief test with prebuild and it looks like it works as expected for Scenario 1, but Scenario 2 results in an incorrect conversion before the second scheme. For example, if you have variable unit_conversion_var with units of km in the host model and then Scheme A has units for m (different from host) for that variable, while Scheme B has units of km (same as host) for that variable, you get code that looks like:

tmpvar_1 = 1.0E+3_kind_phys*unit_conversion_var(one:nx)
call schemeA(errmsg,errflg,tmpvar_1)
unit_conversion_var(one:nx) = 1.0E-3_kind_phys*tmpvar_1
...
tmpvar_1 = 1.0E+3_kind_phys*unit_conversion_var(one:nx)
call schemeB(errmsg,errflg,tmpvar_1)
unit_conversion_var(one:nx) = 1.0E-3_kind_phys*tmpvar_1

When you should get code that looks like:

tmpvar_1 = 1.0E+3_kind_phys*unit_conversion_var(one:nx)
call schemeA(errmsg,errflg,tmpvar_1)
unit_conversion_var(one:nx) = 1.0E-3_kind_phys*tmpvar_1
...
call schemeB(errmsg,errflg,unit_conversion_var)

NOTE: I modified the optional arguments prebuild test for this, so the fact that the conversions are being done on optional arguments may be part of the problem!

climbfuji commented 1 day ago

Thanks for testing. This is not what I expected (from my vague memory of how this is implemented)!