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

Domain resample #2

Merged
merged 8 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/buildTest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
# version: [XIOS/trunk@2252, XIOS2/trunk, XIOS3/trunk]
version: [XIOS/trunk@2252, XIOS2/trunk]
version: [XIOS/trunk@2252, XIOS2/trunk, XIOS3/trunk]
steps:
# Check out repository branch
- uses: actions/checkout@v4
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*__pycache__*
32 changes: 32 additions & 0 deletions xios_examples/read_axis_resample/axis_input.cdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
netcdf axis_input {
dimensions:
z = 10 ;
z_resample = 4 ;
variables:
float z(z) ;
z:long_name = "original z coordinate" ;
z:units = "1";
float z_resample(z_resample) ;
z_resample:long_name = "resampled z coordinate" ;
z_resample:units = "1";
double original_data(z) ;
original_data:long_name = "input data values" ;
original_data:units = "1";
double resample_data(z_resample) ;
resample_data:long_name = "expected resampled data values" ;
resample_data:units = "1";

// global attributes:
:title = "Input data for XIOS Axis resampling; data is a square function of the z coordinate." ;

data:

z = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ;

z_resample = 1.5, 3.5, 5.5, 7.5 ;

original_data = 1, 4, 9, 16, 25, 36, 49, 64, 81, 100 ;

resample_data = 2.25, 12.25, 30.25, 56.25 ;

}
117 changes: 27 additions & 90 deletions xios_examples/read_axis_resample/test_resample_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,108 +7,45 @@
import glob
import unittest

import xios_examples.shared_testing as xshared

this_path = os.path.realpath(__file__)
this_dir = os.path.dirname(this_path)

class TestResample(unittest.TestCase):
"""
UnitTest class to contain tests,
1 test case function per input `.cdl` file

"""
@classmethod
def setUpClass(cls):
"""
First, build the fortran code only once for this class.

"""
subprocess.run(['make', 'clean'], cwd=this_dir, check=True)
subprocess.run(['make'], cwd=this_dir, check=True)
if os.environ.get('MVER', '') == 'XIOS3/trunk':
with open(os.path.join(this_dir, 'iodef.xml'), 'r') as ioin:
iodef_in = ioin.read()
# patch in transport protocol choice for XIOS3
# needed for CI runners
in2 = '<variable_group id="parameters" >'
in3 = ('<variable_group id="parameters" >\n'
' <variable id="transport_protocol" '
'type="string" >p2p</variable>')
iodef_out = iodef_in.replace(in2, in3)
with open(os.path.join(this_dir, 'iodef.xml'), 'w') as ioout:
ioout.write(iodef_out)

def tearDown(self):
"""
After each test function,
report any errors from XIOS, then
remove the input and output netCDF files.

"""
class TestResampleAxis(xshared._TestCase):
test_dir = this_dir
transient_inputs = ['axis_input.nc']
transient_outputs = ['axis_output.nc']
rtol = 5e-04

for ef in glob.glob('{}/*.err'.format(this_dir)):
print(ef)
with open(ef, 'r') as efile:
print(efile.read(), flush=True)

os.remove('{}/axis_input.nc'.format(this_dir))
os.remove('{}/axis_output.nc'.format(this_dir))

@classmethod
def tearDownClass(cls):
"""
Finally, clean the build for this class, after all tests have run.

"""
subprocess.run(['make', 'clean'], cwd=this_dir)

# A list of input `.cdl` files where XIOS is known to produce different
# output from the expected output data
# for future investigation / ToDo
known_failures = ['test_axis_input_edge_simple_square_ten.cdl']
# this is a dict, where the name of the key is the name of the test
# to register as a known_failure (tname)
# and the value is a string explaining the failure
# this handles FAIL conditions but NOT ERROR conditions
known_failures = {'test_axis_input_edge_simple_square_ten':
('The last value, nearest the upper edge is'
' not being interpolated using a square poynomial'
' unlike the first, which is also near the edge'
' and is being calculated sensibly')}

