diff --git a/xios_examples/ugrid_projected/Makefile b/xios_examples/ugrid_projected/Makefile new file mode 100644 index 0000000..b5e888c --- /dev/null +++ b/xios_examples/ugrid_projected/Makefile @@ -0,0 +1,34 @@ +# Make file for the write demonstartion XIOS programme +# Targets provided our detailed below... +# +# all: (default) Build the write programme +# clean: Delete all final products and working files +# run: run the programme +# +# Environment Variables expected by this MakeFile: +# +# FC: mpif90 +# FCFLAGS: -g & include files for netcdf & xios +# LD_FLAGS: for xios, netcdf, netcdff, stfc++ +# LD_LIBRARY_PATH: for netCDF & XIOS libs +# XIOS_BINDIR: The directory for XIOS binary files + +.PHONY: all, clean, run + +all: write + +# fortran compilation +%.o: %.F90 + $(FC) $(FCFLAGS) -c $< + +# fortran linking +write: write.o + $(FC) -o write.exe write.o $(LDFLAGS) \ + && ln -fs $(XIOS_BINDIR)/xios_server.exe . + +run: + mpiexec -n 1 ./write.exe : -n 1 ./xios_server.exe + +# cleanup +clean: + rm -f *.exe *.o *.mod *.MOD *.out *.err diff --git a/xios_examples/ugrid_projected/Readme.md b/xios_examples/ugrid_projected/Readme.md new file mode 100644 index 0000000..a6764ef --- /dev/null +++ b/xios_examples/ugrid_projected/Readme.md @@ -0,0 +1,3 @@ +Demonstration of basic UGrid domain specification. + +Read mesh from file then create output mesh to add data to. diff --git a/xios_examples/ugrid_projected/__init__.py b/xios_examples/ugrid_projected/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/xios_examples/ugrid_projected/axis_check.xml b/xios_examples/ugrid_projected/axis_check.xml new file mode 100644 index 0000000..1a19131 --- /dev/null +++ b/xios_examples/ugrid_projected/axis_check.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xios_examples/ugrid_projected/iodef.xml b/xios_examples/ugrid_projected/iodef.xml new file mode 100644 index 0000000..37acd4d --- /dev/null +++ b/xios_examples/ugrid_projected/iodef.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/xios_examples/ugrid_projected/main.xml b/xios_examples/ugrid_projected/main.xml new file mode 100644 index 0000000..0bebc4b --- /dev/null +++ b/xios_examples/ugrid_projected/main.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xios_examples/ugrid_projected/planar_mesh.cdl b/xios_examples/ugrid_projected/planar_mesh.cdl new file mode 100644 index 0000000..02a9db2 --- /dev/null +++ b/xios_examples/ugrid_projected/planar_mesh.cdl @@ -0,0 +1,170 @@ +netcdf planar_mesh { +dimensions: + One = 1 ; + Two = 2 ; + Four = 4 ; + nmesh_node = 21 ; + nmesh_edge = 32 ; + nmesh_face = 12 ; +variables: + int mesh ; + mesh:cf_role = "mesh_topology" ; + mesh:geometry = "planar" ; + mesh:topology = "non_periodic" ; + mesh:coord_sys = "xyz" ; + mesh:periodic_x = "F" ; + mesh:periodic_y = "F" ; + mesh:constructor_inputs = "geometry=planar;topology=non_periodic;coord_sys=xyz;edge_cells_x=6;edge_cells_y=2;periodic_x=F;periodic_y=F;domain_size=[6.00,2.00];domain_centre=[9000.00,7000.00]" ; + mesh:max_stencil_depth = 0 ; + mesh:n_mesh_maps = 0 ; + mesh:long_name = "Topology data of 2D unstructured mesh" ; + mesh:topology_dimension = 2 ; + mesh:node_coordinates = "mesh_node_x mesh_node_y" ; + mesh:face_coordinates = "mesh_face_x mesh_face_y" ; + mesh:face_node_connectivity = "mesh_face_nodes" ; + mesh:edge_node_connectivity = "mesh_edge_nodes" ; + mesh:face_edge_connectivity = "mesh_face_edges" ; + mesh:face_face_connectivity = "mesh_face_links" ; + mesh:domain_extents = "mesh_domain_extents" ; + mesh:npanels = 1 ; + int mesh_face_nodes(nmesh_face, Four) ; + mesh_face_nodes:cf_role = "face_node_connectivity" ; + mesh_face_nodes:long_name = "Maps every quadrilateral face to its four corner nodes." ; + mesh_face_nodes:start_index = 1 ; + int mesh_face_edges(nmesh_face, Four) ; + mesh_face_edges:cf_role = "face_edge_connectivity" ; + mesh_face_edges:long_name = "Maps every quadrilateral face to its four edges." ; + mesh_face_edges:start_index = 1 ; + int mesh_face_links(nmesh_face, Four) ; + mesh_face_links:cf_role = "face_face_connectivity" ; + mesh_face_links:long_name = "Indicates which other faces neighbour each face." ; + mesh_face_links:start_index = 1 ; + mesh_face_links:_FillValue = -9999 ; + int mesh_edge_nodes(nmesh_edge, Two) ; + mesh_edge_nodes:cf_role = "edge_node_connectivity" ; + mesh_edge_nodes:long_name = "Maps every edge to the two nodes that it connects." ; + mesh_edge_nodes:start_index = 1 ; + double mesh_node_x(nmesh_node) ; + mesh_node_x:standard_name = "projection_x_coordinate" ; + mesh_node_x:long_name = "x coordinate of 2D mesh nodes." ; + mesh_node_x:units = "m" ; + double mesh_node_y(nmesh_node) ; + mesh_node_y:standard_name = "projection_y_coordinate" ; + mesh_node_y:long_name = "y coordinate of 2D mesh nodes." ; + mesh_node_y:units = "m" ; + double mesh_face_x(nmesh_face) ; + mesh_face_x:standard_name = "projection_x_coordinate" ; + mesh_face_x:long_name = "x coordinate of 2D face centres" ; + mesh_face_x:units = "m" ; + double mesh_face_y(nmesh_face) ; + mesh_face_y:standard_name = "projection_y_coordinate" ; + mesh_face_y:long_name = "y coordinate of 2D face centres" ; + mesh_face_y:units = "m" ; + double mesh_domain_extents(Four, Two) ; + double node_empty_data_container(nmesh_node) ; + node_empty_data_container:coordinates = "mesh_node_y mesh_node_x" ; + double face_empty_data_container(nmesh_face) ; + face_empty_data_container:coordinates = "mesh_face_y mesh_face_x" ; + double edge_empty_data_container(nmesh_edge) ; + +// global attributes: + :Conventions = "CF-1.6 UGRID-1.0" ; + +data: + + mesh = _ ; + + mesh_face_nodes = + 1, 2, 3, 4, + 2, 5, 6, 3, + 5, 7, 8, 6, + 7, 9, 10, 8, + 9, 11, 12, 10, + 11, 13, 14, 12, + 15, 16, 2, 1, + 16, 17, 5, 2, + 17, 18, 7, 5, + 18, 19, 9, 7, + 19, 20, 11, 9, + 20, 21, 13, 11 ; + + mesh_face_edges = + 1, 2, 3, 4, + 3, 5, 6, 7, + 6, 8, 9, 10, + 9, 11, 12, 13, + 12, 14, 15, 16, + 15, 17, 18, 19, + 20, 21, 22, 2, + 22, 23, 24, 5, + 24, 25, 26, 8, + 26, 27, 28, 11, + 28, 29, 30, 14, + 30, 31, 32, 17 ; + + mesh_face_links = + _, 7, 2, _, + 1, 8, 3, _, + 2, 9, 4, _, + 3, 10, 5, _, + 4, 11, 6, _, + 5, 12, _, _, + _, _, 8, 1, + 7, _, 9, 2, + 8, _, 10, 3, + 9, _, 11, 4, + 10, _, 12, 5, + 11, _, _, 6 ; + + mesh_edge_nodes = + 4, 1, + 1, 2, + 3, 2, + 4, 3, + 2, 5, + 6, 5, + 3, 6, + 5, 7, + 8, 7, + 6, 8, + 7, 9, + 10, 9, + 8, 10, + 9, 11, + 12, 11, + 10, 12, + 11, 13, + 14, 13, + 12, 14, + 1, 15, + 15, 16, + 2, 16, + 16, 17, + 5, 17, + 17, 18, + 7, 18, + 18, 19, + 9, 19, + 19, 20, + 11, 20, + 20, 21, + 13, 21 ; + + mesh_node_x = 8997, 8998, 8998, 8997, 8999, 8999, 9000, 9000, 9001, 9001, + 9002, 9002, 9003, 9003, 8997, 8998, 8999, 9000, 9001, 9002, 9003 ; + + mesh_node_y = 7000, 7000, 7001, 7001, 7000, 7001, 7000, 7001, 7000, 7001, + 7000, 7001, 7000, 7001, 6999, 6999, 6999, 6999, 6999, 6999, 6999 ; + + mesh_face_x = 8997.5, 8998.5, 8999.5, 9000.5, 9001.5, 9002.5, 8997.5, + 8998.5, 8999.5, 9000.5, 9001.5, 9002.5 ; + + mesh_face_y = 7000.5, 7000.5, 7000.5, 7000.5, 7000.5, 7000.5, 6999.5, + 6999.5, 6999.5, 6999.5, 6999.5, 6999.5 ; + + mesh_domain_extents = + 8997, 6999, + 9003, 6999, + 9003, 7001, + 8997, 7001 ; +} diff --git a/xios_examples/ugrid_projected/test_write_metadata.py b/xios_examples/ugrid_projected/test_write_metadata.py new file mode 100644 index 0000000..9265e88 --- /dev/null +++ b/xios_examples/ugrid_projected/test_write_metadata.py @@ -0,0 +1,53 @@ +import copy +import glob +import netCDF4 +import numpy as np +import os +import subprocess +import unittest + +import xios_examples.shared_testing as xshared + +this_path = os.path.realpath(__file__) +this_dir = os.path.dirname(this_path) + +class TestWriteMetadata(xshared._TestCase): + test_dir = this_dir + transient_inputs = ['cubedsphere_mesh.nc'] + transient_outputs = ['data_output.nc'] + executable = './write.exe' + mesh_file_cdl = 'planar_mesh.cdl' + + @classmethod + def make_a_write_test(cls, inf, nclients=1, nservers=1): + """ + this function makes a test case and returns it as a test function, + suitable to be dynamically added to a TestCase for running. + + """ + # always copy for value, don't pass by reference. + infcp = copy.copy(inf) + # expected by the fortran XIOS program's main.xml + inputfile = cls.transient_inputs[0] + outputfile = cls.transient_outputs[0] + @unittest.skipIf(os.environ.get('MVER', '') != 'XIOS3/trunk', + "skipping for XIOS2 as XIOS3 syntax used") + def test_write_metadata(self): + # create a netCDF file using nc_method + cls.make_netcdf(infcp, inputfile) + cls.run_mpi_xios(nclients=nclients, nservers=nservers) + + # load the result netCDF file + runfile = '{}/{}'.format(cls.test_dir, outputfile) + assert(os.path.exists(runfile)) + return test_write_metadata + +f = f'{this_dir}/planar_mesh.cdl' +# unique name for the test +tname = 'test_{}'.format(os.path.splitext(os.path.basename(f))[0]) +# add the test as an attribute (function) to the test class + +# !!! remove this limit on success +if os.environ.get('MVER', '').startswith('XIOS3/trunk'): + setattr(TestWriteMetadata, tname, + TestWriteMetadata.make_a_write_test(f, nclients=1)) diff --git a/xios_examples/ugrid_projected/write.F90 b/xios_examples/ugrid_projected/write.F90 new file mode 100644 index 0000000..8577f79 --- /dev/null +++ b/xios_examples/ugrid_projected/write.F90 @@ -0,0 +1,322 @@ +!----------------------------------------------------------------------------- +! (C) Crown copyright 2025 Met Office. All rights reserved. +! The file LICENCE, distributed with this code, contains details of the terms +! under which the code may be used. +!----------------------------------------------------------------------------- +!> Programme to just write data with coordinate system definition metadata. +!> +program write + use xios + use mpi + USE, INTRINSIC :: ISO_C_BINDING + use iso_fortran_env, only : output_unit + + implicit none + + integer :: comm = -1 + integer :: rank = -1 + integer :: npar = 0 + + call initialise() + call simulate() + call finalise() +contains + + subroutine initialise() + + type(xios_date) :: origin + type(xios_date) :: start + type(xios_duration) :: tstep + integer :: mpi_error + integer :: len_node, ni_node, ibegin_node + integer :: len_face, ni_face, ibegin_face + integer :: len_edge, ni_edge, ibegin_edge + integer :: fcount, ecount, fvcount, evcount + integer :: fvertex_len, evertex_len, fvertex_n, evertex_n + double precision, dimension (:), allocatable :: node_y_vals, node_x_vals, & + face_y_vals, face_x_vals, & + edge_y_vals, edge_x_vals + double precision, dimension (:,:), allocatable :: face_y_bounds, face_x_bounds, & + edge_y_bounds, edge_x_bounds, & + mesh_face_nodes_dbl, mesh_edge_nodes_dbl, & + inbfx, inbfy + integer, dimension (:,:), allocatable :: mesh_face_nodes, mesh_edge_nodes + character(len=64) :: t_origin + + origin = xios_date(2022, 2, 2, 12, 0, 0) + start = xios_date(2022, 12, 13, 12, 0, 0) + tstep = xios_hour + + ! Initialise MPI and XIOS + call MPI_INIT(mpi_error) + call xios_initialize('client', return_comm=comm) + + call MPI_Comm_rank(comm, rank, mpi_error) + call MPI_Comm_size(comm, npar, mpi_error) + + ! use the axis_check context to obtain sizing information on all arrays + ! for use in defining the main context interpretation + + print *, 'rank:', rank, ' ', "initialising axis_check" + flush(output_unit) + call xios_context_initialize('axis_check', comm) + call xios_set_time_origin(origin) + call xios_set_start_date(start) + call xios_set_timestep(tstep) + + call xios_close_context_definition() + print *, 'rank:', rank, ' ', "axis_check initialised" + flush(output_unit) + + ! fetch sizes of axes from the input file for allocate + call xios_get_domain_attr('cndata::', ni_glo=len_node, ni=ni_node, ibegin=ibegin_node) + call xios_get_domain_attr('cfdata::', ni_glo=len_face, ni=ni_face, ibegin=ibegin_face) + call xios_get_domain_attr('cedata::', ni_glo=len_edge, ni=ni_edge, ibegin=ibegin_edge) + call xios_get_axis_attr('mesh_face_nodes::[0]', n_glo=fvertex_len, n=fvertex_n) + print *, 'rank:', rank, ' ', "fvertex length: ", fvertex_len + call xios_get_axis_attr('mesh_edge_nodes::[0]', n_glo=evertex_len, n=evertex_n) + print *, 'rank:', rank, ' ', "evertex length: ", evertex_len + + allocate ( node_x_vals(ni_node) ) + allocate ( node_y_vals(ni_node) ) + allocate ( face_x_vals(ni_face) ) + allocate ( face_y_vals(ni_face) ) + allocate ( edge_x_vals(ni_edge) ) + allocate ( edge_y_vals(ni_edge) ) + allocate ( mesh_face_nodes(fvertex_len, ni_face) ) + allocate ( mesh_face_nodes_dbl(fvertex_len, ni_face) ) + allocate ( mesh_edge_nodes(evertex_len, ni_edge) ) + allocate ( mesh_edge_nodes_dbl(evertex_len, ni_edge) ) + allocate ( face_y_bounds(fvertex_len, ni_face) ) + allocate ( face_x_bounds(fvertex_len, ni_face) ) + allocate ( edge_y_bounds(evertex_len, ni_edge) ) + allocate ( edge_x_bounds(evertex_len, ni_edge) ) + print *, 'rank:', rank, ' ', 'ni_node= ', ni_node + print *, 'rank:', rank, ' ', 'ni_face= ', ni_face + print *, 'rank:', rank, ' ', 'ni_edge= ', ni_edge + print *, 'rank:', rank, ' ', 'fvertices: ', fvertex_len + flush(output_unit) + + allocate ( inbfx(fvertex_len, ni_face) ) + allocate ( inbfy(fvertex_len, ni_face) ) + ! print *, 'get bounds' + ! flush(output_unit) + ! call xios_get_domain_attr('cfdata::', bounds_lon_1d=inbfx, bounds_lat_1d=inbfy) + ! print *, 'inbfx=', inbfx + ! print *, 'inbfy=', inbfy + + print *, 'get coordinate values' + flush(output_unit) + ! fetch coordinate value arrays from the input file + call xios_get_domain_attr('cndata::', lonvalue_1d=node_x_vals, latvalue_1d=node_y_vals) + call xios_get_domain_attr('cfdata::', lonvalue_1d=face_x_vals, latvalue_1d=face_y_vals) + !call xios_get_domain_attr('cedata::', lonvalue_1d=edge_x_vals, latvalue_1d=edge_y_vals) + print *, 'rank:', rank, ' ', 'node xvals= ', node_x_vals + print *, 'rank:', rank, ' ', 'node yvals= ', node_y_vals + print *, 'rank:', rank, ' ', 'face xvals= ', face_x_vals + print *, 'rank:', rank, ' ', 'face yvals= ', face_y_vals + !print *, 'rank:', rank, ' ', 'edge xvals= ', edge_x_vals, 'edge yvals= ', edge_y_vals + flush(output_unit) + + call xios_recv_field("mesh_face_nodes", mesh_face_nodes_dbl) + mesh_face_nodes = int(mesh_face_nodes_dbl) + + print *, 'rank:', rank, ' ', 'mesh_face_nodes= ', mesh_face_nodes + flush(output_unit) + + do fvcount=1, fvertex_len + do fcount=1, ni_face + ! print *, 'rank:', rank, ' ', mesh_face_nodes(fvcount, fcount) + print *, 'rank:', rank, ' ', 'fvcount=', fvcount, 'fcount=', fcount + face_x_bounds(fvcount, fcount) = node_x_vals(mesh_face_nodes(fvcount, fcount)) + face_y_bounds(fvcount, fcount) = node_y_vals(mesh_face_nodes(fvcount, fcount)) + end do + + end do + print *, 'rank:', rank, ' ', "face_x_bounds: ", shape(face_x_bounds) + print *, 'rank:', rank, ' ', face_x_bounds + print *, 'rank:', rank, ' ', "face_y_bounds: ", shape(face_y_bounds) + print *, 'rank:', rank, ' ', face_y_bounds + + call xios_recv_field("mesh_edge_nodes", mesh_edge_nodes_dbl) + mesh_edge_nodes = int(mesh_edge_nodes_dbl) + print *, 'rank:', rank, ' ', "mesh_edge_nodes", mesh_edge_nodes + + do ecount=1, ni_edge + do evcount=1, evertex_len + edge_x_bounds(evcount, ecount) = node_x_vals(mesh_edge_nodes(evcount, ecount)) + edge_y_bounds(evcount, ecount) = node_y_vals(mesh_edge_nodes(evcount, ecount)) + end do + edge_x_vals(ecount) = edge_x_bounds(1, ecount) - 0.5 * & + (edge_x_bounds(1, ecount) - edge_x_bounds(2, ecount)) + edge_y_vals(ecount) = edge_y_bounds(1, ecount) - 0.5 * & + (edge_y_bounds(1, ecount) - edge_y_bounds(2, ecount)) + end do + print *, 'rank:', rank, ' ', "edge_x: ", shape(edge_x_vals), edge_x_vals + print *, 'rank:', rank, ' ', "edge_x_bounds: ", shape(edge_x_bounds) + print *, 'rank:', rank, ' ', edge_x_bounds(1, :) + print *, 'rank:', rank, ' ', edge_x_bounds(2, :) + print *, 'rank:', rank, ' ', "edge_y: ", shape(edge_y_vals), edge_y_vals + print *, 'rank:', rank, ' ', "edge_y_bounds: ", shape(edge_y_bounds) + print *, 'rank:', rank, ' ', edge_y_bounds(1, :) + print *, 'rank:', rank, ' ', edge_y_bounds(2, :) + + + ! finalise axis_check context, it no longer in use + ! call xios_set_current_context('axis_check') + call xios_context_finalize() + print *, 'rank:', rank, ' ', "axis check finalised successfully" + flush(output_unit) + + ! initialize the main context for interacting with the data. + print *, 'rank:', rank, ' ', "initialising main context" + flush(output_unit) + call xios_context_initialize('main', comm) + + call xios_set_time_origin(origin) + call xios_set_start_date(start) + call xios_set_timestep(tstep) + + ! define the horizontal domain and vertical axis using the input file values + + print *, 'rank:', rank, ' ', "now define domain configuration from input mesh" + flush(output_unit) + print *, 'rank:', rank, ' ', 'ibegin_node=', ibegin_node, ' ; ni_node=', ni_node + print *, 'rank:', rank, ' ', 'nodes: x, y' + print *, 'rank:', rank, ' ', node_x_vals(ibegin_node+1:(ibegin_node+ni_node)) + print *, 'rank:', rank, ' ', node_y_vals(ibegin_node+1:(ibegin_node+ni_node)) + print *, 'rank:', rank, ' ', 'faces' + print *, 'rank:', rank, ' ', face_x_vals(ibegin_face+1:(ibegin_face+ni_face)) + print *, 'rank:', rank, ' ', face_y_vals(ibegin_face+1:(ibegin_face+ni_face)) + print *, 'rank:', rank, ' ', 'face bounds' + print *, 'rank:', rank, ' ', face_x_bounds(:,ibegin_face+1:(ibegin_face+ni_face)) + print *, 'rank:', rank, ' ', face_y_bounds(:,ibegin_face+1:(ibegin_face+ni_face)) + print *, 'rank:', rank, ' ', 'edges' + print *, 'rank:', rank, ' ', edge_x_vals(ibegin_edge+1:(ibegin_edge+ni_edge)) + print *, 'rank:', rank, ' ', edge_y_vals(ibegin_edge+1:(ibegin_edge+ni_edge)) + print *, 'rank:', rank, ' ', 'edge bounds' + print *, 'rank:', rank, ' ', edge_x_bounds(:,ibegin_edge+1:(ibegin_edge+ni_edge)) + print *, 'rank:', rank, ' ', edge_y_bounds(:,ibegin_edge+1:(ibegin_edge+ni_edge)) + call xios_set_domain_attr("node_domain", ni_glo=len_node, ni=ni_node, ibegin=ibegin_node, & + nj_glo=len_node, nj=ni_node, jbegin=ibegin_node, & + latvalue_1d=node_y_vals(ibegin_node+1:(ibegin_node+ni_node)), & + lonvalue_1d=node_x_vals(ibegin_node+1:(ibegin_node+ni_node))) + call xios_set_domain_attr("face_domain", ni_glo=len_face, ni=ni_face, ibegin=ibegin_face, & + nj_glo=len_face, nj=ni_face, jbegin=ibegin_face, & + latvalue_1d=face_y_vals(ibegin_face+1:(ibegin_face+ni_face)), & + lonvalue_1d=face_x_vals(ibegin_face+1:(ibegin_face+ni_face)), & + bounds_lat_1d=face_y_bounds(:,ibegin_face+1:(ibegin_face+ni_face)), & + bounds_lon_1d=face_x_bounds(:,ibegin_face+1:(ibegin_face+ni_face))) + call xios_set_domain_attr("edge_domain", ni_glo=len_edge, ni=ni_edge, ibegin=ibegin_edge, & + nj_glo=len_edge, nj=ni_edge, jbegin=ibegin_edge, & + latvalue_1d=edge_y_vals(ibegin_edge+1:(ibegin_edge+ni_edge)), & + lonvalue_1d=edge_x_vals(ibegin_edge+1:(ibegin_edge+ni_edge)), & + bounds_lat_1d=edge_y_bounds(:,ibegin_edge+1:(ibegin_edge+ni_edge)), & + bounds_lon_1d=edge_x_bounds(:,ibegin_edge+1:(ibegin_edge+ni_edge))) + + print *, 'rank:', rank, ' ', "ready to close main context definition" + flush(output_unit) + + + call xios_close_context_definition() + print *, 'rank:', rank, ' ', "main context defined successfully" + flush(output_unit) + call xios_get_domain_attr('ndata::', lonvalue_1d=node_x_vals, latvalue_1d=node_y_vals) + print *, 'rank:', rank, ' ', "output node x = ", node_x_vals + print *, 'rank:', rank, ' ', "output node y = ", node_y_vals + flush(output_unit) + call xios_get_domain_attr('fdata::', lonvalue_1d=face_x_vals, latvalue_1d=face_y_vals) + print *, 'rank:', rank, ' ', "output face x = ", face_x_vals + print *, 'rank:', rank, ' ', "output face y = ", face_y_vals + flush(output_unit) + + deallocate (node_x_vals) + deallocate (node_y_vals) + deallocate (face_x_vals) + deallocate (face_y_vals) + deallocate (edge_x_vals) + deallocate (edge_y_vals) + deallocate (face_y_bounds) + deallocate (face_x_bounds) + deallocate (edge_y_bounds) + deallocate (edge_x_bounds) + deallocate (mesh_face_nodes_dbl) + deallocate (mesh_face_nodes) + print *, 'rank:', rank, ' ', "deallocations" + end subroutine initialise + + subroutine finalise() + + integer :: mpi_error + + ! Finalise all XIOS contexts and MPI + print *, 'rank:', rank, ' ', "finalising" + flush(output_unit) + call xios_set_current_context('main') + call xios_context_finalize() + print *, 'rank:', rank, ' ', "finalised main" + flush(output_unit) + call xios_finalize() + print *, 'rank:', rank, ' ', "finalised xios" + flush(output_unit) + call MPI_Finalize(mpi_error) + + end subroutine finalise + + subroutine simulate() + + type(xios_date) :: start + type(xios_date) :: current + integer :: ts + integer :: i + integer :: len_node + integer :: len_edge + integer :: len_face + double precision :: frtv + + ! Allocatable arrays, size is taken from input file + double precision, dimension (:), allocatable :: node_data, face_data, edge_data + + print *, 'rank:', rank, ' ', "simulation" + ! obtain sizing of the grid for the array allocation + call xios_get_domain_attr('ndata::', ni=len_node) + call xios_get_domain_attr('fdata::', ni=len_face) + call xios_get_domain_attr('edata::', ni=len_edge) + + allocate ( node_data(len_node) ) + allocate ( face_data(len_face) ) + allocate ( edge_data(len_edge) ) + print *, 'rank:', rank, ' ', 'len_node= ', len_node + print *, 'rank:', rank, ' ', 'len_face= ', len_face + print *, 'rank:', rank, ' ', 'len_edge= ', len_edge + flush(output_unit) + + do ts=1, 2 + call xios_update_calendar(ts) + call xios_get_current_date(current) + do i=1, len_node + node_data(i) = ts + end do + call xios_send_field('ndata', node_data) + + do i=1, len_face + face_data(i) = 10 * ts + end do + call xios_send_field('fdata', face_data) + + do i=1, len_edge + edge_data(i) = 100 * ts + end do + call xios_send_field('edata', edge_data) + + enddo + + deallocate (node_data) + deallocate (face_data) + deallocate (edge_data) + print *, 'rank:', rank, ' ', "fields sent, exiting simulation" + flush(output_unit) + + end subroutine simulate + +end program write diff --git a/xios_examples/ugrid_projected/xios.xml b/xios_examples/ugrid_projected/xios.xml new file mode 100644 index 0000000..9ec1df0 --- /dev/null +++ b/xios_examples/ugrid_projected/xios.xml @@ -0,0 +1,22 @@ + + + + + performance + + + 1.0 + + + + + true + + 100 + + + true + + + +