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

Read4D #43

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
34 changes: 34 additions & 0 deletions xios_examples/read4D/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Make file for the read demonstartion XIOS programme
# Targets provided our detailed below...
#
# all: (default) Build the read 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: read

# fortran compilation
%.o: %.F90
$(FC) $(FCFLAGS) -c $<

# fortran linking
read: read.o
$(FC) -o read.exe read.o $(LDFLAGS) \
&& ln -fs $(XIOS_BINDIR)/xios_server.exe .

run:
mpiexec -n 1 ./read.exe : -n 1 ./xios_server.exe

# cleanup
clean:
rm -f *.exe *.o *.mod *.MOD *.out *.err
1 change: 1 addition & 0 deletions xios_examples/read4D/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

22 changes: 22 additions & 0 deletions xios_examples/read4D/domain_check.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<context>

<calendar type="Gregorian"/>


<grid_definition>
<grid id="mlev_grid">
<domain id="original_domain" type="rectilinear" >
<generate_rectilinear_domain/>
</domain>
<axis id="mlev" />
<axis id="t" />
</grid>
</grid_definition>

<file_definition type="one_file">
<file id="din" name="sample_smaller" output_freq="1ts" mode="read" enabled=".true.">
<field id="specific_humidity" name="specific_humidity" grid_ref="mlev_grid" operation="instant" read_access=".true." />
</file>
</file_definition>

</context>
8 changes: 8 additions & 0 deletions xios_examples/read4D/iodef.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<simulation>

<context id="domain_check" src="domain_check.xml"/>

<context id="xios" src="xios.xml"/>

</simulation>
119 changes: 119 additions & 0 deletions xios_examples/read4D/read.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
!-----------------------------------------------------------------------------
! (C) Crown copyright 2020 Met Office. All rights reserved.
! The file LICENCE, distributed with this code, contains details of the terms
! under which the code may be used.
!-----------------------------------------------------------------------------
!> Read 3D data on a domain + axis grid
!>
program resample
use xios
use mpi

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 :: ni_glo
integer :: nj_glo
integer :: ni
integer :: nj
integer :: ibegin
integer :: jbegin
integer :: nk_glo
integer :: nk
integer :: kbegin
integer :: nl_glo
integer :: nl
integer :: lbegin

! Datetime setup, required for XIOS & matched to input
origin = xios_date(2024, 11, 15, 0, 0, 0)
start = xios_date(2024, 11, 15, 0, 0, 0)
tstep = xios_hour * 6

! 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)

call xios_context_initialize('domain_check', comm)
call xios_set_time_origin(origin)
call xios_set_start_date(start)
call xios_set_timestep(tstep)
print *, "ready to close context domain_check"
call xios_close_context_definition()
print *, "context domain_check closed (read?)"

call xios_get_domain_attr("original_domain", &
ni_glo=ni_glo, nj_glo=nj_glo, &
ni=ni, nj=nj, &
ibegin=ibegin, jbegin=jbegin)
print *, 'original_domain: rank,ni_glo,nj_glo,ni,nj,ibegin,jbegin ',rank,ni_glo,nj_glo,ni,nj,ibegin,jbegin
call xios_get_axis_attr("mlev", n_glo=nk_glo, n=nk, begin=kbegin)
print *, 'mlev: n_glo, n, begin', nk_glo, nk, kbegin
call xios_get_axis_attr("t", n_glo=nl_glo, n=nl, begin=lbegin)
print *, 't: n_glo, n, begin', nl_glo, nl, lbegin



end subroutine initialise

subroutine finalise()

integer :: mpi_error

print *, "! Finalise all XIOS contexts and MPI"
call xios_set_current_context('domain_check')
call xios_context_finalize()
print *, "domain_check context finalised"
! call xios_set_current_context('main')
! call xios_context_finalize()
call MPI_Comm_free(comm, mpi_error)
call xios_finalize()
call MPI_Finalize(mpi_error)

end subroutine finalise

subroutine simulate()

type(xios_date) :: current
integer :: ts
integer :: lenx
integer :: leny
integer :: lenz
integer :: lent

! Allocatable arrays, size is taken from input file
double precision, dimension (:,:,:,:), allocatable :: inshdata

call xios_get_domain_attr("original_domain", ni=lenx, nj=leny)
call xios_get_axis_attr("mlev", n=lenz)
call xios_get_axis_attr("t", n=lent)


