Skip to content

Output along ship trackes / mooring curtains#925

Draft
JanStreffing wants to merge 2 commits into
mainfrom
feature/tracks
Draft

Output along ship trackes / mooring curtains#925
JanStreffing wants to merge 2 commits into
mainfrom
feature/tracks

Conversation

@JanStreffing
Copy link
Copy Markdown
Collaborator

I wrote FESOM 2D curtain output. It works by providing a list of lat lon in a csv file. FESOM the computes the greatcircle connections. It desifies those lines and for each subsection picks the nearest neighbour fesom nodal center. Here is a first example of an track / curtained i picked with 7 coordiantes:

/home/a/a270092/esm_tools/namelists/fesom2/tracks/test_track_core2_transect.csv
# Multi-segment transect for the FESOM-2.7 ship-track / mooring curtain
# feature (io_tracks.F90, feature/tracks branch). Same 7 vertices used by
# track_densify_demo.py to visualize the densify-and-snap pipeline.
#
# Path: subpolar N. Atlantic -> Iceland -> Nordic Seas -> Fram Strait.
# At track_resolution_km = 5.0 (default), this densifies to ~639 dense
# samples that resolve to ~152 unique CORE2 mesh nodes.
#
# Format: lon, lat
-35.0,  55.0
-30.0,  57.5
-25.0,  60.0
-20.0,  62.5
-15.0,  65.0
 -8.0,  70.0
  5.0,  78.0
grafik grafik

One year of hourly test outputs at: /work/bb1469/a270092/runtime/awiesm3-develop/test_track_11/outdata/fesom

I have only tested the output via XIOS. Not without it.

@JanStreffing JanStreffing self-assigned this May 31, 2026
@JanStreffing JanStreffing added the enhancement New feature or request label May 31, 2026
Emit a 2D (depth x along-track) NetCDF curtain of any 3D node-based
FESOM field along a user-supplied polyline, at a user-supplied cadence.
Multiple tracks can run simultaneously and write to separate files.

Config (set in namelist.io's &nml_tracks block, or via XIOS XML
overrides in context_fesom.xml for XIOS-coupled runs):

  ltracks               master switch (default off)
  track_files           semicolon-separated list of CSV paths
  track_vars            semicolon-separated tracer per track (temp|salt)
  track_names           semicolon-separated names (default track1..N)
  track_resolution_km   densification spacing (default 5 km)
  track_output_freq     shared XIOS cadence ('1h', '3h', '1d', '1mo', ...)

For each track, io_tracks_register_xios runs the pipeline:
  1. parse the CSV polyline vertices on rank 0
  2. slerp each great-circle segment at track_resolution_km
  3. MPI_MINLOC nearest-neighbour: per rank scans strictly-owned mesh
     nodes; reduce picks the global owner with tie-break by lowest rank
  4. collapse consecutive duplicate gids
  5. build a sparse per-rank list (sorted by global position)
  6. register a runtime XIOS domain (track_<name>), grid
     (grid_3d_track_<name>), field (<var>_track_<name>) and a <file>
     inside the shared "fesom_tracks" file_group

io_tracks_send packs the configured tracer at owned mesh nodes and
calls xios_send_field every timestep; XIOS gates the actual write at
freq_op. Output file pattern: <var>_track_<name>.fesom_<year>-<year>.nc
with shape (time, cell, nz).

Files:
  src/io_tracks.F90        new module
  src/io_xios.F90          xios_getvar() for the six config variables
                           plus io_tracks_register_xios() call before
                           xios_close_context_definition
  src/io_meandata.F90      &nml_tracks namelist + ltracks added to
                           &nml_general
  src/fesom_module.F90     io_tracks_send() call in the time loop
@JanStreffing JanStreffing marked this pull request as draft June 1, 2026 16:50
@JanStreffing
Copy link
Copy Markdown
Collaborator Author

Putting this on draft while reworking to be in line with tripyview logic.

@JanStreffing
Copy link
Copy Markdown
Collaborator Author

Nodal works with new logic:
grafik

Replaces the snap-to-nearest-mesh-node curtain sampler with a
geometry-aware pipeline ported from tripyview/sub_transect.py. For each
polyline sub-segment we find the mesh edges it crosses, then interpolate
each crossed edge's two endpoint values via V*(1-t)+V*t at the actual
intersection parameter t. Output samples lie on the line — no more
mesh-resolution-dependent zig-zag.

Changes:
  * src/mod_tracks_geometry.F90 (new, ~750 LOC pure Fortran). Public
    transect_t + analyse_transect: bbox + polar widening, signed-distance
    line-edge intersection, alternating up/down-section path with the
    triangle's edge_cross_dxdy used directly (1:2 LEFT, 3:4 RIGHT), and
    cumulative great-circle distance. No MPI / XIOS deps.
  * src/io_tracks.F90 rewrite around the new geometry kernel:
      - rank 0 calls gather_nod/_elem/_edge to assemble the global mesh
        once at init (same primitives io_mesh_info.F90 uses);
      - rank 0 runs analyse_transect; result broadcast to all ranks;
      - per-rank lid_n1/lid_n2 strict-own lookups built via a direct g2l
        table from myList_nod2D(1:myDim_nod2D);
      - sampling kernel: weighted contributions + weight-sum buffers
        (both MPI_Allreduced); rescale-by-weight so wet/dry edges fall
        back to the surviving endpoint instead of a half-amplitude
        partial sum; NaN where neither endpoint contributes;
      - per-level wet/dry mask via mesh%nlevels_nod2D(lid)-1;
      - round-robin m -> rank assignment for XIOS write ownership.
  * src/io_meandata.F90 / src/io_xios.F90: drop the now-meaningless
    track_resolution_km knob from the namelist binding and XML override
    block (sampling cadence is set by the mesh, not the user).
  * src/fesom_module.F90: pass mesh to io_tracks_send (needed for the
    per-level wet/dry mask).

io_xios_init's partit is now intent(inout) because the new gather path
requires it; matches the existing io_mesh_info pattern.

Verified by a 1-day CORE2 smoke run across four tracks (Atlantic->Fram
plus the three Polarstern MOSAiC ice-camp windows). Crossed-edge counts
log cleanly (242 / 187 / 60 / 24); curtains have no streaky-bottom
artifact from partial-wet edges.
@JanStreffing
Copy link
Copy Markdown
Collaborator Author

Old method vs new one:
grafikgrafik
Limitation of tripyview is that we don't do great circles. Needs more points in csv to get close. Can be improved later if desired.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant