google-research / neuralgcm

Hybrid ML + physics model of the Earth's atmosphere
https://neuralgcm.readthedocs.io
Apache License 2.0
612 stars 65 forks source link

availability of surface variables? #108

Open GanZhang-GFD opened 1 month ago

GanZhang-GFD commented 1 month ago

The NeuralGCM paper contains some analytics that depend on the surface information. For example, the precipitable water calculation involves a vertical integral that needs surface pressure. The tracking of cyclones uses sea-level pressure and near-surface wind. However, the output of the PressureLevelModel does not contain surface variables. Additionally, surface temperature is also a variable that can enable many applications. How may users access these surface variables?

yaniyuval commented 1 month ago

You can output the surface pressure from the model by adding to the config SurfacePressureDiagnostics. Something like this should do the trick: new_model_config_str = '\n'.join([ ckpt['model_config_str'], 'StochasticPhysicsParameterizationStep.diagnostics_module = @SurfacePressureDiagnostics',]) ckpt['model_config_str'] = new_model_config_str

Regarding TC tracking: we give a full detail in the appendix of our paper how we used 2 different methods (using sea level pressure/vorticity at 850hPa + other criterion) to track cyclones (that yielded similar results) but non-used near-surface wind.

We currently do not have the concept of "surface variables" (except surface pressure which is a prognostic variable in our dycore) and we output variables only on pressure levels.

ShihengDuan commented 3 weeks ago

Surface temperature would be useful.

GanZhang-GFD commented 3 weeks ago

Thanks @yaniyuval! Sorry for not seeing your reply earlier:

You can output the surface pressure from the model by adding to the config SurfacePressureDiagnostics. Something like this should do the trick: new_model_config_str = '\n'.join([ ckpt['model_config_str'], 'StochasticPhysicsParameterizationStep.diagnostics_module = @SurfacePressureDiagnostics',]) ckpt['model_config_str'] = new_model_config_str

I did a quick test with the demo notebook and placed the suggested edits between the step of downloading ckpt and "model = neuralgcm.PressureLevelModel.from_checkpoint(ckpt)". But the model initialization ran into the following error:

ValueError: No configurable matching reference '@SurfacePressureDiagnostics'.

Did I miss any other steps when configuring the model?

Regarding TC tracking: we give a full detail in the appendix of our paper how we used 2 different methods (using sea level pressure/vorticity at 850hPa + other criterion) to track cyclones (that yielded similar results) but non-used near-surface wind.

SLP is the key variable. Thanks for the clarification about the tracking.

GanZhang-GFD commented 3 weeks ago

Surface temperature would be useful.

Agree. Before the functionality is implemented, it is relatively straightforward to approximate the surface temperature when surface pressure is available.

yaniyuval commented 2 weeks ago

@GanZhang-GFD , Try to pip install directly from the github page since the SurfacePressureDiagnostics was added only recently: pip install git+https://github.com/google-research/neuralgcm.git@main

GanZhang-GFD commented 2 weeks ago

@yaniyuval Thanks! I managed to finish the run with the newer model version.

1) The surface pressure appears to be in the final state object. The data array does not have the unit attribute. The values suggest some log operation was involved. Reversing log10 yields a reasonable pattern, but the lowest values are too small. Did I miss any steps?

plt.contourf(10**(final_state.diagnostics['surface_pressure'].T), cmap='Reds')
plt.colorbar()
Screenshot 2024-08-29 at 5 14 22 AM

2) Is there a smart way to access surface pressure at steps before the final state?

yaniyuval commented 2 weeks ago

@GanZhang-GFD, You should try to add the units to the surface pressure. Something like that should work:

new_inputs_to_units_mapping = {
  'u': 'meter / second',
  'v': 'meter / second',
  't': 'kelvin',
  'z': 'm**2 s**-2',
  'sim_time': 'dimensionless',
  'tracers': {'specific_humidity': 'dimensionless',
            'specific_cloud_liquid_water_content': 'dimensionless',
            'specific_cloud_ice_water_content': 'dimensionless',
             },
  'diagnostics': {'surface_pressure': 'kg / (meter s**2)'}
  }

new_model_config_str = '\n'.join([ ckpt['model_config_str'], 
                                  f'DimensionalLearnedPrimitiveToWeatherbenchDecoder.inputs_to_units_mapping = {new_inputs_to_units_mapping}',
                                   'DimensionalLearnedPrimitiveToWeatherbenchDecoder.diagnostics_module = @NodalModelDiagnosticsDecoder',
                                   'StochasticPhysicsParameterizationStep.diagnostics_module = @SurfacePressureDiagnostics',]) 
ckpt['model_config_str'] = new_model_config_str

Note that we know that some initial conditions have some drift in the global surface pressure (these are also the ones that will be more unstable) and in the next version we will publish we will likely have some fix to that.

GanZhang-GFD commented 2 weeks ago

@yaniyuval Thanks again! The code snippet didn't change the output values.

The test was with the reference code with pip neuralgcm.git@main. I also tested other variants of the pressure unit with the model config dictionary.

I am still interested in checking whether any existing mechanisms help access surface pressure at steps before the final state. Rolling out the model step by step is feasible but somewhat cumbersome.

GanZhang-GFD commented 2 weeks ago

Re drift in surface pressure: I also noticed drifts in other variables (e.g., temperature) of various magnitudes. Larger drifts usually come together with model instability. Smaller drifts appear to do relatively little harm when the simulations are not very long. Had some thoughts. I look forward to testing the next model version!

yaniyuval commented 2 weeks ago

@GanZhang-GFD , I slightly updated the snippet. When I use it I get the correct units. See a snapshot.

Screenshot 2024-08-29 at 8 13 00 PM
GanZhang-GFD commented 2 weeks ago

@yaniyuval The updated snippet worked! Thanks.

For the others watching this issue: The snippet helps put the surface pressure into the prediction object (along with other variables like u, v, etc.). Since the surface pressure is avialable at the same output steps, my other question was also resolved.

ShihengDuan commented 2 weeks ago

Regarding TC tracking: we give a full detail in the appendix of our paper how we used 2 different methods (using sea level pressure/vorticity at 850hPa + other criterion) to track cyclones (that yielded similar results) but non-used near-surface wind.

We currently do not have the concept of "surface variables" (except surface pressure which is a prognostic variable in our dycore) and we output variables only on pressure levels.

Hi @yaniyuval , Is sea level pressure an output or diagnostic variable? It seems not available in the standard output variables.