allocate ( inshdata(lent, lenz, leny, lenx) )
print *, "ready to load data from specific humidity array variable"
! Load data from the input file
call xios_recv_field('specific_humidity', inshdata)
print *, "data loaded from specific humidity array variable"
deallocate (inshdata)

end subroutine simulate

end program resample
8 changes: 8 additions & 0 deletions xios_examples/read4D/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
read4D
------

This example reads in a sample NetCDF file of 4D structured data (data payload is `missing`).
XIOS simply reads data from that file into memory.

This is designed to be extensible, enabling much larger files to be read,
across multiple client and server ranks, and performance analyses undertaken
105 changes: 105 additions & 0 deletions xios_examples/read4D/sample_smaller.cdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
netcdf sample_smaller {
dimensions:
time = 2 ;
model_level_number = 4 ;
latitude = 95 ;
longitude = 127 ;
bnds = 2 ;
variables:
float specific_humidity(time, model_level_number, latitude, longitude) ;
specific_humidity:standard_name = "specific_humidity" ;
specific_humidity:units = "kg kg-1" ;
specific_humidity:grid_mapping = "latitude_longitude" ;
specific_humidity:coordinates = "forecast_period forecast_reference_time level_height sigma surface_altitude" ;
int latitude_longitude ;
latitude_longitude:grid_mapping_name = "latitude_longitude" ;
latitude_longitude:longitude_of_prime_meridian = 0. ;
latitude_longitude:earth_radius = 6371229. ;
double time(time) ;
time:axis = "T" ;
time:units = "hours since 1970-01-01 00:00:00" ;
time:standard_name = "time" ;
time:calendar = "standard" ;
int model_level_number(model_level_number) ;
model_level_number:axis = "Z" ;
model_level_number:units = "1" ;
model_level_number:standard_name = "model_level_number" ;
model_level_number:positive = "up" ;
float latitude(latitude) ;
latitude:axis = "Y" ;
latitude:units = "degrees_north" ;
latitude:standard_name = "latitude" ;
float longitude(longitude) ;
longitude:axis = "X" ;
longitude:units = "degrees_east" ;
longitude:standard_name = "longitude" ;
double forecast_period ;
forecast_period:units = "hours" ;
forecast_period:standard_name = "forecast_period" ;
double forecast_reference_time(time) ;
forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ;
forecast_reference_time:standard_name = "forecast_reference_time" ;
forecast_reference_time:calendar = "standard" ;
float level_height(model_level_number) ;
level_height:bounds = "level_height_bnds" ;
level_height:units = "m" ;
level_height:long_name = "level_height" ;
level_height:positive = "up" ;
level_height:standard_name = "atmosphere_hybrid_height_coordinate" ;
level_height:axis = "Z" ;
level_height:formula_terms = "a: level_height b: sigma orog: surface_altitude" ;
float level_height_bnds(model_level_number, bnds) ;
float sigma(model_level_number) ;
sigma:bounds = "sigma_bnds" ;
sigma:units = "1" ;
sigma:long_name = "sigma" ;
float sigma_bnds(model_level_number, bnds) ;
float surface_altitude(latitude, longitude) ;
surface_altitude:units = "m" ;
surface_altitude:standard_name = "surface_altitude" ;

// global attributes:
:Conventions = "CF-1.7" ;
data:

time = 481008, 481014 ;

model_level_number = 0, 1, 2, 3 ;

latitude = -89.95312, -89.85938, -89.76562, -89.67188, -89.57812, -89.48438,
-89.39062, -89.29688, -89.20312, -89.10938, -89.01562, -88.92188,
-88.82812, -88.73438, -88.64062, -88.54688, -88.45312, -88.35938,
-88.26562, -88.17188, -88.07812, -87.98438, -87.89062, -87.79688,
-87.70312, -87.60938, -87.51562, -87.42188, -87.32812, -87.23438,
-87.14062, -87.04688, -86.95312, -86.85938, -86.76562, -86.67188,
-86.57812, -86.48438, -86.39062, -86.29688, -86.20312, -86.10938,
-86.01562, -85.92188, -85.82812, -85.73438, -85.64062, -85.54688,
-85.45312, -85.35938, -85.26562, -85.17188, -85.07812, -84.98438,
-84.89062, -84.79688, -84.70312, -84.60938, -84.51562, -84.42188,
-84.32812, -84.23438, -84.14062, -84.04688, -83.95312, -83.85938,
-83.76562, -83.67188, -83.57812, -83.48438, -83.39062, -83.29688,
-83.20312, -83.10938, -83.01562, -82.92188, -82.82812, -82.73438,
-82.64062, -82.54688, -82.45312, -82.35938, -82.26562, -82.17188,
-82.07812, -81.98438, -81.89062, -81.79688, -81.70312, -81.60938,
-81.51562, -81.42188, -81.32812, -81.23438, -81.14062 ;

longitude = 0.0703125, 0.2109375, 0.3515625, 0.4921875, 0.6328125,
0.7734375, 0.9140625, 1.054688, 1.195312, 1.335938, 1.476562, 1.617188,
1.757812, 1.898438, 2.039062, 2.179688, 2.320312, 2.460938, 2.601562,
2.742188, 2.882812, 3.023438, 3.164062, 3.304688, 3.445312, 3.585938,
3.726562, 3.867188, 4.007812, 4.148438, 4.289062, 4.429688, 4.570312,
4.710938, 4.851562, 4.992188, 5.132812, 5.273438, 5.414062, 5.554688,
5.695312, 5.835938, 5.976562, 6.117188, 6.257812, 6.398438, 6.539062,
6.679688, 6.820312, 6.960938, 7.101562, 7.242188, 7.382812, 7.523438,
7.664062, 7.804688, 7.945312, 8.085938, 8.226562, 8.367188, 8.507812,
8.648438, 8.789062, 8.929688, 9.070312, 9.210938, 9.351562, 9.492188,
9.632812, 9.773438, 9.914062, 10.05469, 10.19531, 10.33594, 10.47656,
10.61719, 10.75781, 10.89844, 11.03906, 11.17969, 11.32031, 11.46094,
11.60156, 11.74219, 11.88281, 12.02344, 12.16406, 12.30469, 12.44531,
12.58594, 12.72656, 12.86719, 13.00781, 13.14844, 13.28906, 13.42969,
13.57031, 13.71094, 13.85156, 13.99219, 14.13281, 14.27344, 14.41406,
14.55469, 14.69531, 14.83594, 14.97656, 15.11719, 15.25781, 15.39844,
15.53906, 15.67969, 15.82031, 15.96094, 16.10156, 16.24219, 16.38281,
16.52344, 16.66406, 16.80469, 16.94531, 17.08594, 17.22656, 17.36719,
17.50781, 17.64844, 17.78906 ;
}
41 changes: 41 additions & 0 deletions xios_examples/read4D/test_read4D.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
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 TestRead4D(xshared._TestCase):
test_dir = this_dir
transient_inputs = ['sample_smaller.nc']
transient_outputs = []
executable = './read.exe'

