Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fv3core uses the MetricTerms #16

Merged
merged 22 commits into from
Nov 22, 2021
Merged

Conversation

rheacangeo
Copy link
Contributor

@rheacangeo rheacangeo commented Nov 16, 2021

Purpose

Changes moved over from the feature/use_grid branch of fv3core -- ai2cm/fv3core#652
The fv3core/grid section now provided the functionality to create MetricTerms, the grid variables we need to run the model without reading them from serialized data on disk. When we want to test performance of new or larger datasets, it will be helpful to be able to initialize the grid without needing to first run the Fortran model to create the data.
This PR updates fv3core to make use of the MetricTerms class.

  • Create a GridData instance from a MetricTerms instance
  • Add a --compute_grid option to the regression tests to run the tests using a generated grid rather than serialized data from the Grid-Info savepoint. Currently this can only be applied to Parallel tests, and is only enabled for FVDynamics. Tracer2D1L fails (metric diff of 1e-9) because the computed GridData does not match the Fortran version bit-for-bit.
  • Added running FVDynamics both with and without --compute_grid to the parallel_regression jenkins tests
  • use ak, bk, ptop and ks from the grid_data rather than from serialized input data
  • update the performance scripts and wrapper runfiles to call FVDynamics with its updated API and not use the Grid-Info savepoint
  • Moved grid constants as attributes to MetricTerms to avoid circular imports
  • removed all instances of "spec.grid." to enable running the performance script without the Grid-Info savepoint. Added TODOs to revisit and maybe compute those derived grid terms closer to where they are used
  • added lon/lat to MetricTerms. Although perhaps redundant, I imagine these would be common variables someone would want from this class. Use them in a2b_ord4 and it makes that code more readable. Updated the fortran changelog to reflect this.
  • add computations of the coriolis parameters f0 and fC to the model (part of the 'fortran 'gridstruct' that gets computed in state initialization rather than in the grid. here computing them in the init of the C_SW and D_SW instances that use them.

@rheacangeo rheacangeo marked this pull request as draft November 16, 2021 08:59
@rheacangeo rheacangeo requested a review from oelbert November 16, 2021 09:00
@rheacangeo
Copy link
Contributor Author

launch jenkins

Comment on lines -2123 to +2127
min_area = self._np.min(self.area.view[:])
max_area = self._np.max(self.area.view[:])
min_area_c = self._np.min(self.area_c.view[:])
max_area_c = self._np.max(self.area_c.view[:])

min_area = self._np.min(self.area.storage[3:-4, 3:-4])[()]
max_area = self._np.max(self.area.storage[3:-4, 3:-4])[()]
min_area_c = self._np.min(self.area_c.storage[3:-4, 3:-4])[()]
max_area_c = self._np.max(self.area_c.storage[3:-4, 3:-4])[()]
Copy link
Contributor Author

@rheacangeo rheacangeo Nov 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise cupy.min on a quantity view returns a cupy array, while numpy returns a scalar as expected.

@@ -601,119 +601,6 @@ def calculate_grid_a(z11, z12, z21, z22, sin_sg5):
return a11, a12, a21, a22


def edge_factors(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this calculation is moved to a2b_ord4

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Contributor Author

@rheacangeo rheacangeo Nov 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically did this due to a comment in a2b that the edge factors should be computed locally in that module because it is the only place it is used. Since I was deleting the trigger to do this work (calling spec.grid), I thought I should do the work. After our discussion, have reverted this change, and a future PR may put them in their own class structure to make it easier to read.

@rheacangeo
Copy link
Contributor Author

launch jenkins

1 similar comment
@rheacangeo
Copy link
Contributor Author

launch jenkins

@rheacangeo
Copy link
Contributor Author

rheacangeo commented Nov 16, 2021

Current failures may not be specific to this branch, others have reported similar in other branches. This is specific to the gtc backends. This is the error:
fv3core/fv3core/.gt_cache/py38_1013/gtcgtcpu_ifirst/fv3core/utils/stencil/copy_stencil/m_copy_stencil__gtcgtcpu_ifirst_0224270a4e_pyext.cpython-38-x86_64-linux-gnu.so: cannot open shared object file: No such file or directory

@rheacangeo
Copy link
Contributor Author

launch jenkins

@rheacangeo rheacangeo marked this pull request as ready for review November 17, 2021 00:46
Copy link
Contributor

@oelbert oelbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks really good! I think there's a lot in here that maybe should be split into separate PRs, like moving the edge factors into a2b_ord4 or putting the grid constants back into global_constants (not sure if either of those are necessary, but that's another reason to split them into separate PRs). I have a few more nits about comments and function naming, but overall really good.

@@ -39,18 +39,6 @@ def initialize_serializer(data_directory: str, rank: int = 0) -> serialbox.Seria
)