# iterate through `.cdl` files in this test case folder
for f in glob.glob('{}/*.cdl'.format(this_dir)):
def make_a_test(inf):
"""
this function makes a test case and returns it as a function.

"""
# always copy for value, don't pass by reference.
infile = copy.copy(inf)
# expected by the fortran XIOS resample program's main.xml
outfile = 'axis_input.nc'
def test_resample(self):
# create a netCDF file from the `.cdl` input
subprocess.run(['ncgen', '-k', 'nc4', '-o', 'axis_input.nc',
infile], cwd=this_dir, check=True)
# run the compiled Fortran XIOS programme
subprocess.run(['mpiexec', '-n', '1', './resample.exe', ':',
'-n', '1', './xios_server.exe'],
cwd=this_dir, check=True)
# load the result netCDF file
rootgrp = netCDF4.Dataset('{}/axis_output.nc'.format(this_dir),
'r')
# read data from the resampled, expected & diff variables
diff = rootgrp['resampled_minus_resample'][:]
# prepare message for failure
msg = ('the expected resample data array\n {exp}\n '
'differs from the resampled data array\n {res} \n '
'with diff \n {diff}\n')
msg = msg.format(exp=rootgrp['resample_data'][:],
res=rootgrp['resampled_data'][:],
diff=diff)
if np.any(diff):
# print message for fail case,
# as expected failures do not report msg.
print(msg)
# assert that all of the `diff` varaible values are zero
self.assertTrue(not np.any(diff), msg=msg)
return test_resample
# unique name for the test
tname = 'test_{}'.format(os.path.basename(f))
tname = 'test_{}'.format(os.path.splitext(os.path.basename(f))[0])
# add the test as an attribute (function) to the test class
if tname in known_failures:
if os.environ.get('MVER', '') == 'XIOS3/trunk':
# these tests are hitting exceptions with XIOS3
# but not XIOS2, so skip for XIOS3 runner
setattr(TestResampleAxis, tname,
unittest.skip(TestResampleAxis.make_a_resample_test(f)))
elif tname in known_failures:
# set decorator @unittest.expectedFailure
setattr(TestResample, tname, unittest.expectedFailure(make_a_test(f)))
setattr(TestResampleAxis, tname,
unittest.expectedFailure(TestResampleAxis.make_a_resample_test(f)))
else:
setattr(TestResample, tname, make_a_test(f))
setattr(TestResampleAxis, tname,
TestResampleAxis.make_a_resample_test(f))
56 changes: 56 additions & 0 deletions xios_examples/read_domain_resample/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Make file for the resample demonstartion XIOS programme
# Targets provided our detailed below...
#
# all: (default) Build the resample programme
# clean: Delete all final products and working files
# run: run the programme
#
# Environment Variables expected by this MakeFile:
#
# NETCDF_LIB_DIR: the directories for the netCDF lib files
# encoded as a -L string, e.g.
# "-L/dir1 -L/dir2"
# NETCDF_INC_DIR: the directories for the netCDF include files
# encoded as a -I string, e.g.
# "-I/dir3 -I/dir4"
# (note, this is for consistency with the XIOS build process
# required for the CI build machine.
# this is not required for other directories)
#
# XIOS_INCDIR: The directory for XIOS include files
# XIOS_LIBDIR: The directory for XIOS lib files
# XIOS_BINDIR: The directory for XIOS binary files

FCFLAGS = -g -ffree-line-length-none

FC = mpif90 # compiler driver for MPI programs

# compiler flag, includes
FCFLAGS += -I$(XIOS_INCDIR) $(NETCDF_INCDIR)

# loader flags
LDFLAGS = \
-L$(XIOS_LIBDIR) \
$(NETCDF_LIBDIR) \
-lxios \
-lnetcdf \
-lnetcdff \
-lstdc++

all: resample

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

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

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

# cleanup
clean:
rm -f *.exe *.o *.mod *.MOD *.out *.err *.nc
3 changes: 3 additions & 0 deletions xios_examples/read_domain_resample/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""
Enable this folder to be a module path, for imports and test discovery.
"""
33 changes: 33 additions & 0 deletions xios_examples/read_domain_resample/axis_check.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<context>

<calendar type="Gregorian"/>

<axis_definition>
<axis id="x" unit="1" long_name="original x coordinate" />
<axis id="y" unit="1" long_name="original y coordinate" />
<axis id="x_resample" unit="1" long_name="resampled x coordinate" />
<axis id="y_resample" unit="1" long_name="resampled y coordinate" />

</axis_definition>

<grid_definition>
<grid id="oax_grid">
<axis axis_ref="x" />
<axis axis_ref="y" />
</grid>

<grid id="reax_grid">
<axis axis_ref="x_resample" />
<axis axis_ref="y_resample" />
</grid>

</grid_definition>

<file_definition type="one_file">
<file id="din" name="domain_input" output_freq="1ts" mode="read" enabled=".true.">
<field id="odatax" name="original_data" grid_ref="oax_grid" operation="instant" />
<field id="edatax" name="resample_data" grid_ref="reax_grid" operation="instant" />
</file>
</file_definition>

</context>
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
netcdf domain_input {
dimensions:
x = 5 ;
y = 5 ;
x_resample = 4 ;
y_resample = 4 ;
variables:
float x(x) ;
x:long_name = "original x coordinate" ;
x:units = "1";
float y(y) ;
y:long_name = "original y coordinate" ;
y:units = "1";
float x_resample(x_resample) ;
x_resample:long_name = "resampled x coordinate" ;
x_resample:units = "1";
float y_resample(y_resample) ;
y_resample:long_name = "resampled y coordinate" ;
y_resample:units = "1";
double original_data(y,x) ;
original_data:long_name = "input data values" ;
original_data:units = "1";
double resample_data(y_resample,x_resample) ;
resample_data:long_name = "expected resampled data values" ;
resample_data:units = "1";

// global attributes:
:title = "Input data for XIOS Domain resampling; data is a square function of the x & y coordinates; x^2+y^2." ;

data:

x = 0, 2, 4, 6, 8 ;

y = 0, 2, 4, 6, 8 ;

x_resample = 1, 3, 5, 7 ;

y_resample = 1, 3, 5, 7 ;

original_data = 0, 4, 16, 36, 64,
4, 8, 20, 40, 68,
16, 20, 32, 52, 80,
36, 40, 52, 72, 100,
64, 68, 80, 100, 128 ;

resample_data = 2, 10, 26, 50,
10, 18, 34, 58,
26, 34, 50, 74,
50, 58, 74, 98 ;

}
49 changes: 49 additions & 0 deletions xios_examples/read_domain_resample/domain_input_simple_linear.cdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
netcdf domain_input {
dimensions:
x = 5 ;
y = 5 ;
x_resample = 2 ;
y_resample = 2 ;
variables:
float x(x) ;
x:long_name = "original x coordinate" ;
x:units = "1";
float y(y) ;
y:long_name = "original y coordinate" ;
y:units = "1";
float x_resample(x_resample) ;
x_resample:long_name = "resampled x coordinate" ;
x_resample:units = "1";
float y_resample(y_resample) ;
y_resample:long_name = "resampled y coordinate" ;
y_resample:units = "1";
double original_data(y,x) ;
original_data:long_name = "input data values" ;
original_data:units = "1";
double resample_data(y_resample,x_resample) ;
resample_data:long_name = "expected resampled data values" ;
resample_data:units = "1";

// global attributes:
:title = "Input data for XIOS Domain resampling; data is a sum of the x & y coordinates; x + y ." ;

data:

x = 0, 2, 4, 6, 8 ;

y = 0, 2, 4, 6, 8 ;

x_resample = 3, 5 ;

y_resample = 3, 5 ;

original_data = 0, 2, 4, 6, 8,
2, 4, 6, 8, 10,
4, 6, 8, 10, 12,
6, 8, 10, 12, 14,
8, 10, 12, 14, 16 ;

resample_data = 6, 8,
8, 10 ;

}
Loading