Skip to content

Add utility script to convert existing mpas-o ics to omega ics#562

Draft
katsmith133 wants to merge 5 commits into
E3SM-Project:mainfrom
katsmith133:add-mpaso-ic-to-omega-conv
Draft

Add utility script to convert existing mpas-o ics to omega ics#562
katsmith133 wants to merge 5 commits into
E3SM-Project:mainfrom
katsmith133:add-mpaso-ic-to-omega-conv

Conversation

@katsmith133
Copy link
Copy Markdown
Contributor

PR adds a utility script to convert existing MPAS-O initial conditions to Omega initial conditions. In general, it converts potential temperature/absolute salinity to conservative temperature/practical salinity using the GSW toolbox, it sets the velocity fields to zero, it renames variables to match expected names in Omega using mpaso_to_omega.yaml, and it computes and adds PseudoThickness.

Flags:
--input-file (required) = input path and name of MPAS-O initial condition file.
--output-file (required) = output path and name of Omega initial condition file.
--eos-type (optional, defaults to teos10) = choose between teos10 and linear to either convert to conservative temperature and practical salinity for use with TEOS-10 EOS option in Omega, or keep the same potential temperature and absolute salinity for use with the Linear EOS option in Omega. Output file is appended with teos10eos or lineareos to help keep track.
--zero-velocity-mpas-file (optional, defaults to not executing this) = option to output another initial condition file that is for MPAS-O, but with the velocity fields set to zero.

Note: mpaso_to_omega.yaml does not contain all the variable names we need to convert (eg. latCell to LatCell). For now these are still included in the new omega ic file, but with the old names. Options:

  1. I make it so that it automatically just converts all variables not in mpaso_to_omega.yaml to upper camel case
  2. Add missing variable name conversions into mpaso_to_omega.yaml that are needed for Omega
  3. Leave as is
  4. Leave out any variable names not in mpaso_to_omega.yaml

Leaving PR in draft mode for now until things are more finalized and the below checklist can be filled in.

Checklist

  • User's Guide has been updated
  • Developer's Guide has been updated
  • API documentation in the Developer's Guide (api.md) has any new or modified class, method and/or functions listed
  • Documentation has been built locally and changes look as expected
  • Testing comment in the PR documents testing used to verify the changes
  • New tests have been added to a test suite

@katsmith133 katsmith133 requested review from cbegeman and xylar April 24, 2026 21:05
Comment thread utils/omega/convert_mpaso_ic_to_omega.py
Comment thread utils/omega/convert_mpaso_ic_to_omega.py Outdated
Comment thread utils/omega/convert_mpaso_ic_to_omega.py Outdated
Comment thread utils/omega/convert_mpaso_ic_to_omega.py Outdated
Comment thread utils/omega/convert_mpaso_ic_to_omega.py Outdated
Comment thread utils/omega/convert_mpaso_ic_to_omega.py Outdated
Comment thread utils/omega/convert_mpaso_ic_to_omega.py Outdated
Copy link
Copy Markdown
Collaborator

@xylar xylar left a comment

Choose a reason for hiding this comment

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

Thanks so much for getting this going! It's pretty close to what we need.

One small development workflow detail: Make sure to use pre-commit when you're committing files so they get linted. Easy enough to lint later but it makes the commit history a little messier.

I have a few comments, largely similar to @cbegeman's.

We need to figure out how we want surface pressure handled, because that's pretty central to not just the EOS but the correct computation of the p* coordinate. That's the one piece that I think might need further discusison.

Comment thread utils/omega/convert_mpaso_ic_to_omega.py Outdated
Comment thread utils/omega/convert_mpaso_ic_to_omega.py Outdated
Comment thread utils/omega/convert_mpaso_ic_to_omega.py Outdated
Comment thread utils/omega/convert_mpaso_ic_to_omega.py Outdated
@katsmith133
Copy link
Copy Markdown
Contributor Author

@xylar and @cbegeman, thanks for the draft review!

Linting: I interpreted this statement