def read_grid(serializer: serialbox.Serializer, rank: int = 0) -> Grid:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to keep this functionality just in case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to run other test cases besides baroclinic, and even from a serialized grid

communicator = util.CubedSphereCommunicator(mpi_comm, partitioner)
# generate the grid
grid = spec.make_grid_with_data_from_namelist(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WOOHOO!

TILE_DIM = "tile"
CARTESIAN_DIM = "xyz_direction"
N_TILES = 6
RIGHT_HAND_GRID = False
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we re-combining these into global_constants? This was one of Jeremy's asks for the initial grid PR in order to keep the namespaces separate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up with a circular import, is there a reason these can't live next to MetricTerms?

@@ -7,22 +7,15 @@

import fv3core.utils.global_config as global_config
import fv3gfs.util
from fv3core.grid import MetricTerms
from fv3core.utils.global_constants import CARTESIAN_DIM, LON_OR_LAT_DIM, TILE_DIM
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment on global_constants

dims=self.area.dims,
units="m^-1",
gt4py_backend=self.area.gt4py_backend,
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch on these attributes!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are ok with having these here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I just completely neglected putting them in before, even though I should have

@@ -565,3 +579,8 @@ def __init__(self, func, origin, domain, *args, **kwargs):
@pytest.fixture()
def python_regression(pytestconfig):
return pytestconfig.getoption("python_regression")


@pytest.fixture()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, thanks for adding it!

):
"""
Args:
grid: fv3core grid object
namelist: flattened fv3gfs namelist
dp0: air pressure on interface levels, reference pressure
can be used as an approximation
column_namelist: ???
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

always happy to remove ? from docstrings

self.dycore = fv_dynamics.DynamicalCore(
comm=communicator,
grid_data=spec.grid.grid_data,
grid_data=grid_data, # grid_data,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this comment or the one below for damping data? It seems self-explanatory from the names.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch lol

@@ -17,6 +17,7 @@
)

import gt4py
import numpy
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see why we're doing this double import, but is there another way to do this? It feels really awkward

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no this was not on purpose, good catch! Also removing now that a2b is moved back

@@ -1632,9 +1633,20 @@ def compute_parallel(self, inputs, communicator):
in_state = self.state_from_inputs(inputs)
grid_generator._grid.data[:] = in_state["grid"].data[:]
grid_generator._agrid.data[:] = in_state["agrid"].data[:]
a2b = AGrid2BGridFourthOrder(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this feels very awkward here instead of keeping the edge factors inside the grids

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we're sticking with it?

Copy link
Contributor

@oelbert oelbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 extremely minor nitpicks and one question, otherwise looks good to go

fv3core/examples/standalone/runfile/acoustics.py Outdated Show resolved Hide resolved
fv3core/fv3core/grid/generation.py Outdated Show resolved Hide resolved
dims=self.area.dims,
units="m^-1",
gt4py_backend=self.area.gt4py_backend,
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I just completely neglected putting them in before, even though I should have

fv3core/fv3core/grid/generation.py Outdated Show resolved Hide resolved
@@ -376,6 +376,17 @@ def initialize_delpc_ptc(delpc: FloatField, ptc: FloatField):
ptc = 0.0


def compute_fC(stencil_factory: StencilFactory, lon: FloatFieldIJ, lat: FloatFieldIJ):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@@ -1632,9 +1633,20 @@ def compute_parallel(self, inputs, communicator):
in_state = self.state_from_inputs(inputs)
grid_generator._grid.data[:] = in_state["grid"].data[:]
grid_generator._agrid.data[:] = in_state["agrid"].data[:]
a2b = AGrid2BGridFourthOrder(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we're sticking with it?

@rheacangeo
Copy link
Contributor Author

launch jenkins

Copy link
Contributor

@oelbert oelbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

@rheacangeo
Copy link
Contributor Author

launch jenkins

@rheacangeo rheacangeo enabled auto-merge (squash) November 22, 2021 19:48
@rheacangeo
Copy link
Contributor Author

launch jenkins

1 similar comment
@rheacangeo
Copy link
Contributor Author

launch jenkins

@rheacangeo rheacangeo merged commit d234c3b into main Nov 22, 2021
@rheacangeo rheacangeo deleted the feature/use_new_grid_in_dycore branch November 22, 2021 22:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants