Skip to content

Read surface topography from Elmer-Xios output - #12

Merged
BenjaminRodenberg merged 33 commits into
mainfrom
feature_greenland
Dec 3, 2025
Merged

BenjaminRodenberg merged 33 commits into
mainfrom
feature_greenland

Conversation

@ClemensSchannwell

@ClemensSchannwell ClemensSchannwell commented Oct 23, 2025 •

Copy link
Copy Markdown
Collaborator

In order to read the surface topography from an actual Elmer/Ice simulation, I included the option to --netcdf-mesh-unstructured. Since this surface topography uses the library XIOS to write the file, it lives on the same grid as Elmer. This simplifies the reading of the file as the surface topography comes in the same order as the Elmer mesh.
I think this feature will be helpful in the case of initialisation, because we can read the same surface topography in with which Elmer is initialised and also if we decide that we do not need to update the surface topography within a EBFM run, we can simply read it it at the start of the next simulation.
I also wanted to write some model output for easy inspection using ncview or similar, but while it works in principle, this is still in its early stage. This does not hold up further development of the EBFM-dummy but would be good to have to check whether results from EBFM are physically plausible.
I made some test with the feature_greenland branch and all previous documented running commands of the model still work as before (as far as I can tell at least).

To test the new model on levante, you can run:

mpirun -np 1 ebfm --elmer-mesh /work/bm1514/data/ebfm_dummy/mesh/MESH --netcdf-mesh-unstructured /work/bm1514/data/elmer-xios-output/restart.nc

The elmer-xios file should be accessible for all project members on levante.

@BenjaminRodenberg BenjaminRodenberg left a comment

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 merged main into this branch and cleaned up some formatting errors (will push in a moment). One part is still problematic (see comment below).

We introduced some checks in #13 and #14. These should help to have a uniform formatting and make sure all code is properly licensed. Please refer to https://github.com/wardvp/EBFM?tab=readme-ov-file#developer-notes for documentation.

Comment thread src/dummy.py Outdated
Comment thread src/dummy.py Outdated
@BenjaminRodenberg

Copy link
Copy Markdown
Collaborator

I did another merge with main to avoid that the two branches diverge too much.

Main change: src/dummy.py has been renamed to src/main.py. It's also generally recommended to install the package with pip install -e . now if you are developing and use the ebfm application for running (this will hide implementation details like src/main.py).

The last commit before the merge was 29350ad (just in case the merge causes trouble and you need to go back).

@BenjaminRodenberg BenjaminRodenberg added this to the v0.2.0 milestone Nov 20, 2025

@BenjaminRodenberg BenjaminRodenberg left a comment

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 reviewed the design of this PR and provided some general comments.

I can also take care of the implementation of (some of) these parts if you want. Please just let me know in the comments.

Comment thread src/ebfm/INIT.py Outdated
Comment thread src/ebfm/INIT.py Outdated
Comment thread src/ebfm/INIT.py Outdated
Comment thread src/ebfm/LOOP_write_to_file.py Outdated


def main(OUTFILE, io, OUT, grid, t, time, C):
def main(OUTFILE, io, OUT, grid, t, time, C, gridtype):

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.

Is it possible to use grid["input_type"] here? Introducing a new type is no problem in my opinion. Extending the interface is something I would only do if necessary.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

So this and everything that is related to changes in the save_netCDF_file(gridtype) function is something, we should probably discuss whether it belongs to this pull request. I started implementing writing, a netcdf output file, but did not finish the work. So the question now is whether, I scratch the code bits that belong to this and open a new PR once this is merged or whether I keep this "unfinished" work in there. I am thinking the former is the better option.

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 assume this is a problem originating from the general design of the code. The design is not very extensible yet.

Can you provide a link to your sketch? This helps me to better understand what you are trying to achieve with the writer and how we could update the design to make it a bot more extensible and avoid merge conflicts etc.

(maybe you noticed: I tried to follow a similar goal with #44 to decouple the configuration from the implementation in order to avoid merge conflicts and allow for easier parallel development)

Comment thread src/ebfm/LOOP_write_to_file.py Outdated
return True

def save_netCDF_file():
def save_netCDF_file(gridtype):

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.

This function is a bit problematic in my opinion due to the variables that are used from the outer scope (this makes the input/output hard to understand). Doing a big refactoring of the codebase is out of scope. But I think we could start here (since we are touching this function) by turning this function from a nested function (inside main) into an independent function on the root level of this file. I.e.:

Not

def main(...):
    ...
    elif io["output_type"] == 2:
        save_netCDF_file(gridtype=gridtype)
    ...

    def save_netCDF_file(gridtype):
        ...

but

def save_netCDF_file(gridtype, io, ...):
    ...

def main(...):
    ...
    elif io["output_type"] == 2:
        save_netCDF_file(gridtype=gridtype, io=io, ...)
    ...

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.

After some refactoring this problem still exists but it's actually not really the scope of this PR (it's already a problem of the original code). I would ignore this problem for now and do the refactoring at some later point when it fits better.

@ClemensSchannwell feel free to resolve this discussion if you agree.

Comment thread src/ebfm/LOOP_write_to_file.py Outdated
Comment thread src/main.py Outdated
Comment on lines +255 to +263
IN["h"] = data_from_elmer["h"]
grid["z"] = IN["h"][0].ravel()
# TODO add gradient field later
# IN['h'] = data_from_elmer['h']
# grid['z'] = IN['h'][0].ravel()

@BenjaminRodenberg BenjaminRodenberg Nov 25, 2025 •

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 assume we need to revert this in order to not break existing functionality?

Why did you have to comment it out in the first place? Is this something that is easy to fix or should we add a guard around this part? I.e.

if grid["grid_type"] == GridInputType.ELMERXIOS:
    logger.warning(f"Grid type {grid["grid_type"]} does not support outputting IN["h"] and grid["z"]. Ignoring these fields.")  # todo: find a fix if necessary
else:
    # usual behavior

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, we can revert this. It does actually not break anything. Since I am passing 42 from Elmer, I simply wanted to see whether it would do something more sensible if I did not update the topography (h in this case). Generally, a little further down the line it might actually not bad to also allow a flag --with-topography-update or similar.

Comment thread src/ebfm/INIT.py
grid["slope_gamma"][(grid["slope_x"] > 0) & (grid["slope_y"] == 0)] = np.pi / 2
grid["slope_gamma"][(grid["slope_x"] < 0) & (grid["slope_y"] == 0)] = -np.pi / 2
grid["slope_gamma"] = -grid["slope_gamma"]
elif grid["input_type"] is GridInputType.ELMER_XIOS:

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.

Does this work?

It's generally a good idea to make sure that at least one of the cases in this chain of if-elif-statements is entered. I always append a final else: raise Exception(f"Cannot handle unexpected {grid["input_type"]=}"). This will make sure that the program exits.

@BenjaminRodenberg

Copy link
Copy Markdown
Collaborator

I'm taking care of some of the changes suggested in my review here: #44

I will merge #44 first, then integrate the updated main into this PR. This should resolve most of my comments above.

Comment thread src/main.py Outdated
io, OUTFILE = LOOP_write_to_file.main(OUTFILE, io, OUT, grid, t, time2, C)
pass
if grid["input_type"] is GridInputType.MATLAB:
gridtype = "structured"

@BenjaminRodenberg BenjaminRodenberg Nov 25, 2025 •

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.

To make sure: gridtype = "unstructured" is not tested/supported yet? Or do you manually set gridtype = "unstructured" during development here?

Comment thread src/ebfm/INIT.py Outdated
grid["slope_gamma"][(grid["slope_x"] < 0) & (grid["slope_y"] == 0)] = -np.pi / 2
grid["slope_gamma"] = -grid["slope_gamma"]
elif grid["input_type"] is GridInputType.ELMER_XIOS:
grid = read_elmer_xios_grid(grid=grid, gridfile=args.elmer_xios_mesh)

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.

Suggested change
grid = read_elmer_xios_grid(grid=grid, gridfile=args.elmer_xios_mesh)
grid = read_elmer_xios_grid(grid=grid, gridfile=args.netcdf_mesh_unstructured)

args.elmer_xios_mesh does not exist. Can you clarify?

@BenjaminRodenberg

Copy link
Copy Markdown
Collaborator

I performed another merge of main into this PR. I will push in a moment. Note that there is a good chance that the merge broke something. This should not be dramatic but just in case: The latest known working commit of this PR is 0b14bf3.

Comment thread src/ebfm/grid.py Outdated

@BenjaminRodenberg BenjaminRodenberg left a comment

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.

Some minor comments on the design. I can take care of this as soon as you are done. Please let me know when I can take over here again.

Comment thread src/ebfm/config.py
Comment thread src/ebfm/config.py
Comment thread src/ebfm/INIT.py
Comment thread src/main.py
help="End time of the simulation in format 'DD-Mon-YYYY HH:MM', e.g., '02-Jan-1979 09:00'.",
default="2-Jan-1979 09:00",
help="End time of the simulation in format 'DD-Mon-YYYY HH:MM'",
default="2-Jan-1979 00:00",

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 did another merge of main into this PR. The default values are quite arbitrary. So I'm fine to just change the default to the value you are using if this saves you some typing.

You can also use the new options to provide different values.

@BenjaminRodenberg BenjaminRodenberg left a comment

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.

Looks good to me.

@ClemensSchannwell

Copy link
Copy Markdown
Collaborator Author

Yes, I have tested the new version this morning and see no regression. So also from my side it looks good to go!

@BenjaminRodenberg
BenjaminRodenberg merged commit b473704 into main Dec 3, 2025
6 checks passed
@BenjaminRodenberg
BenjaminRodenberg deleted the feature_greenland branch December 3, 2025 11:07
BenjaminRodenberg added a commit that referenced this pull request Jan 19, 2026
* Comment out grid assignment from IN['h']
* Fix regression of main w.r.t baseline by reverting some changes from #12 and #57.
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