code or modifying existing code is to use a PEP8 style checker. When you create
a load script, we automatically install [pre-commit](https://pre-commit.com/),
a tool that helps to enforce this standard by checking your code each time you
make a commit. It will tell you about various types of problems it finds.

to mean that the pre-commit was active, but I see now that that is not the case. I will make sure to fix that in the next commit. Thanks!

PS vs AS: Thanks for that catch! Something must have switched it up in my brain 🤦‍♀️

Everything else: Will work on making those changes today!

@katsmith133 katsmith133 force-pushed the add-mpaso-ic-to-omega-conv branch from cdff9ae to 8784e5d Compare May 1, 2026 16:19
@katsmith133
Copy link
Copy Markdown
Contributor Author

katsmith133 commented May 1, 2026

Ok, made most of the changes from both of your reviews (please let me know if I didn't address them in the way you anticipated), just need to change the pressure calculation and how we want to define surface pressure, and then also add in the Earth radius scaling discussed in E3SM-Project/Omega#395 (comment). Also maybe add in some documentation, but I'll leave that for when I change it away from being a draft.

Also, linting is back in the game!

@xylar
Copy link
Copy Markdown
Collaborator

xylar commented May 1, 2026

If we want to include the sphere radius fix here, we would also need to renormalize all the Cartesian mesh coordinate (xCell, xEdge, xVertex, etc.) so they're consistent with the new radius.

@katsmith133
Copy link
Copy Markdown
Contributor Author

katsmith133 commented May 4, 2026

If we want to include the sphere radius fix here, we would also need to renormalize all the Cartesian mesh coordinate (xCell, xEdge, xVertex, etc.) so they're consistent with the new radius.

@xylar I am open to doing the work, if that is what you think is the best course of action. What is the other option if we dont do the scaling in this script? Have it in the Omega code? I can see benefits to both.

@xylar
Copy link
Copy Markdown
Collaborator

xylar commented May 4, 2026

What is the other option if we dont do the scaling in this script? Have it in the Omega code? I can see benefits to both.

That's a good question. I would personally prefer it not be something Omega tries to compensate for and just be an error if the sphere radius of an input file doesn't match the PCD value but others may very well feel differently.

Probably we should discuss this more on the Omega side. See E3SM-Project/Omega#395 (comment).

@cbegeman
Copy link
Copy Markdown
Collaborator

cbegeman commented May 4, 2026

Is it an option to just have these fields properly scaled during mesh creation in compass? I thought we were going to make a new mesh anyhow since the recent ones have ice shelf cavities.

@xylar
Copy link
Copy Markdown
Collaborator

xylar commented May 4, 2026

Is it an option to just have these fields properly scaled during mesh creation in compass? I thought we were going to make a new mesh anyhow since the recent ones have ice shelf cavities.

@vanroekel, perhaps you can weight in here but my understanding was that there wasn't any appetite for creating new Compass meshes without ice-shelf cavities and that we would go with the older E3SM initial conditions that were constructed without them. I think there's a risk of going down a rabbit hole if we try to create new meshes and initial conditions in Compass. We won't be able to use them in E3SM itself, for example, so they would only be useful for standalone testing. But also PCD isn't in Compass so we'd need to manually intervene to set the sphere radius. One manual intervention won't be too hard to do or to document but if it turns into several, which seems plausible, that's where we start needing a special Compass branch for the new mesh and we're down a rabbit hole.

It seems preferable to me to prioritize the translation script for any pre-Polaris initial conditions and Polaris itself for any new ones.

@cbegeman
Copy link
Copy Markdown
Collaborator

cbegeman commented May 4, 2026

Is it an option to just have these fields properly scaled during mesh creation in compass? I thought we were going to make a new mesh anyhow since the recent ones have ice shelf cavities.

@vanroekel, perhaps you can weight in here but my understanding was that there wasn't any appetite for creating new Compass meshes without ice-shelf cavities and that we would go with the older E3SM initial conditions that were constructed without them. I think there's a risk of going down a rabbit hole if we try to create new meshes and initial conditions in Compass. We won't be able to use them in E3SM itself, for example, so they would only be useful for standalone testing. But also PCD isn't in Compass so we'd need to manually intervene to set the sphere radius. One manual intervention won't be too hard to do or to document but if it turns into several, which seems plausible, that's where we start needing a special Compass branch for the new mesh and we're down a rabbit hole.

It seems preferable to me to prioritize the translation script for any pre-Polaris initial conditions and Polaris itself for any new ones.

Thanks for reminding me of that @xylar. No need to rehash settled discussions.

@vanroekel
Copy link
Copy Markdown

I agree with @xylar's recap and priorities.

@cbegeman
Copy link
Copy Markdown
Collaborator

cbegeman commented May 4, 2026

Maybe we can proceed without the sphere radius fix. I don't think it's crucial for initial global Omega simulations. Let me know if I'm missing something.

@xylar
Copy link
Copy Markdown
Collaborator

xylar commented May 4, 2026

Maybe we can proceed without the sphere radius fix. I don't think it's crucial for initial global Omega simulations. Let me know if I'm missing something.

Not fixing the sphere radius is one option. To me, that feels like it would make comparison between MPAS-Ocean and Omega a bit more challenging. MPAS-Ocean will use the sphere radius in the metadata in standalone mode. Omega will use the one from PCD but will have coordinate arrays that are consistent with the other.

It feels to me like the happy medium is just scaling the coordinate variables and setting the sphere_radius global attribute here in this script. I think the scaled coordinates would imply the need to change any other fields in the initial condition. They won't care about this small change. But I believe some operators (horizontal advection?) would see a slight impact. If we include the rescaling here, Omega doesn't have to worry about it but we can be sure that MPAS-Ocean and Omega will have consistent Earth radius.

@cbegeman
Copy link
Copy Markdown
Collaborator

cbegeman commented May 4, 2026

Maybe we can proceed without the sphere radius fix. I don't think it's crucial for initial global Omega simulations. Let me know if I'm missing something.

Not fixing the sphere radius is one option. To me, that feels like it would make comparison between MPAS-Ocean and Omega a bit more challenging. MPAS-Ocean will use the sphere radius in the metadata in standalone mode. Omega will use the one from PCD but will have coordinate arrays that are consistent with the other.

It feels to me like the happy medium is just scaling the coordinate variables and setting the sphere_radius global attribute here in this script. I think the scaled coordinates would imply the need to change any other fields in the initial condition. They won't care about this small change. But I believe some operators (horizontal advection?) would see a slight impact. If we include the rescaling here, Omega doesn't have to worry about it but we can be sure that MPAS-Ocean and Omega will have consistent Earth radius.

It does look like at least second derivatives rely on the actual coordinates https://github.com/E3SM-Project/Omega/blob/develop/components/omega/src/ocn/HorzOperators.h#L336

@xylar
Copy link
Copy Markdown
Collaborator

xylar commented May 4, 2026

I'd prefer that we do the scaling here as part of this tool.

I went through the mesh converter and here are the affected variables:

Scaled by R (linear distances):

  • xCell, yCell, zCell
  • xEdge, yEdge, zEdge
  • xVertex, yVertex, zVertex
  • dcEdge
  • dvEdge

Scaled by R² (areas):

  • areaCell
  • areaTriangle
  • kiteAreasOnVertex

@katsmith133
Copy link
Copy Markdown
Contributor Author

Ok, I can work on including the rescaling.

Just to be clear this would be something like this?
xCell_new = R_new * xCell_old / R_old where R_new is what is in PCD and R_old is whatever was in the input file

Or is it more complicated?

@xylar
Copy link
Copy Markdown
Collaborator

xylar commented May 4, 2026

Yep, that's exactly it.

@katsmith133
Copy link
Copy Markdown
Contributor Author

Ok, one more question. I have is so that it changes the sphere_radius global attribute for the new MPAS file it outputs, but do we want to change any of the global attributes in the new Omega file?

Options:

  1. Delete them (at least those that are config options for MPAS)
  2. Keep them in as is
  3. Convert those that we can to Omega config names using mpas_to_omega.yaml

@xylar
Copy link
Copy Markdown
Collaborator

xylar commented May 5, 2026

I think we want to remove almost all global attributes. The config options for sure. No need to try to translate them to Omega equivalents. They're just provenance.

The ones to keep are those specifically for MPAS meshes:

  • on_a_sphere
  • sphere_radius
  • is_periodic
  • x_period
  • y_period

Maybe also these (though Polaris and Omega will not use them):

  • mesh_spec
  • Conventions
  • file_id

@katsmith133
Copy link
Copy Markdown
Contributor Author

katsmith133 commented May 5, 2026

Ok, here's what I've got (this is all for the QU240 mesh):

Surface Potential Temp (MPAS) - Conservative Temp (Omega) Map
(first is from python script, second is from McDougall (2002)):
Screenshot 2026-05-05 at 11 48 24 AM
Screenshot 2026-05-05 at 12 01 07 PM

Percent Diff of Surface Absolute Salinity (Omega) - Practical Salinity (MPAS) Map
(first is from python script, second is from GSW Toolbox Github https://teos-10.github.io/GSW-R/articles/gsw.html)
Screenshot 2026-05-05 at 11 48 41 AM
Screenshot 2026-05-05 at 11 45 31 AM

Here is the header info for the Omega netcdf file:

netcdf ocean.QU.240km.151209.omega.teos10eos {
dimensions:
	NVertLayers = 60 ;
	time = 1 ;
	NEdges = 22403 ;
	NCells = 7153 ;
	NVertices = 15211 ;
	MaxCellsOnEdge = 2 ;
	MaxEdges = 6 ;
	MaxEdges2 = 12 ;
	VertexDegree = 3 ;
variables:
	double refZMid(NVertLayers) ;
		refZMid:_FillValue = NaN ;
	double NormalVelocity(time, NEdges, NVertLayers) ;
		NormalVelocity:_FillValue = NaN ;
	double LayerThickness(time, NCells, NVertLayers) ;
		LayerThickness:_FillValue = NaN ;
	double restingThickness(NCells, NVertLayers) ;
		restingThickness:_FillValue = NaN ;
	double boundaryLayerDepth(time, NCells) ;
		boundaryLayerDepth:_FillValue = NaN ;
	double refBottomDepth(NVertLayers) ;
		refBottomDepth:_FillValue = NaN ;
	double bottomDepth(NCells) ;
		bottomDepth:_FillValue = NaN ;
	double bottomDepthObserved(NCells) ;
		bottomDepthObserved:_FillValue = NaN ;
	int MaxLayerCell(NCells) ;
	double vertCoordMovementWeights(NVertLayers) ;
		vertCoordMovementWeights:_FillValue = NaN ;
	int edgeMask(NEdges, NVertLayers) ;
	double Temperature(time, NCells, NVertLayers) ;
		Temperature:_FillValue = NaN ;
		Temperature:standard_name = "sea_water_conservative_temperature" ;
		Temperature:long_name = "Conservative temperature" ;
	double Salinity(time, NCells, NVertLayers) ;
		Salinity:_FillValue = NaN ;
		Salinity:standard_name = "sea_water_absolute_salinity" ;
		Salinity:long_name = "Absolute salinity" ;
	double LatCell(NCells) ;
		LatCell:_FillValue = NaN ;
	double LonCell(NCells) ;
		LonCell:_FillValue = NaN ;
	double XCell(NCells) ;
		XCell:_FillValue = NaN ;
	double YCell(NCells) ;
		YCell:_FillValue = NaN ;
	double ZCell(NCells) ;
		ZCell:_FillValue = NaN ;
	int indexToCellID(NCells) ;
	double LatEdge(NEdges) ;
		LatEdge:_FillValue = NaN ;
	double LonEdge(NEdges) ;
		LonEdge:_FillValue = NaN ;
	double XEdge(NEdges) ;
		XEdge:_FillValue = NaN ;
	double YEdge(NEdges) ;
		YEdge:_FillValue = NaN ;
	double ZEdge(NEdges) ;
		ZEdge:_FillValue = NaN ;
	int indexToEdgeID(NEdges) ;
	double LatVertex(NVertices) ;
		LatVertex:_FillValue = NaN ;
	double LonVertex(NVertices) ;
		LonVertex:_FillValue = NaN ;
	double XVertex(NVertices) ;
		XVertex:_FillValue = NaN ;
	double YVertex(NVertices) ;
		YVertex:_FillValue = NaN ;
	double ZVertex(NVertices) ;
		ZVertex:_FillValue = NaN ;
	int indexToVertexID(NVertices) ;
	double meshDensity(NCells) ;
		meshDensity:_FillValue = NaN ;
	int CellsOnEdge(NEdges, MaxCellsOnEdge) ;
	int NEdgesOnCell(NCells) ;
	int NEdgesOnEdge(NEdges) ;
	int EdgesOnCell(NCells, MaxEdges) ;
	int EdgesOnEdge(NEdges, MaxEdges2) ;
	double weightsOnEdge(NEdges, MaxEdges2) ;
		weightsOnEdge:_FillValue = NaN ;
	double DvEdge(NEdges) ;
		DvEdge:_FillValue = NaN ;
	double DcEdge(NEdges) ;
		DcEdge:_FillValue = NaN ;
	double AngleEdge(NEdges) ;
		AngleEdge:_FillValue = NaN ;
	double AreaCell(NCells) ;
		AreaCell:_FillValue = NaN ;
	double AreaTriangle(NVertices) ;
		AreaTriangle:_FillValue = NaN ;
	int CellsOnCell(NCells, MaxEdges) ;
	int VerticesOnCell(NCells, MaxEdges) ;
	int VerticesOnEdge(NEdges, MaxCellsOnEdge) ;
	int EdgesOnVertex(NVertices, VertexDegree) ;
	int CellsOnVertex(NVertices, VertexDegree) ;
	double KiteAreasOnVertex(NVertices, VertexDegree) ;
		KiteAreasOnVertex:_FillValue = NaN ;
	double FEdge(NEdges) ;
		FEdge:_FillValue = NaN ;
	double FVertex(NVertices) ;
		FVertex:_FillValue = NaN ;
	double FCell(NCells) ;
		FCell:_FillValue = NaN ;
	double PseudoThickness(time, NCells, NVertLayers) ;
		PseudoThickness:_FillValue = NaN ;
		PseudoThickness:long_name = "pseudo-layer thickness" ;
		PseudoThickness:units = "m" ;
		PseudoThickness:description = "PseudoThickness = layerThickness / (RhoSw * SpecVol)" ;

// global attributes:
		:Conventions = "MPAS" ;
		:on_a_sphere = "YES" ;
		:sphere_radius = 6371008.7714 ;
		:is_periodic = "NO" ;
		:x_period = 0. ;
		:y_period = 0. ;
		:mesh_spec = "0.0" ;
		:file_id = "27n5kl6ryr" ;
}

And here is the header info for the new MPAS netcdf file:

netcdf ocean.QU.240km.151209.mpas {
dimensions:
	Time = UNLIMITED ; // (1 currently)
	nVertLevels = 60 ;
	nEdges = 22403 ;
	nCells = 7153 ;
	nVertices = 15211 ;
	TWO = 2 ;
	maxEdges = 6 ;
	maxEdges2 = 12 ;
	vertexDegree = 3 ;
variables:
	double refZMid(nVertLevels) ;
		refZMid:_FillValue = NaN ;
	double normalVelocity(Time, nEdges, nVertLevels) ;
		normalVelocity:_FillValue = NaN ;
	double layerThickness(Time, nCells, nVertLevels) ;
		layerThickness:_FillValue = NaN ;
	double restingThickness(nCells, nVertLevels) ;
		restingThickness:_FillValue = NaN ;
	double boundaryLayerDepth(Time, nCells) ;
		boundaryLayerDepth:_FillValue = NaN ;
	double refBottomDepth(nVertLevels) ;
		refBottomDepth:_FillValue = NaN ;
	double bottomDepth(nCells) ;
		bottomDepth:_FillValue = NaN ;
	double bottomDepthObserved(nCells) ;
		bottomDepthObserved:_FillValue = NaN ;
	int maxLevelCell(nCells) ;
	double vertCoordMovementWeights(nVertLevels) ;
		vertCoordMovementWeights:_FillValue = NaN ;
	int edgeMask(nEdges, nVertLevels) ;
	double temperature(Time, nCells, nVertLevels) ;
		temperature:_FillValue = NaN ;
	double salinity(Time, nCells, nVertLevels) ;
		salinity:_FillValue = NaN ;
	double latCell(nCells) ;
		latCell:_FillValue = NaN ;
	double lonCell(nCells) ;
		lonCell:_FillValue = NaN ;
	double xCell(nCells) ;
		xCell:_FillValue = NaN ;
	double yCell(nCells) ;
		yCell:_FillValue = NaN ;
	double zCell(nCells) ;
		zCell:_FillValue = NaN ;
	int indexToCellID(nCells) ;
	double latEdge(nEdges) ;
		latEdge:_FillValue = NaN ;
	double lonEdge(nEdges) ;
		lonEdge:_FillValue = NaN ;
	double xEdge(nEdges) ;
		xEdge:_FillValue = NaN ;
	double yEdge(nEdges) ;
		yEdge:_FillValue = NaN ;
	double zEdge(nEdges) ;
		zEdge:_FillValue = NaN ;
	int indexToEdgeID(nEdges) ;
	double latVertex(nVertices) ;
		latVertex:_FillValue = NaN ;
	double lonVertex(nVertices) ;
		lonVertex:_FillValue = NaN ;
	double xVertex(nVertices) ;
		xVertex:_FillValue = NaN ;
	double yVertex(nVertices) ;
		yVertex:_FillValue = NaN ;
	double zVertex(nVertices) ;
		zVertex:_FillValue = NaN ;
	int indexToVertexID(nVertices) ;
	double meshDensity(nCells) ;
		meshDensity:_FillValue = NaN ;
	int cellsOnEdge(nEdges, TWO) ;
	int nEdgesOnCell(nCells) ;
	int nEdgesOnEdge(nEdges) ;
	int edgesOnCell(nCells, maxEdges) ;
	int edgesOnEdge(nEdges, maxEdges2) ;
	double weightsOnEdge(nEdges, maxEdges2) ;
		weightsOnEdge:_FillValue = NaN ;
	double dvEdge(nEdges) ;
		dvEdge:_FillValue = NaN ;
	double dcEdge(nEdges) ;
		dcEdge:_FillValue = NaN ;
	double angleEdge(nEdges) ;
		angleEdge:_FillValue = NaN ;
	double areaCell(nCells) ;
		areaCell:_FillValue = NaN ;
	double areaTriangle(nVertices) ;
		areaTriangle:_FillValue = NaN ;
	int cellsOnCell(nCells, maxEdges) ;
	int verticesOnCell(nCells, maxEdges) ;
	int verticesOnEdge(nEdges, TWO) ;
	int edgesOnVertex(nVertices, vertexDegree) ;
	int cellsOnVertex(nVertices, vertexDegree) ;
	double kiteAreasOnVertex(nVertices, vertexDegree) ;
		kiteAreasOnVertex:_FillValue = NaN ;
	double fEdge(nEdges) ;
		fEdge:_FillValue = NaN ;
	double fVertex(nVertices) ;
		fVertex:_FillValue = NaN ;
	double fCell(nCells) ;
		fCell:_FillValue = NaN ;

// global attributes:
		:Conventions = "MPAS" ;
		:on_a_sphere = "YES" ;
		:sphere_radius = 6371008.7714 ;
		:is_periodic = "NO" ;
		:x_period = 0. ;
		:y_period = 0. ;
		:mesh_spec = "0.0" ;
		:file_id = "27n5kl6ryr" ;
}

Both files have zero velocities and both sphere_radius and associated mesh variables have been scaled.

Any other verification that would be helpful in making sure things are being done correctly?

ds.encoding['unlimited_dims'] = [
d for d in ds.encoding['unlimited_dims'] if d in ds.dims
]
ds.to_netcdf(output_file)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we probably want to use https://mpas-dev.github.io/MPAS-Tools/master/generated/mpas_tools.io.write_netcdf.html#mpas_tools.io.write_netcdf

The reason is that this will use the NetCDF default fill values. We should also talk about the format to use. I had thought we wanted NETCDF3_64BIT_DATA and this is what Polaris produces. But it sounds like E3SM v4 will use NETCDF4.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

For now I have changed it to use mpas tools. Perhaps we should discuss the format in the next Omega meeting?

@xylar
Copy link
Copy Markdown
Collaborator

xylar commented May 6, 2026

Your test output from the QU240 initial condition looks very promising! Thanks for those comparisons.

@katsmith133
Copy link
Copy Markdown
Contributor Author

Ok, updated to mpas tools write_netcdf and here is the output for EC30to60:

Temperature absolute difference (top = this PR, bottom = McDougall 2002):
Screenshot 2026-05-06 at 1 24 21 PM

Screenshot 2026-05-05 at 11 45 38 AM

Salinity percent different (top = this PR, bottom = GSW Toolbox):
Screenshot 2026-05-06 at 12 49 07 PM
Screenshot 2026-05-05 at 11 45 31 AM

Header info from new Omega netcdf file:

netcdf ocean.EC30to60E2r2.200908.omega.teos10eos {
dimensions:
	time = 1 ;
	NCells = 236853 ;
	NEdges = 719506 ;
	NVertices = 482371 ;
	MaxEdges = 7 ;
	MaxCellsOnEdge = 2 ;
	VertexDegree = 3 ;
	MaxEdges2 = 14 ;
	nForcingGroupsMax = 4 ;
	StrLen = 64 ;
	NVertLayers = 60 ;
	NVertLayersP1 = 61 ;
variables:
	double SSHGradientMeridional(time, NCells) ;
		SSHGradientMeridional:long_name = "Meridional gradient of SSH reconstructed at cell centers" ;
		SSHGradientMeridional:units = "m m^{-1}" ;
	double SSHGradientZonal(time, NCells) ;
		SSHGradientZonal:long_name = "Zonal gradient of SSH reconstructed at cell centers" ;
		SSHGradientZonal:units = "m m^{-1}" ;
	double AngleEdge(NEdges) ;
		AngleEdge:units = "radians" ;
		AngleEdge:long_name = "Angle the edge normal makes with local eastward direction." ;
	double AreaCell(NCells) ;
		AreaCell:units = "m^2" ;
		AreaCell:long_name = "Area of each cell in the primary grid." ;
	double AreaTriangle(NVertices) ;
		AreaTriangle:units = "m^2" ;
		AreaTriangle:long_name = "Area of each cell (triangle) in the dual grid." ;
	double atmosphericPressure(time, NCells) ;
		atmosphericPressure:units = "Pa" ;
		atmosphericPressure:long_name = "Pressure at the sea surface due to the atmosphere." ;
	double bottomDepth(NCells) ;
		bottomDepth:units = "m" ;
		bottomDepth:long_name = "Depth of the bottom of the ocean. Given as a positive distance from sea level." ;
	int CellsOnCell(NCells, MaxEdges) ;
		CellsOnCell:units = "unitless" ;
		CellsOnCell:long_name = "List of cells that neighbor each cell." ;
	int CellsOnEdge(NEdges, MaxCellsOnEdge) ;
		CellsOnEdge:units = "unitless" ;
		CellsOnEdge:long_name = "List of cells that straddle each edge." ;
	int CellsOnVertex(NVertices, VertexDegree) ;
		CellsOnVertex:units = "unitless" ;
		CellsOnVertex:long_name = "List of cells that share a vertex." ;
	double DcEdge(NEdges) ;
		DcEdge:units = "m" ;
		DcEdge:long_name = "Length of each edge, computed as the distance between cellsOnEdge." ;
	double DvEdge(NEdges) ;
		DvEdge:units = "m" ;
		DvEdge:long_name = "Length of each edge, computed as the distance between verticesOnEdge." ;
	int EdgesOnCell(NCells, MaxEdges) ;
		EdgesOnCell:units = "unitless" ;
		EdgesOnCell:long_name = "List of edges that border each cell." ;
	int EdgesOnEdge(NEdges, MaxEdges2) ;
		EdgesOnEdge:units = "unitless" ;
		EdgesOnEdge:long_name = "List of edges that border each of the cells that straddle each edge." ;
	int EdgesOnVertex(NVertices, VertexDegree) ;
		EdgesOnVertex:units = "unitless" ;
		EdgesOnVertex:long_name = "List of edges that share a vertex as an endpoint." ;
	double FCell(NCells) ;
		FCell:units = "s^{-1}" ;
		FCell:long_name = "Coriolis parameter at cell centers." ;
	double FEdge(NEdges) ;
		FEdge:units = "s^{-1}" ;
		FEdge:long_name = "Coriolis parameter at edges." ;
	double FVertex(NVertices) ;
		FVertex:units = "s^{-1}" ;
		FVertex:long_name = "Coriolis parameter at vertices." ;
	double filteredSSHGradientMeridional(time, NCells) ;
		filteredSSHGradientMeridional:units = "m m^{-1}" ;
		filteredSSHGradientMeridional:long_name = "Time filtered meridional gradient of SSH" ;
	double filteredSSHGradientZonal(time, NCells) ;
		filteredSSHGradientZonal:units = "m m^{-1}" ;
		filteredSSHGradientZonal:long_name = "Time filtered zonal gradient of SSH" ;
	char forcingGroupNames(time, nForcingGroupsMax, StrLen) ;
	char forcingGroupRestartTimes(time, nForcingGroupsMax, StrLen) ;
	int indMLD(time, NCells) ;
		indMLD:units = "unitless" ;
		indMLD:long_name = "index of model where mixed layer depth occurs (always one past)" ;
	int indexToCellID(NCells) ;
		indexToCellID:units = "unitless" ;
		indexToCellID:long_name = "List of global cell IDs." ;
	int indexToEdgeID(NEdges) ;
		indexToEdgeID:units = "unitless" ;
		indexToEdgeID:long_name = "List of global edge IDs." ;
	int indexToVertexID(NVertices) ;
		indexToVertexID:units = "unitless" ;
		indexToVertexID:long_name = "List of global vertex IDs." ;
	double KiteAreasOnVertex(NVertices, VertexDegree) ;
		KiteAreasOnVertex:units = "m^2" ;
		KiteAreasOnVertex:long_name = "Area of the portions of each dual cell that are part of each cellsOnVertex." ;
	double LatCell(NCells) ;
		LatCell:units = "radians" ;
		LatCell:long_name = "Latitude location of cell centers in radians." ;
	double LatEdge(NEdges) ;
		LatEdge:units = "radians" ;
		LatEdge:long_name = "Latitude location of edge midpoints in radians." ;
	double LatVertex(NVertices) ;
		LatVertex:units = "radians" ;
		LatVertex:long_name = "Latitude location of vertices in radians." ;
	double LayerThickness(time, NCells, NVertLayers) ;
		LayerThickness:units = "m" ;
		LayerThickness:long_name = "layer thickness" ;
	double LonCell(NCells) ;
		LonCell:units = "radians" ;
		LonCell:long_name = "Longitude location of cell centers in radians." ;
	double LonEdge(NEdges) ;
		LonEdge:units = "radians" ;
		LonEdge:long_name = "Longitude location of edge midpoints in radians." ;
	double LonVertex(NVertices) ;
		LonVertex:units = "radians" ;
		LonVertex:long_name = "Longitude location of vertices in radians." ;
	int MaxLayerCell(NCells) ;
		MaxLayerCell:units = "unitless" ;
		MaxLayerCell:long_name = "Index to the last active ocean cell in each column." ;
	double meshDensity(NCells) ;
		meshDensity:units = "unitless" ;
		meshDensity:long_name = "Value of density function used to generate a particular mesh at cell centers." ;
	int NEdgesOnCell(NCells) ;
		NEdgesOnCell:units = "unitless" ;
		NEdgesOnCell:long_name = "Number of edges that border each cell." ;
	int NEdgesOnEdge(NEdges) ;
		NEdgesOnEdge:units = "unitless" ;
		NEdgesOnEdge:long_name = "Number of edges that surround each of the cells that straddle each edge. These edges are used to reconstruct the tangential velocities." ;
	double normalBarotropicVelocity(time, NEdges) ;
		normalBarotropicVelocity:units = "m s^{-1}" ;
		normalBarotropicVelocity:long_name = "barotropic velocity, used in split-explicit time-stepping" ;
	double NormalVelocity(time, NEdges, NVertLayers) ;
		NormalVelocity:units = "m s^{-1}" ;
		NormalVelocity:long_name = "horizontal velocity, normal component to an edge" ;
	double refBottomDepth(NVertLayers) ;
		refBottomDepth:units = "m" ;
		refBottomDepth:long_name = "Reference depth of ocean for each vertical level. Used in \'z-level\' type runs." ;
	double restingThickness(NCells, NVertLayers) ;
		restingThickness:units = "m" ;
		restingThickness:long_name = "Layer thickness when the ocean is at rest, i.e. without SSH or internal perturbations." ;
	double Salinity(time, NCells, NVertLayers) ;
		Salinity:_FillValue = 9.96920996838687e+36 ;
		Salinity:long_name = "Absolute salinity" ;
		Salinity:units = "grams salt per kilogram seawater" ;
		Salinity:standard_name = "sea_water_absolute_salinity" ;
	double salinitySurfaceValue(time, NCells) ;
		salinitySurfaceValue:long_name = "salinity extrapolated to ocean surface" ;
		salinitySurfaceValue:units = "PSU" ;
	double seaIcePressure(time, NCells) ;
		seaIcePressure:units = "Pa" ;
		seaIcePressure:long_name = "Pressure at the sea surface due to sea ice." ;
	char simulationStartTime(StrLen) ;
		simulationStartTime:units = "unitless" ;
		simulationStartTime:long_name = "start time of first simulation, with format \'YYYY-MM-DD_HH:MM:SS\'" ;
	double surfaceVelocityMeridional(time, NCells) ;
		surfaceVelocityMeridional:long_name = "Meridional surface velocity reconstructed at cell centers" ;
		surfaceVelocityMeridional:units = "m s^{-1}" ;
	double surfaceVelocityZonal(time, NCells) ;
		surfaceVelocityZonal:long_name = "Zonal surface velocity reconstructed at cell centers" ;
		surfaceVelocityZonal:units = "m s^{-1}" ;
	double Temperature(time, NCells, NVertLayers) ;
		Temperature:_FillValue = 9.96920996838687e+36 ;
		Temperature:long_name = "Conservative temperature" ;
		Temperature:units = "degrees Celsius" ;
		Temperature:standard_name = "sea_water_conservative_temperature" ;
	double temperatureSurfaceValue(time, NCells) ;
		temperatureSurfaceValue:long_name = "potential temperature extrapolated to ocean surface" ;
		temperatureSurfaceValue:units = "degrees Celsius" ;
	double vertCoordMovementWeights(NVertLayers) ;
		vertCoordMovementWeights:units = "unitless" ;
		vertCoordMovementWeights:long_name = "Weights used for distribution of sea surface height perturbations through multiple vertical levels." ;
	double vertNonLocalFluxTemp(time, NCells, NVertLayersP1) ;
		vertNonLocalFluxTemp:long_name = "CVMix/KPP: nonlocal boundary layer mixing term for temperature" ;
		vertNonLocalFluxTemp:units = "nondimensional" ;
	int VerticesOnCell(NCells, MaxEdges) ;
		VerticesOnCell:units = "unitless" ;
		VerticesOnCell:long_name = "List of vertices that border each cell." ;
	int VerticesOnEdge(NEdges, MaxCellsOnEdge) ;
		VerticesOnEdge:units = "unitless" ;
		VerticesOnEdge:long_name = "List of vertices that straddle each edge." ;
	double weightsOnEdge(NEdges, MaxEdges2) ;
		weightsOnEdge:units = "unitless" ;
		weightsOnEdge:long_name = "Reconstruction weights associated with each of the edgesOnEdge, used to reconstruct the tangentialVelocity from normalVelocities on neighboring edges." ;
	double XCell(NCells) ;
		XCell:units = "unitless" ;
		XCell:long_name = "X Coordinate in cartesian space of cell centers." ;
	double XEdge(NEdges) ;
		XEdge:units = "unitless" ;
		XEdge:long_name = "X Coordinate in cartesian space of edge midpoints." ;
	double XVertex(NVertices) ;
		XVertex:units = "unitless" ;
		XVertex:long_name = "X Coordinate in cartesian space of vertices." ;
	double YCell(NCells) ;
		YCell:units = "unitless" ;
		YCell:long_name = "Y Coordinate in cartesian space of cell centers." ;
	double YEdge(NEdges) ;
		YEdge:units = "unitless" ;
		YEdge:long_name = "Y Coordinate in cartesian space of edge midpoints." ;
	double YVertex(NVertices) ;
		YVertex:units = "unitless" ;
		YVertex:long_name = "Y Coordinate in cartesian space of vertices." ;
	double ZCell(NCells) ;
		ZCell:units = "unitless" ;
		ZCell:long_name = "Z Coordinate in cartesian space of cell centers." ;
	double ZEdge(NEdges) ;
		ZEdge:units = "unitless" ;
		ZEdge:long_name = "Z Coordinate in cartesian space of edge midpoints." ;
	double ZVertex(NVertices) ;
		ZVertex:units = "unitless" ;
		ZVertex:long_name = "Z Coordinate in cartesian space of vertices." ;
	double PseudoThickness(time, NCells, NVertLayers) ;
		PseudoThickness:long_name = "pseudo-layer thickness" ;
		PseudoThickness:units = "m" ;
		PseudoThickness:description = "PseudoThickness = layerThickness / (RhoSw * SpecVol)" ;

// global attributes:
		:Conventions = "MPAS" ;
		:on_a_sphere = "YES" ;
		:sphere_radius = 6371008.7714 ;
		:is_periodic = "NO" ;
		:x_period = 0. ;
		:y_period = 0. ;
		:mesh_spec = "0.0" ;
		:file_id = "h9151zlyfl" ;
		:history = "Wed May 06 11:39:48 2026: utils/omega/convert_mpaso_ic_to_omega.py --input-file /pscratch/sd/k/katsmith/InitConditions/meshes/ocean.EC30to60E2r2.200908.nc --output-file /pscratch/sd/k/katsmith/InitConditions/meshes/ocean.EC30to60E2r2.200908.omega.nc --visualization" ;
}

Header info from new MPAS netcdf file:

netcdf ocean.EC30to60E2r2.200908.mpas {
dimensions:
	Time = UNLIMITED ; // (1 currently)
	nCells = 236853 ;
	nEdges = 719506 ;
	nVertices = 482371 ;
	maxEdges = 7 ;
	TWO = 2 ;
	vertexDegree = 3 ;
	maxEdges2 = 14 ;
	nForcingGroupsMax = 4 ;
	StrLen = 64 ;
	nVertLevels = 60 ;
	nVertLevelsP1 = 61 ;
variables:
	double SSHGradientMeridional(Time, nCells) ;
		SSHGradientMeridional:long_name = "Meridional gradient of SSH reconstructed at cell centers" ;
		SSHGradientMeridional:units = "m m^{-1}" ;
	double SSHGradientZonal(Time, nCells) ;
		SSHGradientZonal:long_name = "Zonal gradient of SSH reconstructed at cell centers" ;
		SSHGradientZonal:units = "m m^{-1}" ;
	double angleEdge(nEdges) ;
		angleEdge:units = "radians" ;
		angleEdge:long_name = "Angle the edge normal makes with local eastward direction." ;
	double areaCell(nCells) ;
		areaCell:units = "m^2" ;
		areaCell:long_name = "Area of each cell in the primary grid." ;
	double areaTriangle(nVertices) ;
		areaTriangle:units = "m^2" ;
		areaTriangle:long_name = "Area of each cell (triangle) in the dual grid." ;
	double atmosphericPressure(Time, nCells) ;
		atmosphericPressure:units = "Pa" ;
		atmosphericPressure:long_name = "Pressure at the sea surface due to the atmosphere." ;
	double bottomDepth(nCells) ;
		bottomDepth:units = "m" ;
		bottomDepth:long_name = "Depth of the bottom of the ocean. Given as a positive distance from sea level." ;
	int cellsOnCell(nCells, maxEdges) ;
		cellsOnCell:units = "unitless" ;
		cellsOnCell:long_name = "List of cells that neighbor each cell." ;
	int cellsOnEdge(nEdges, TWO) ;
		cellsOnEdge:units = "unitless" ;
		cellsOnEdge:long_name = "List of cells that straddle each edge." ;
	int cellsOnVertex(nVertices, vertexDegree) ;
		cellsOnVertex:units = "unitless" ;
		cellsOnVertex:long_name = "List of cells that share a vertex." ;
	double dcEdge(nEdges) ;
		dcEdge:units = "m" ;
		dcEdge:long_name = "Length of each edge, computed as the distance between cellsOnEdge." ;
	double dvEdge(nEdges) ;
		dvEdge:units = "m" ;
		dvEdge:long_name = "Length of each edge, computed as the distance between verticesOnEdge." ;
	int edgesOnCell(nCells, maxEdges) ;
		edgesOnCell:units = "unitless" ;
		edgesOnCell:long_name = "List of edges that border each cell." ;
	int edgesOnEdge(nEdges, maxEdges2) ;
		edgesOnEdge:units = "unitless" ;
		edgesOnEdge:long_name = "List of edges that border each of the cells that straddle each edge." ;
	int edgesOnVertex(nVertices, vertexDegree) ;
		edgesOnVertex:units = "unitless" ;
		edgesOnVertex:long_name = "List of edges that share a vertex as an endpoint." ;
	double fCell(nCells) ;
		fCell:units = "s^{-1}" ;
		fCell:long_name = "Coriolis parameter at cell centers." ;
	double fEdge(nEdges) ;
		fEdge:units = "s^{-1}" ;
		fEdge:long_name = "Coriolis parameter at edges." ;
	double fVertex(nVertices) ;
		fVertex:units = "s^{-1}" ;
		fVertex:long_name = "Coriolis parameter at vertices." ;
	double filteredSSHGradientMeridional(Time, nCells) ;
		filteredSSHGradientMeridional:units = "m m^{-1}" ;
		filteredSSHGradientMeridional:long_name = "Time filtered meridional gradient of SSH" ;
	double filteredSSHGradientZonal(Time, nCells) ;
		filteredSSHGradientZonal:units = "m m^{-1}" ;
		filteredSSHGradientZonal:long_name = "Time filtered zonal gradient of SSH" ;
	char forcingGroupNames(Time, nForcingGroupsMax, StrLen) ;
	char forcingGroupRestartTimes(Time, nForcingGroupsMax, StrLen) ;
	int indMLD(Time, nCells) ;
		indMLD:units = "unitless" ;
		indMLD:long_name = "index of model where mixed layer depth occurs (always one past)" ;
	int indexToCellID(nCells) ;
		indexToCellID:units = "unitless" ;
		indexToCellID:long_name = "List of global cell IDs." ;
	int indexToEdgeID(nEdges) ;
		indexToEdgeID:units = "unitless" ;
		indexToEdgeID:long_name = "List of global edge IDs." ;
	int indexToVertexID(nVertices) ;
		indexToVertexID:units = "unitless" ;
		indexToVertexID:long_name = "List of global vertex IDs." ;
	double kiteAreasOnVertex(nVertices, vertexDegree) ;
		kiteAreasOnVertex:units = "m^2" ;
		kiteAreasOnVertex:long_name = "Area of the portions of each dual cell that are part of each cellsOnVertex." ;
	double latCell(nCells) ;
		latCell:units = "radians" ;
		latCell:long_name = "Latitude location of cell centers in radians." ;
	double latEdge(nEdges) ;
		latEdge:units = "radians" ;
		latEdge:long_name = "Latitude location of edge midpoints in radians." ;
	double latVertex(nVertices) ;
		latVertex:units = "radians" ;
		latVertex:long_name = "Latitude location of vertices in radians." ;
	double layerThickness(Time, nCells, nVertLevels) ;
		layerThickness:units = "m" ;
		layerThickness:long_name = "layer thickness" ;
	double lonCell(nCells) ;
		lonCell:units = "radians" ;
		lonCell:long_name = "Longitude location of cell centers in radians." ;
	double lonEdge(nEdges) ;
		lonEdge:units = "radians" ;
		lonEdge:long_name = "Longitude location of edge midpoints in radians." ;
	double lonVertex(nVertices) ;
		lonVertex:units = "radians" ;
		lonVertex:long_name = "Longitude location of vertices in radians." ;
	int maxLevelCell(nCells) ;
		maxLevelCell:units = "unitless" ;
		maxLevelCell:long_name = "Index to the last active ocean cell in each column." ;
	double meshDensity(nCells) ;
		meshDensity:units = "unitless" ;
		meshDensity:long_name = "Value of density function used to generate a particular mesh at cell centers." ;
	int nEdgesOnCell(nCells) ;
		nEdgesOnCell:units = "unitless" ;
		nEdgesOnCell:long_name = "Number of edges that border each cell." ;
	int nEdgesOnEdge(nEdges) ;
		nEdgesOnEdge:units = "unitless" ;
		nEdgesOnEdge:long_name = "Number of edges that surround each of the cells that straddle each edge. These edges are used to reconstruct the tangential velocities." ;
	double normalBarotropicVelocity(Time, nEdges) ;
		normalBarotropicVelocity:units = "m s^{-1}" ;
		normalBarotropicVelocity:long_name = "barotropic velocity, used in split-explicit time-stepping" ;
	double normalVelocity(Time, nEdges, nVertLevels) ;
		normalVelocity:units = "m s^{-1}" ;
		normalVelocity:long_name = "horizontal velocity, normal component to an edge" ;
	double refBottomDepth(nVertLevels) ;
		refBottomDepth:units = "m" ;
		refBottomDepth:long_name = "Reference depth of ocean for each vertical level. Used in \'z-level\' type runs." ;
	double restingThickness(nCells, nVertLevels) ;
		restingThickness:units = "m" ;
		restingThickness:long_name = "Layer thickness when the ocean is at rest, i.e. without SSH or internal perturbations." ;
	double salinity(Time, nCells, nVertLevels) ;
		salinity:long_name = "salinity" ;
		salinity:units = "grams salt per kilogram seawater" ;
	double salinitySurfaceValue(Time, nCells) ;
		salinitySurfaceValue:long_name = "salinity extrapolated to ocean surface" ;
		salinitySurfaceValue:units = "PSU" ;
	double seaIcePressure(Time, nCells) ;
		seaIcePressure:units = "Pa" ;
		seaIcePressure:long_name = "Pressure at the sea surface due to sea ice." ;
	char simulationStartTime(StrLen) ;
		simulationStartTime:units = "unitless" ;
		simulationStartTime:long_name = "start time of first simulation, with format \'YYYY-MM-DD_HH:MM:SS\'" ;
	double surfaceVelocityMeridional(Time, nCells) ;
		surfaceVelocityMeridional:long_name = "Meridional surface velocity reconstructed at cell centers" ;
		surfaceVelocityMeridional:units = "m s^{-1}" ;
	double surfaceVelocityZonal(Time, nCells) ;
		surfaceVelocityZonal:long_name = "Zonal surface velocity reconstructed at cell centers" ;
		surfaceVelocityZonal:units = "m s^{-1}" ;
	double temperature(Time, nCells, nVertLevels) ;
		temperature:long_name = "potential temperature" ;
		temperature:units = "degrees Celsius" ;
	double temperatureSurfaceValue(Time, nCells) ;
		temperatureSurfaceValue:long_name = "potential temperature extrapolated to ocean surface" ;
		temperatureSurfaceValue:units = "degrees Celsius" ;
	double vertCoordMovementWeights(nVertLevels) ;
		vertCoordMovementWeights:units = "unitless" ;
		vertCoordMovementWeights:long_name = "Weights used for distribution of sea surface height perturbations through multiple vertical levels." ;
	double vertNonLocalFluxTemp(Time, nCells, nVertLevelsP1) ;
		vertNonLocalFluxTemp:long_name = "CVMix/KPP: nonlocal boundary layer mixing term for temperature" ;
		vertNonLocalFluxTemp:units = "nondimensional" ;
	int verticesOnCell(nCells, maxEdges) ;
		verticesOnCell:units = "unitless" ;
		verticesOnCell:long_name = "List of vertices that border each cell." ;
	int verticesOnEdge(nEdges, TWO) ;
		verticesOnEdge:units = "unitless" ;
		verticesOnEdge:long_name = "List of vertices that straddle each edge." ;
	double weightsOnEdge(nEdges, maxEdges2) ;
		weightsOnEdge:units = "unitless" ;
		weightsOnEdge:long_name = "Reconstruction weights associated with each of the edgesOnEdge, used to reconstruct the tangentialVelocity from normalVelocities on neighboring edges." ;
	double xCell(nCells) ;
		xCell:units = "unitless" ;
		xCell:long_name = "X Coordinate in cartesian space of cell centers." ;
	double xEdge(nEdges) ;
		xEdge:units = "unitless" ;
		xEdge:long_name = "X Coordinate in cartesian space of edge midpoints." ;
	double xVertex(nVertices) ;
		xVertex:units = "unitless" ;
		xVertex:long_name = "X Coordinate in cartesian space of vertices." ;
	double yCell(nCells) ;
		yCell:units = "unitless" ;
		yCell:long_name = "Y Coordinate in cartesian space of cell centers." ;
	double yEdge(nEdges) ;
		yEdge:units = "unitless" ;
		yEdge:long_name = "Y Coordinate in cartesian space of edge midpoints." ;
	double yVertex(nVertices) ;
		yVertex:units = "unitless" ;
		yVertex:long_name = "Y Coordinate in cartesian space of vertices." ;
	double zCell(nCells) ;
		zCell:units = "unitless" ;
		zCell:long_name = "Z Coordinate in cartesian space of cell centers." ;
	double zEdge(nEdges) ;
		zEdge:units = "unitless" ;
		zEdge:long_name = "Z Coordinate in cartesian space of edge midpoints." ;
	double zVertex(nVertices) ;
		zVertex:units = "unitless" ;
		zVertex:long_name = "Z Coordinate in cartesian space of vertices." ;

// global attributes:
		:Conventions = "MPAS" ;
		:on_a_sphere = "YES" ;
		:sphere_radius = 6371008.7714 ;
		:is_periodic = "NO" ;
		:x_period = 0. ;
		:y_period = 0. ;
		:mesh_spec = "0.0" ;
		:file_id = "h9151zlyfl" ;
		:history = "Wed May 06 11:33:27 2026: utils/omega/convert_mpaso_ic_to_omega.py --input-file /pscratch/sd/k/katsmith/InitConditions/meshes/ocean.EC30to60E2r2.200908.nc --output-file /pscratch/sd/k/katsmith/InitConditions/meshes/ocean.EC30to60E2r2.200908.omega.nc --visualization" ;
}

@xylar
Copy link
Copy Markdown
Collaborator

xylar commented May 6, 2026

One more variable needs conversion: restingThickness --> RefPseudoThickness. I think this will happen automatically with #573.

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.

4 participants