@unittest.skipIf(os.environ.get('MVER', '') == 'XIOS/trunk@2252',
Copy link
Collaborator

Choose a reason for hiding this comment

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

A comment here about why this is being skipped for r2252 would be useful

Copy link
Member Author

Choose a reason for hiding this comment

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

there is a bug in XIOSr2252 which is causing problems with reading dimensionality from these 4D inputs
it's still not clear all of the conditions which lead to this, certainly some reads work, but this case fails.
it's a known error, and fixed in newer XIOS2 revisions

I've added a code comment detailing the failure mode within the code, as requested

"skipping for ")
def test_read_4d(self):
inputfile = self.transient_inputs[0]
infile = inputfile.replace('.nc', '.cdl')

subprocess.run(['ncgen', '-k', 'nc4', '-o', inputfile,
infile], cwd=self.test_dir, check=True)
self.run_mpi_xios()

@classmethod
def setUpClass(cls):
if os.environ.get('MVER', '').startswith('XIOS3/trunk'):
with open(os.path.join(cls.test_dir, 'read.F90'), 'r') as ioin:
iodef_in = ioin.read()
# patch in XIOS3 domain access source code syntax
in2 = 'xios_get_domain_attr("original_domain"'
in3 = ('xios_get_domain_attr("specific_humidity::"')
iodef_out = iodef_in.replace(in2, in3)
with open(os.path.join(cls.test_dir, 'read.F90'), 'w') as ioout:
ioout.write(iodef_out)
super().setUpClass()
22 changes: 22 additions & 0 deletions xios_examples/read4D/xios.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<context>
<variable_definition>
<variable_group id="buffer">
<variable id="optimal_buffer_size" type="string">
performance
</variable>
<variable id="buffer_size_factor" type="double">
1.0
</variable>
</variable_group>

<variable_group id="parameters" >
<variable id="using_server" type="bool">true</variable>
<variable id="info_level" type="int">
100
</variable>
<variable id="print_file" type="bool">
true
</variable>
</variable_group>
</variable_definition>
</context>